Nginx + php-fpm: cada php-fpm procesa 70-100% de CPU cuando se ejecuta

8

Tengo una situación en la que ocurre lo siguiente:

  • Estamos en linode con 8 núcleos, 8 gb de ram, 2.6 ghz, usando nginx + php-fpm, estamos obteniendo gráficos extremadamente altos de uso de CPU (que no queremos ser un vecino VPS tan malo) ...

  • Tenemos alrededor de menos de 100 usuarios en el sitio a la vez, por lo que esta situación también es increíblemente vergonzosa, porque nuestro uso de CPU es muy alto.

  • Estamos utilizando un Framework muy desconocido, posiblemente intensivo en CPU, php-wise, cuestionablemente horrible en lugar de otros frameworks bien conocidos, bien documentados y bien diseñados como WordPress o Drupal en los que hay MUCHA documentación sobre el almacenamiento en caché (así como complementos que manejan el almacenamiento en caché) php en una plataforma nginx + php_fpm.

  • Por lo tanto, tenemos alrededor de 6 procesos php-fpm abiertos que, al EJECUTARSE, consumen individualmente GRANDES (más de 30%, y a menudo cerca del 99%) cantidades de CPU, y realmente no tengo la menor idea de cómo evitar que usen tanta CPU . No puedo decir qué scripts php están causando estos picos porque están sucediendo todo el tiempo ... por lo general, solo 1 o 2 se están ejecutando, pero cuando los 6 se ejecutan, maximizamos los 8 cpus.

  • Mi archivo pool.d / www.conf tiene la siguiente configuración:

    pm = dynamic
    pm.max_children = 10
    pm.start_servers = 4
    pm.min_spare_servers = 2
    pm.max_spare_servers = 6
    
  • Hicimos esta configuración ^ porque, en la forma en que lo estoy interpretando, nuestra memoria es realmente increíble (htop muestra 472/7000 + mb utilizados, sin intercambio, etc.) y podríamos manejar muchos más procesos y romper la línea esperando obtener procesado, PERO desafortunadamente, dado que cada proceso es demasiado intenso en nuestra CPU cuando se ejecuta, terminamos manejando nuestra CPU por el techo, por lo que no podemos manejar suficientes procesos.

  • La pregunta : ¿qué podemos hacer para reducir el uso de la CPU del proceso php-fpm para que podamos aumentar la configuración en ese archivo de configuración de grupo para php-fpm ? Y también sí, el /var/log/php5-fpm.log nos está gritando que aumentemos nuestros hijos y ajustemos / aumentemos nuestros servidores min / max / start. Pero hacerlo hace que nuestro promedio de carga sea una locura como se dijo anteriormente. ¿Cómo podemos hacerlo sin usar necesariamente un caché o cuáles son nuestras opciones?

  • ¿Mi idea? He leído cosas sobre el uso de cpulimit para garantizar que ningún proceso requiera más que una cantidad asignada de CPU, pero ¿eso retrasará las cosas para que no se puedan usar? O al hacerlo, podríamos aumentar nuestra capacidad para ejecutar más de unos pocos procesos; también pensé en ejecutar dos grupos: uno para nuestro sitio web orientado hacia adelante (lo que experimentan los clientes) y otro para un back-end (que está afectando nuestro sitio orientado hacia adelante cuando el tiempo -informes de consumo se están ejecutando).

  • He pasado unos días investigando, buscando en Google, etc. sobre este tema, y ​​es difícil porque la situación de cada persona es tan única en su sistema, que el problema está en un marco tan específico, inaudito y posiblemente mal escrito. Es difícil encontrar una solución. Tampoco podemos descartar este marco todavía: tengo que encontrar una solución de algún tipo.


ACTUALIZACIÓN: he implementado memcache para almacenar sesiones php, porque el marco depende en gran medida de las sesiones de los usuarios y la naturaleza de nuestro sistema es que los empleados a menudo usan varias pestañas a la vez, cada una de las cuales vuelve a las sesiones para confirmar las habilidades / datos de usuario / etc. ... así que espero ver un aumento en el rendimiento de esto, bienvenido a comentar sobre eso si lo desea, veré cómo va mañana cuando superemos nuestras horas pico de mayor volumen.

