8

I have a 64-bit server but only 256MB of RAM. So, I moved to nginx server with fast-cgi to connect to PHP. I have PHP 5.3.6 running.

The issue is that after every two or three days when I try to access any PHP page then I get server internal error. The only way around is to restart php-fpm manually. This means I should have set some wrong parameters which is causing it to choke. Below I have listed the relevant configs.

/etc/php-fpm.conf :-

include=/etc/php-fpm.d/*.conf
log_level = error
;emergency_restart_threshold = 0
;emergency_restart_interval = 0
;process_control_timeout = 0

/etc/php-fpm.d/www.conf :-

[www]
pm = dynamic
pm.max_children = 10
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 5
pm.max_requests = 500

/etc/nginx/php.conf :-

location ~ \.php {
        fastcgi_param  QUERY_STRING       $query_string;
        fastcgi_param  REQUEST_METHOD     $request_method;
        fastcgi_param  CONTENT_TYPE       $content_type;
        fastcgi_param  CONTENT_LENGTH     $content_length;

        fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
        fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        fastcgi_param  REQUEST_URI        $request_uri;
        fastcgi_param  DOCUMENT_URI       $document_uri;
        fastcgi_param  DOCUMENT_ROOT      $document_root;
        fastcgi_param  SERVER_PROTOCOL    $server_protocol;

        fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
        fastcgi_param  SERVER_SOFTWARE    nginx;

        fastcgi_param  REMOTE_ADDR        $remote_addr;
        fastcgi_param  REMOTE_PORT        $remote_port;
        fastcgi_param  SERVER_ADDR        $server_addr;
        fastcgi_param  SERVER_PORT        $server_port;
        fastcgi_param  SERVER_NAME        $server_name;

        fastcgi_pass unix:---some-location---;
}

Update 1

And I have four nginx processes running. On an average each php-fpm process takes 35MB of RAM (Virtual memory size 320MB each). I also have a MySql process running.

Update 2

I forgot to paste the logs.

php-fpm error log :-

WARNING: [pool www] seems busy (you may need to increase start_servers, or min/max_spare_servers), spawning 8 children, there are 1 idle, and 7 total children
WARNING: [pool www] server reached max_children setting (10), consider raising it
NOTICE: Terminating ...

php-fpm www.error log :-

PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 122880 bytes) in /home/webadmin/blog.applegrew.com/html/wordpress/wp-content/plugins/jetpack/class.jetpack-signature.php on line 137
PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 122880 bytes) in /home/webadmin/blog.applegrew.com/html/wordpress/wp-content/plugins/jetpack/class.jetpack-signature.php on line 137
PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 122880 bytes) in /home/webadmin/blog.applegrew.com/html/wordpress/wp-content/plugins/jetpack/class.jetpack-signature.php on line 137
AppleGrew
  • 407
  • 2
  • 6
  • 14

3 Answers3

18

An off-hand recommendation would be to lower your set values - probably cut them in half.

You have: pm.max_children = 10 If you say 35MB/process = 350MB; on a 256MB box that means either a lot of swapping or you run out of memory - neither is good.

I'd say take at least 100MB for other processes, maybe even 150MB to be safe, and then divide that number by 35MB to get your max_children. Keep all other numbers in line:

pm = dynamic
pm.max_children = 4
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 2
pm.max_requests = 500

Stop PHP-FPM and run free to get an idea of your available memory - divide by your 35MB to get your max_children.

Depending on how much memory MySQL takes, you might have to drop max_children to 3.

I do find that PHP-FPM processes share a lot of memory, do a quick experiment to determine how much is really used. Stop PHP-FPM and run free. Start PHP-FPM visit a few common pages (necessary since memory increases depending on the pages loaded), and check the total memory used, again using free - divide the difference by the number of processes. It isn't a perfect system, but I do find it to be fairly accurate (sometimes the data column in top isn't bad either).

cyberx86
  • 20,620
  • 1
  • 60
  • 80
  • I do a stop, `free` and start. I divide that free memory by 35 to get the `max_children value`. I didn't get the purpose of last para. – AppleGrew Jul 30 '11 at 08:28
  • It seems I can support only max 2.3 processes of PHP. :P Anyway I have now `max_children` to 3. – AppleGrew Jul 30 '11 at 08:56
  • a) The purpose of the 'last para' was to get a more accurate value for how much a PHP process consumes. I find that the value from ps or top doesn't always match the drop in available memory. If find the available memory, run a few PHP processes, and then remeasure available memory (instead of looking at the memory used by the processes) you can get an 'alternate' (and perhaps better) value for how much memory each process uses. b) The memory_limit parameter suggested by invarbrass is a good suggestion as well. c) Take a look at the mysqltuner.pl script, it may help with your DB config. – cyberx86 Jul 30 '11 at 19:31
  • @cyberx86, what value of `free` do you take into account? The one from '-/+ buffers/cache' row which is used for disk cache, but actually free for apps? – Roman Newaza Dec 13 '12 at 06:15
  • @RomanNewaza - yes, you want to look at the memory available to the application, so you will use the entry for 'free' under '-/+ buffers/cache'. – cyberx86 Dec 13 '12 at 21:56
  • @cyberx86 great adjustment i'm looking for someone who can help me with my php5 configuration on production server, how can i contact you? – Liad Livnat Feb 05 '14 at 10:27
  • @LiadLivnat, I appreciate the offer, however, at this time, I cannot take on additional consulting roles. You can always ask on SF for some help - but if you are looking for someone to consult, you could try asking on the meta.SF site, SE Careers, or in The Comms Room. Also, most people post a website/contact information on their profile - you can find the top users under the php-fpm tag and look at their profiles. – cyberx86 Feb 05 '14 at 13:11
6

Your php-fpm setup seems OK.

But the server you're running is somewhat resource constrained. It's obvious from the logs that PHP processes are exhausting the available memory.

Adding to the suggestions provided by cyberx86:

You can try editing the memory_limit parameter in the php.ini file (see here) (though I'm not sure it will do much good)

Given the small amount of system memory, I think you should seriously consider switching to 32-bit OS. Using an x64 OS is actually hurting you rather than being beneficial.

If you're not utilizing InnoDB storage in your MySql database, you may also consider turning off InnoDB in your my.cnf - it will save another 100 MB's of RAM.

Lowendbox has a great tutorial on how to optimize servers for low memory configuration.

invarbrass
  • 161
  • 2
  • Well my voice has gone hoarse trying to reason with my hosting company to provide 32-bit OS to me. It seems all over the net these companies provide only 64-bit. I found only one company which provides 32-bit OS but they are much more costly. – AppleGrew Jul 30 '11 at 08:39
3

A very handy command to find the memory taken by php:

ps --no-headers -o "rss,cmd" -C php5-fpm | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"M") }'

Then you divide the RAM you want dedicate to php, and you have your max_children value!

Also, you can monitor manually (you must setup the endpoint php-status) or with Nagios.

Thomas Decaux
  • 1,239
  • 11
  • 13
  • `awk: fatal: division by zero attempted` – samayo Jun 25 '14 at 17:32
  • 1
    Means you have no php5-fpm process .... you need to change the name of the process "php5-fpm" to fit your own. – Thomas Decaux Jun 26 '14 at 09:20
  • I used this command `ps --no-headers -o "rss,cmd" | grep php5-fpm | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"M") }'` Somehow -C options doesn't works. – dieend Nov 14 '14 at 08:41
  • Try to run the command separately (I mean ps --no-headers -o "rss,cmd" first etc... ) this should be easy to debug – Thomas Decaux Nov 14 '14 at 18:03