¿Qué hay de malo en mi configuración de php-fpm?

8

Tengo un servidor de 64 bits pero solo 256 MB de RAM. Entonces, me mudé al servidor nginx con fast-cgi para conectarme a PHP. Tengo PHP 5.3.6 ejecutándose.

El problema es que después de cada dos o tres días, cuando intento acceder a cualquier página PHP, aparece un error interno del servidor. La única forma de hacerlo es reiniciar php-fpm manualmente. Esto significa que debería haber establecido algunos parámetros incorrectos que están causando que se ahogue. A continuación he enumerado las configuraciones relevantes.

/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---;
}

Actualización 1

Y tengo cuatro procesos nginx ejecutándose. En promedio, cada proceso php-fpm requiere 35 MB de RAM (tamaño de memoria virtual de 320 MB cada uno). También tengo un proceso MySql en ejecución.

Actualización 2

Olvidé pegar los registros.

registro de errores de php-fpm: -

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
fuente

Respuestas:

17

Una recomendación no convencional sería reducir los valores establecidos, probablemente reducirlos a la mitad.

Tiene: pm.max_children = 10 Si dice 35MB / proceso = 350MB; en un cuadro de 256 MB que significa mucho intercambio o se queda sin memoria, ninguno de los dos es bueno.

Yo diría que tome al menos 100 MB para otros procesos, tal vez incluso 150 MB para estar seguro, y luego divida ese número por 35 MB para obtener sus max_children. Mantenga todos los otros números en línea:

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

Detenga PHP-FPM y ejecútelo freepara tener una idea de su memoria disponible: divida por sus 35 MB para obtener sus max_children.

Dependiendo de la cantidad de memoria que tome MySQL, es posible que deba reducir max_children a 3.

Encuentro que los procesos PHP-FPM comparten mucha memoria, hago un experimento rápido para determinar cuánto se usa realmente. Detenga PHP-FPM y ejecútelo free. Inicie PHP-FPM, visite algunas páginas comunes (necesario ya que la memoria aumenta según las páginas cargadas) y verifique la memoria total utilizada, nuevamente usando free: divida la diferencia entre el número de procesos. No es un sistema perfecto, pero creo que es bastante preciso (a veces la columna de datos en la parte superior tampoco está mal).

cyberx86
fuente
Hago una parada freey empiezo. Divido esa memoria libre por 35 para obtener el max_children value. No entendí el propósito del último párrafo.
AppleGrew
Parece que solo puedo soportar un máximo de 2.3 procesos de PHP. : P De todos modos, ahora tengo max_childrenque 3.
AppleGrew
a) El propósito del 'último para' era obtener un valor más preciso de cuánto consume un proceso PHP. Encuentro que el valor de ps o top no siempre coincide con la caída en la memoria disponible. Si encuentra la memoria disponible, ejecute algunos procesos PHP y luego vuelva a medir la memoria disponible (en lugar de mirar la memoria utilizada por los procesos) puede obtener un valor 'alternativo' (y quizás mejor) para la cantidad de memoria que utiliza cada proceso. b) El parámetro memory_limit sugerido por invarbrass también es una buena sugerencia. c) Eche un vistazo al script mysqltuner.pl, puede ayudarlo con la configuración de su base de datos.
cyberx86
@ cyberx86, ¿qué valor freetiene en cuenta? ¿El de la fila '- / + buffers / cache' que se usa para caché de disco, pero en realidad es gratis para aplicaciones?
Roman Newaza
@RomanNewaza: sí, desea ver la memoria disponible para la aplicación, por lo que utilizará la entrada 'gratis' en '- / + buffers / cache'.
cyberx86
6

Su configuración de php-fpm parece estar bien.

Pero el servidor que está ejecutando tiene limitaciones de recursos. Es obvio de los registros que los procesos PHP están agotando la memoria disponible.

Agregando a las sugerencias proporcionadas por cyberx86:

Puede intentar editar el parámetro memory_limit en el archivo php.ini (ver aquí ) (aunque no estoy seguro de que sirva de mucho)

Dada la pequeña cantidad de memoria del sistema, creo que debería considerar seriamente cambiar al sistema operativo de 32 bits. El uso de un sistema operativo x64 te está lastimando en lugar de ser beneficioso.

Si no está utilizando el almacenamiento de InnoDB en su base de datos MySql, también puede considerar desactivar InnoDB en su my.cnf, ya que ahorrará otros 100 MB de RAM.

Lowendbox tiene un excelente tutorial sobre cómo optimizar los servidores para la configuración de poca memoria.

invarbrass
fuente
Bueno, mi voz se ha vuelto ronca tratando de razonar con mi empresa de hosting para proporcionarme un sistema operativo de 32 bits. Parece que en toda la red estas compañías proporcionan solo 64 bits. Encontré solo una compañía que proporciona SO de 32 bits, pero son mucho más costosas.
AppleGrew
3

Un comando muy útil para encontrar la memoria tomada por php:

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

Luego divide la RAM que desea dedicar a php, ¡y tiene su valor max_children!

Además, puede monitorear manualmente (debe configurar el punto final php-status) o con Nagios.

Thomas Decaux
fuente
awk: fatal: division by zero attempted
samayo
1
Significa que no tiene un proceso php5-fpm ... necesita cambiar el nombre del proceso "php5-fpm" para que se ajuste al suyo.
Thomas Decaux
Usé este comando ps --no-headers -o "rss,cmd" | grep php5-fpm | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"M") }'De alguna manera -C opciones no funciona.
Dieend
Intente ejecutar el comando por separado (me refiero a ps --no-headers -o "rss, cmd" primero, etc ...) esto debería ser fácil de depurar
Thomas Decaux