http://www.eschrade.com/page/why-you-should-not-use-htaccess-allowoverride-all-in-production
Commonly known as .htaccess, AllowOverride is a neat little feature that allows you to tweak the server’s behavior without modifying the configuration file or restarting the server. Personally, I think this is great for development purposes. It allows you to quickly test various server configurations without needing to mess with restarting the server. It helps you be more (buzzword alert!) agile.
Beyond the obvious security problems of allowing configuration modifications in a public document root there is also a performance impact. What happens with AllowOverride is that Apache will do an open() call on each parent directory from the requested file onward.
To demonstrate this I used a program called strace which checks for system calls and gives you a list of each system call that is made.
First we’ll take a look at the strace with AllowOverride set to None.
Now let’s take a look at the strace results with AllowOverride set to All.
You can clearly see the additional open() calls being made to try and
discover the .htaccess file. In this case the calls are completely
superfluous because we have nothing there. But even so we have a
significant impact on static file throughput.
AllowOverride None
AllowOverride All
The requests where AllowOverride was turned off were executed at 60% of the time of the ones where AllowOverride was turned on.
And remember, this is just the impact of file operations and does not take into account the time to reconfigure Apache during the course of these requests.
So the data would clearly show that there is a negative impact to having AllowOverride turned on in a production environment. Instead it will generally be better to take those changes in .htaccess and place them in your httpd configuration file.
[UPDATE]
In fact Mike Willbanks says you should never do it. I agree with him, but I wouldn’t make as big a stink in dev as I would in prod.
Commonly known as .htaccess, AllowOverride is a neat little feature that allows you to tweak the server’s behavior without modifying the configuration file or restarting the server. Personally, I think this is great for development purposes. It allows you to quickly test various server configurations without needing to mess with restarting the server. It helps you be more (buzzword alert!) agile.
Beyond the obvious security problems of allowing configuration modifications in a public document root there is also a performance impact. What happens with AllowOverride is that Apache will do an open() call on each parent directory from the requested file onward.
To demonstrate this I used a program called strace which checks for system calls and gives you a list of each system call that is made.
First we’ll take a look at the strace with AllowOverride set to None.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | semop(1638426, {{0, -1, SEM_UNDO}}, 1) = 0 epoll_wait(42, {{EPOLLIN, {u32=3507213864, u64=139813282633256}}}, 2, 10000) = 1 accept4(4, {sa_family=AF_INET6, sin6_port=htons(55755), inet_pton(AF_INET6, "::ffff:192.168.0.212", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28], SOCK_CLOEXEC) = 43 semop(1638426, {{0, 1, SEM_UNDO}}, 1) = 0 getsockname(43, {sa_family=AF_INET6, sin6_port=htons(80), inet_pton(AF_INET6, "::ffff:192.168.0.212", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0 fcntl(43, F_GETFL) = 0x2 (flags O_RDWR) fcntl(43, F_SETFL, O_RDWR|O_NONBLOCK) = 0 read(43, "GET /test.txt HTTP/1.0\r\nHost: ma"..., 8000) = 87 gettimeofday({1361542861, 683952}, NULL) = 0 stat("/var/www/magento.loc/test.txt", {st_mode=S_IFREG|0644, st_size=12, ...}) = 0 open("/var/www/magento.loc/test.txt", O_RDONLY|O_CLOEXEC) = 44 fcntl(44, F_GETFD) = 0x1 (flags FD_CLOEXEC) fcntl(44, F_SETFD, FD_CLOEXEC) = 0 mmap(NULL, 12, PROT_READ, MAP_SHARED, 44, 0) = 0x7f28cfc74000 writev(43, [{"HTTP/1.1 200 OK\r\nDate: Fri, 22 F"..., 267}, {"hello world\n", 12}], 2) = 279 munmap(0x7f28cfc74000, 12) = 0 write(12, "192.168.0.212 - - [22/Feb/2013:0"..., 79) = 79 shutdown(43, 1 /* send */) = 0 poll([{fd=43, events=POLLIN}], 1, 2000) = 1 ([{fd=43, revents=POLLIN|POLLHUP}]) read(43, "", 512) = 0 close(43) = 0 read(6, 0x7fff79e2d7cf, 1) = -1 EAGAIN (Resource temporarily unavailable) close(44) = 0 semop(1638426, {{0, -1, SEM_UNDO}}, 1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | semop(1736730, {{0, -1, SEM_UNDO}}, 1) = 0 epoll_wait(42, {{EPOLLIN, {u32=3392874024, u64=140410168747560}}}, 2, 10000) = 1 accept4(4, {sa_family=AF_INET6, sin6_port=htons(55795), inet_pton(AF_INET6, "::ffff:192.168.0.212", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28], SOCK_CLOEXEC) = 43 semop(1736730, {{0, 1, SEM_UNDO}}, 1) = 0 getsockname(43, {sa_family=AF_INET6, sin6_port=htons(80), inet_pton(AF_INET6, "::ffff:192.168.0.212", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0 fcntl(43, F_GETFL) = 0x2 (flags O_RDWR) fcntl(43, F_SETFL, O_RDWR|O_NONBLOCK) = 0 read(43, "GET /test.txt HTTP/1.0\r\nHost: ma"..., 8000) = 87 gettimeofday({1361543373, 140117}, NULL) = 0 stat("/var/www/magento.loc/test.txt", {st_mode=S_IFREG|0644, st_size=12, ...}) = 0 open("/var/www/.htaccess", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) open("/var/www/magento.loc/.htaccess", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) open("/var/www/magento.loc/test.txt/.htaccess", O_RDONLY|O_CLOEXEC) = -1 ENOTDIR (Not a directory) open("/var/www/magento.loc/test.txt", O_RDONLY|O_CLOEXEC) = 44 fcntl(44, F_GETFD) = 0x1 (flags FD_CLOEXEC) fcntl(44, F_SETFD, FD_CLOEXEC) = 0 mmap(NULL, 12, PROT_READ, MAP_SHARED, 44, 0) = 0x7fb3c8bf9000 writev(43, [{"HTTP/1.1 200 OK\r\nDate: Fri, 22 F"..., 267}, {"hello world\n", 12}], 2) = 279 munmap(0x7fb3c8bf9000, 12) = 0 write(12, "192.168.0.212 - - [22/Feb/2013:0"..., 79) = 79 shutdown(43, 1 /* send */) = 0 poll([{fd=43, events=POLLIN}], 1, 2000) = 1 ([{fd=43, revents=POLLIN|POLLHUP}]) read(43, "", 512) = 0 close(43) = 0 read(6, 0x7fff95abfc1f, 1) = -1 EAGAIN (Resource temporarily unavailable) close(44) = 0 semop(1736730, {{0, -1, SEM_UNDO}}, 1 |
AllowOverride None
1 2 3 4 5 6 7 8 9 10 11 | Concurrency Level: 10 Time taken for tests: 2.441 seconds Complete requests: 10000 Failed requests: 0 Write errors: 0 Total transferred: 2790279 bytes HTML transferred: 120012 bytes Requests per second: 4096.02 [#/sec] (mean) Time per request: 2.441 [ms] (mean) Time per request: 0.244 [ms] (mean, across all concurrent requests) Transfer rate: 1116.12 [Kbytes/sec] received |
1 2 3 4 5 6 7 8 9 10 11 | Concurrency Level: 10 Time taken for tests: 3.922 seconds Complete requests: 10000 Failed requests: 0 Write errors: 0 Total transferred: 2790558 bytes HTML transferred: 120024 bytes Requests per second: 2549.42 [#/sec] (mean) Time per request: 3.922 [ms] (mean) Time per request: 0.392 [ms] (mean, across all concurrent requests) Transfer rate: 694.76 [Kbytes/sec] received |
And remember, this is just the impact of file operations and does not take into account the time to reconfigure Apache during the course of these requests.
So the data would clearly show that there is a negative impact to having AllowOverride turned on in a production environment. Instead it will generally be better to take those changes in .htaccess and place them in your httpd configuration file.
[UPDATE]
In fact Mike Willbanks says you should never do it. I agree with him, but I wouldn’t make as big a stink in dev as I would in prod.
No comments:
Post a Comment