amurrell
fuente
Nginx no es muy bueno para una aplicación web intensiva de CPU, pero nuestra CPU alta es mala, realmente mala, y estamos trabajando para solucionarlo. No hay una gran configuración de clientes máximos porque DEBE ser capaz de admitir un número decente de clientes, pero el alto uso de CPU por proceso sesga esa capacidad. Cambiamos a Apache solo porque funciona un poco MEJOR con un alto uso de CPU, pero en última instancia, este problema es más indicativo de un problema de aplicación web y puede llevar un tiempo solucionarlo, pero no hay tiempo como el presente para comenzar a solucionarlo.
amurrell
Cuando va al médico y él le dice que tome ciertos medicamentos, porque sabe que no escuchará las declaraciones de "dejar de beber refrescos y comer comida rápida", esta es exactamente la razón por la que no hubo una gran respuesta para mí, porque la verdad es que , ninguna configuración o solución rápida realmente aplicada, solo la triste verdad de que tenemos que alterar drásticamente nuestra aplicación web.
amurrell
Afortunadamente, si tiene este problema con un marco popular, puede tener la opción de aprovechar el almacenamiento en caché y la abundante documentación al respecto, pero estamos en algo oscuro y aleatorio que no podemos cambiar, excepto el marco en sí. ¡Hurra!
amurrell
1
Entonces, por lo que entiendo, opcache está almacenando su código PHP como binario y php-fpm puede consumirlo mucho más rápido (almacenamiento en caché), pero también debe utilizar el almacenamiento en caché de objetos ... un ejemplo es almacenar una salida de página completa como un "objeto "en algo así como memcached. Esto realmente almacenaría en caché la salida de la página (u otras cosas que desee, como las sesiones de php, etc.) ... Luego, también podría usar barniz, que es un proxy inverso, pero básicamente es un intermediario entre la solicitud y su servidor para que su el servidor no recibe solicitudes directamente, y funciona desde la memoria para servir las URL almacenadas en caché.
amurrell
1
El barniz es impresionante para esto: almacenar una copia en caché de lo que obtuvo del servidor en la memoria, por lo que el barniz toma gran parte de la carga. Mi empleador actual está en nginx y usamos barniz y memcached. Afortunadamente, el marco en el que estamos ahora tiene su propio mecanismo de almacenamiento en caché para determinar el caché de la página (datos de página de salida). En mi último trabajo tuve que escribirlo en el marco yo mismo, no fue divertido, pero funcionó. Apache: no volvería a cambiar, a menos que no tenga tiempo para arreglar nginx ... Odiaba volver pero era única solución para no matar totalmente nuestro proyecto mientras escribía el mecanismo de almacenamiento en caché.
amurrell

Respuestas:

6

Un par de cosas a tener en cuenta (disculpas de antemano si ya las ha considerado): en primer lugar, asegúrese de optimizar su configuración nginx e invoque php-fpm solo cuando sea absolutamente necesario. Lo último que quiere hacer es dejar que php maneje cosas como páginas HTML estáticas (lo que hará felizmente).

En segundo lugar, dado que está usando php-fpm, sugiero que sea más agresivo con el tiempo que los niños de php-fpm pueden vivir. Debe encontrar el punto óptimo entre hilos / hijos de corta duración y estabilidad. Los valores predeterminados de php-fpm son demasiado generosos para cualquier sistema de producción, en mi humilde opinión. Cuanto más tiempo se le permita a un trabajador atender solicitudes, más inestable se volverá. También existe un mayor riesgo de pérdidas de memoria, y si este marco al que se refiere tiene errores como bucles infinitos, que pueden estar causándole problemas con la carga de la CPU, esto no debería doler.

Reduciría el número pm.max_requestsde sus grupos de producción. Creo que el valor predeterminado es 200. Comenzaría desde 50 y vería a dónde lo lleva.

Si falla o es complementario a eso, también puede probar estas opciones globales (AFAIK, todas están deshabilitadas de forma predeterminada):

emergency_restart_threshold 3
emergency_restart_interval 1m
process_control_timeout 5s

¿Qué significa esto? Si 3 procesos secundarios PHP-FPM salen con SIGSEGV o SIGBUS (es decir, se bloquean) en 1 minuto, se supone que PHP-FPM se reiniciará automáticamente. El niño procesa espera 5 segundos para una reacción a las señales del maestro.

Aquí hay una buena descripción de todas las opciones de configuración que mencioné aquí, así como otras: http://myjeeva.com/php-fpm-configuration-101.html

Espero que estos consejos te ayuden! Recuerde ajustar y observar, desafortunadamente no parece haber una regla general para todo esto, como observó, hay demasiadas variables que afectan el comportamiento y la estabilidad de PHP.

Finalmente, el recurso de limitación de CPU sobre el que investigó está documentado aquí , pero solo recurriría a él si agota todas las demás opciones. Si elige esta ruta, definitivamente estaría atento a las posibles interacciones entre los ajustes de PHP-FPM y su configuración de limit.conf. En ese momento, etckeeper puede ser un salvavidas. :)

¡Buena suerte!

Rouben

Rouben
fuente
Voy a intentar limitar las max_requests mañana. Parece que cada proceso que permitimos quiere comer la CPU, por lo que podría ser una buena idea. Estamos utilizando los umbrales de reinicio de emergencia, pero mis números fueron un poco más altos. Probaré los suyos y veré cómo van las cosas. Gracias por su minuciosidad, muy apreciado. ¿Quería saber lo que piensa sobre el almacenamiento en caché? Me pregunto si utilizar el almacenamiento en caché de php significa que el marco debería adaptarse para manejarlo. Soy bastante nuevo en ese concepto.
amurrell
3

Está ejecutando el almacenamiento en caché de opcode, ¿verdad?

Solía ​​ser APC lo que se usaba aquí, pero ha sido una pieza con errores durante bastante tiempo, y ha sido reemplazado por Zend Opcache , que ahora es parte de PHP desde 5.5, y tiene un backport en PECL para 5.3 y 5.4.

Michael Hampton
fuente
Estoy interesado en este Zend OpCache - Estamos en 5.3 - Si pudiera ampliar esta respuesta, ¡realmente lo agradecería!
amurrell
Teníamos xcache, pero ahora he optado por Zend Opcache y lo he instalado y confirmado que está funcionando en phpinfo (). Le
avisaré
Tuve que deshabilitar zend opcache por ahora, todo funcionaba, excepto cualquier archivo css o js generado por php dinámico. Traté de poner en una lista negra esos archivos de opcache, pero la lista negra no funcionó o no puedo decir por qué opcache está causando que nginx obtenga 502 errores de puerta de enlace incorrecta SOLO para esos archivos. Que los necesito para la plantilla y son parte del mal marco. En los registros de nginx recibí toneladas de readv fallidos - 104 error de conexión entre pares.
amurrell