Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Apress.Pro.Drupal.7.Development.3rd.Edition.Dec.2010.pdf
Скачиваний:
73
Добавлен:
14.03.2016
Размер:
12.64 Mб
Скачать

CHAPTER 23 OPTIMIZING DRUPAL

Keep as many idle PHP interpreters hanging around for as long as possible.You want to avoid churning your PHP process pool, which means to avoid constantly reaping and re-spawning PHP interpreters in response to the web traffic load of the moment. Instead it’s better to create a constant-size pool of PHP interpreters, as many as your server memory can hold, and have that pool size remain constant even if most of those processes are idle most of the time. For mod_php you’ll want to set Apache’s StartServers, MinSpareServers, MaxSpareServers, and MaxClients all equal to each other, in which case 50 is a decent starting value for an 8GB Drupal web server. This creates a constant-size preforked pool of Apache+mod_php processes. The other key Apache setting for mod_php is MaxRequestsPerChild, which ideally you will want to set at 0 so that Apache does not re-spawn child processes. But if your web server slowly leaks memory over time, and you strongly suspect mod_php is leaking memory, then you may set MaxRequestsPerChild to 10000 or more, and then dial it down until the memory leak issue is under control.

For mod_fcgid, if you’re experiencing a php-cgi segfault on every 501st PHP request (a known bug in mod_fcgid, which may have already been addressed as of this writing), then you will have to set MaxRequestsPerProcess to 500, which will force each php-cgi interpreter to re-spawn itself every 500 requests. Otherwise, set mod_fcgid MaxRequestsPerProcess to 0 unless php-cgi processes are leaking memory.

Also for mod_fcgid, set IdleTimeout and IdleScanInterval to several hours or more to avoid the overhead of re-spawning PHP interpreters on demand.

Tuning Apache

There are several configuration parameters that will help speed the execution of requests for Drupal sites running on an Apache web server. Some of the biggest improvements can be made through the following recommendations.

mod_expires

This Apache module will let Drupal send out Expires HTTP headers, caching all static files in the user’s browser for two weeks or until a newer version of a file exists. This goes for all images, CSS and JavaScript files, and other static files. The end result is reduced bandwidth and less traffic for the web server to negotiate. Drupal is preconfigured to work with mod_expires and will use it if it is available. The settings for mod_expires are found in Drupal’s .htaccess file.

# Requires mod_expires to be enabled. <IfModule mod_expires.c>

#Enable expirations. ExpiresActive On

#Cache all files for 2 weeks after access (A). ExpiresDefault A1209600

503

CHAPTER 23 OPTIMIZING DRUPAL

<FilesMatch \.php$>

#Do not allow PHP scripts to be cached unless they explicitly send cache

#headers themselves. Otherwise all scripts would have to overwrite the

#headers set by mod_expires if they want another caching behavior. This may

#fail if an error occurs early in the bootstrap process, and it may cause

#problems if a non-Drupal PHP file is installed in a subdirectory. ExpiresActive Off

</FilesMatch>

</IfModule>

We can’t let mod_expires cache PHP-generated content, because the HTML content Drupal produces is not always static. This is the reason Drupal has its own internal caching system for its HTML output (i.e., page caching).

Moving Directives from .htaccess to httpd.conf

Drupal ships with two .htaccess files: one is at the Drupal root, and the other is automatically generated after you create your directory to store uploaded files and visit Configuration -> File system to tell Drupal where the directory is. Any .htaccess files are searched for, read, and parsed on every request. In contrast, httpd.conf is read only when Apache is started. Apache directives can live in either file. If you have control of your own server, you should move the contents of the .htaccess files to the main Apache configuration file (httpd.conf) and disable .htaccess lookups within your web server root by setting

AllowOverride to None:

<Directory /> AllowOverride None

...

</Directory>

This prevents Apache from traversing up the directory tree of every request looking for the

.htaccess file to execute. Apache will then have to do less work for each request, giving it more time to serve more requests.

MPM Prefork vs. Apache MPM Worker

The choice of Apache prefork vs. worker translates into whether to use multiple Apache child processes or fewer child processes, each with multiple threads. Generally for Drupal, the better choice is Apache prefork. Here’s why:

PHP is not thread-safe, so if you’re using mod_php, then your only real choice is Apache prefork. If you’re using Fastcgi (such as mod_fastcgi or mod_fcgid), then you could use Apache MPM worker because PHP requests would be handled externally from Apache.

However, using Apache MPM worker instead of Apache MPM prefork is still not the big win that some make it out to be because there’s nothing magical about threads that makes a multithreaded application automatically faster and more scalable than a preforked multiprocess equivalent, even on multi-core systems, and this is for a few reasons:

First, it helps to demystify what threads really are to a Linux operating system: threads are mostly the same as child processes. What distinguishes a thread from a child process is that a thread has direct shared access to the memory contents of its parent process, whereas a forked child process gets a copy- on-write reference to the memory contents of its parent process. This distinction offers a slight

504

CHAPTER 23 OPTIMIZING DRUPAL

performance advantage to threads, which is then easily squandered on the often complex logistics of synchronizing shared memory access between threads.

Second, the perception that threads use significantly less memory than separate child processes is not as it seems. Using common system tools such as top and ps, it seems as though each Apache child process is using almost as much memory as its Apache parent process. In fact, most of the memory footprint of each Apache child process is the same exact memory regions used by the Apache parent process being repeatedly counted multiple times. This is because most of the memory footprint of child processes is the contents of shared libraries, which most operating systems are smart enough to load into memory once, and every additional process using those same libraries refers to the first shared copy in memory. Another memory usage consideration is child processes will share most of the memory contents of its parents unless it modifies those contents (copy-on-write).

Third, you can kill runaway Apache child processes, but you can’t kill runaway Apache threads without restarting all of Apache. From a server admin perspective, it’s easier to diagnose and address problems in a prefork Apache process pool than a threaded Apache process pool.

Of course, your mileage may vary, so benchmarking different Apache MPM configurations is still a worthy exercise.

Balancing the Apache Pool Size

When using Apache prefork, you want to size your Apache child process pool to avoid process pool churning. In other words, when the Apache server starts, you want to immediately prefork a large pool of Apache processes (as many as your web server memory can support) and have that entire pool of child processes present and waiting for requests, even if they are idle most of the time, rather than constantly incurring the performance overhead of killing and re-spawning Apache child processes in response to the traffic level of the moment.

Here are example Apache prefork settings for a Drupal web server running mod_php.

StartServers 40

MinSpareServers 40

MaxSpareServers 40

MaxClients 80

MaxRequestsPerChild 20000

This is telling Apache to start 40 child processes immediately, and always leave it at 40 processes even if traffic is low, but if traffic is really heavy, then burst up to 80 child processes. (You can raise the 40 and 80 limits according to your own server dimensions.)

You may look at this and ask, “Well, isn’t that a waste of memory to have big fat idle Apache processes hanging about?” But remember this: the goal is to have fast page delivery, and there is no prize for having a lot of free memory. “My server is slow, but look at all that free RAM!!!” If you have the memory, then use it!

Decreasing Apache Timeout

The Timeout setting in the Apache config determines how long a web client can hold a connection open without saying anything. Apache’s default Timeout is 5 minutes (300 seconds), which is far too polite. Decrease Apache’s Timeout to 20 seconds or less.

505

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]