El extraño caso de Mr. Time To First Byte

14

Tengo un servidor web en un Linode 1024 VPS basado en

  • Ubuntu 11.10
  • Nginx 1.0.5
  • PHP 5.3.6 (con PHP-FPM, APC)
  • Barniz 3.0.2

Y un par de blogs allí basados ​​en WordPress 3.3.1. Uno de ellos es un blog simple, con la configuración predeterminada, el tema y solo la publicación "Hello World", para probar el servidor. El otro es un blog clonado desde otro servidor con casi 10k publicaciones y más de 10k comentarios. Este blog tiene alrededor de 5k únicos por día.

El servidor da buenos números en una prueba ab para el blog de prueba , pero la misma prueba con el blog clonado es imposible de hacer: la prueba ab carga demasiado el servidor y tengo que detener el proceso, lo que de todos modos hace que ab muestre Este resultado realmente pobre .

El htop muestra también una carga "normal" cuando está en funcionamiento normal , pero una carga anormalmente grande durante la prueba de ab.

Está sucediendo otra cosa extraña (la más importante para mí): el tiempo hasta el primer byte es extremadamente alto , pero después de eso, el sitio se carga muy rápido. Esto se puede probar fácilmente con servicios como tools.pingdom.com, que proporciona este resultado . Por favor, preste atención a esa región amarilla que significa "tiempo de espera".

¿Por qué está pasando esto? Posibles ideas:

  • Mala configuración de PHP-FPM
  • El tiempo de respuesta de DNS de Linode es horrible. Tonterías: el blog de prueba resuelve DNS bien, TTFB es fantástico
  • Mala configuración de Nginx

En caso de que alguien necesite más información,

javipas
fuente
Creo que esto puede tener algo que ver con la if -fdirectiva que está utilizando en el locationcontenedor en la configuración de nginx. Basado en lo que estoy leyendo aquí wiki.nginx.org/Pitfalls , tengo la sensación de que -festá haciendo una búsqueda ineficiente del archivo que podría causar un problema de Tiempo al primer byte, especialmente si tiene directorios con una gran cantidad de archivos.
d34dh0r53
1
Algunas reflexiones: a) ¿cuáles son las diferencias con el servidor original del que está clonado el blog (por ejemplo, ¿ejecuta la misma pila?) B) si puede, ejecute ab directamente desde el servidor utilizando localhost y el puerto. Intente acceder a través de barniz y luego acceder a nginx directamente). c) Habilite los registros lentos MySQL y PHP-FPM. d) ejecute mysqltuner.pl y vea si puede mejorar su rendimiento de MySQL (esa sería la diferencia más obvia entre los blogs, o complementos). e) La configuración PHP-FPM que publicó no parece ser la utilizada por nginx (/var/run/php5-fpm-tpnet.sock! = /var/run/php5-fpm-www-data.sock)
cyberx86
1
Definitivamente un problema de PHP. Wordpress es realmente lento. Querrá un complemento de almacenamiento en caché para que obtenga un tiempo de carga decente cuando tenga tanto contenido.
Martin Fjordvald
2
Dijiste que 'puedes ejecutar ab en localhost y obtener 4k req / s', ¿a qué localhost (anterior / actual) te refieres? Si ese valor proviene de su servidor actual, el que tiene un alto TTFB, entonces su problema se ha vuelto mucho más interesante, ya que ha eliminado efectivamente PHP, MySQL y su servidor web. TTFB incluye DNS, tiempo de ida y vuelta y tiempo de procesamiento. Un TTFB largo generalmente se debe al procesamiento (por ejemplo, PHP / MySQL). El punto de ejecutar ab directamente contra nginx es eliminar los otros componentes. Además, Varnish, si está configurado correctamente, debe pasar por alto el backend, dando una alta exigencia / s.
cyberx86
1
Sus pruebas de host local no parecen válidas: en realidad no recuperó su blog. Observe la diferencia en el tamaño de la página: 7500bytes cuando se accede desde el dominio, 151 bytes desde localhost. Como probablemente tenga múltiples hosts virtuales, debe pasar el encabezado del host a ab. ab -n 1000 -c 100 -H 'Host: mysite.com' http://127.0.0.1/Dicho esto, la diferencia en los resultados en caché (barniz) frente a los no almacenados en caché es suficiente para validar la posición de que el problema no está relacionado con la red, dns, etc. y radica en el procesamiento, como se esperaba.
cyberx86

Respuestas:

24

En primer lugar, esta no es una respuesta, sino un enfoque de diagnóstico.

Esto de ninguna manera es exhaustivo, o incluso algo cercano, es solo un punto de partida.

Tiempo hasta el primer byte

El tiempo hasta el primer byte (TTFB) tiene varios componentes:

  • Búsqueda de DNS: encuentre la dirección IP del dominio (posible mejora: servidores DNS más numerosos / distribuidos / sensibles)
  • Tiempo de conexión: abra un socket en el servidor, negocie la conexión (el valor típico debe estar alrededor del tiempo de 'ping' - generalmente es necesario un viaje de ida y vuelta - keepalive debería ayudar para solicitudes posteriores)
  • En espera: se requiere el procesamiento inicial antes de que se pueda enviar el primer byte (aquí es donde debería estar su mejora; será más significativo para el contenido dinámico).

Cuando mira una salida de ApacheBench, también ve:

  • Procesamiento: es la suma de espera + transferencia completa de contenido (si el tiempo de transferencia es significativamente más largo de lo que se esperaría para descargar la cantidad de datos recibidos, se está procesando más (después del primer byte recibido) (por ejemplo, la página está vaciar el contenido ya que está disponible)

Comparaciones para eliminar componentes

Con pocas excepciones, su problema radicará en el procesamiento de back-end, que generalmente se reduce a código demasiado complejo / ineficiente, o MySQL mal configurado.

Una buena manera de abordar este problema es a través de una serie de comparaciones que eliminarán varios aspectos de su configuración. Una buena comparación debe ser lo más constante posible para ayudar a reducir el problema. Actualmente, ha proporcionado las siguientes comparaciones:

  1. Sitio idéntico (clonado) que se ejecuta en el servidor antiguo y en el nuevo servidor:
    • Diferencia: servidor
    • Resultado: el antiguo servidor es rápido; nuevo servidor es lento
    • Notas: Lo que necesita aquí es cuantificar las diferencias entre estos servidores, tanto en términos de la pila utilizada (Nginx, etc.) como del hardware (¿el servidor antiguo es más rápido porque es una máquina más potente?)
    • Conclusión: el código puede ejecutarse rápidamente en la configuración correcta
  2. Sitio de prueba versus sitio completo en el nuevo servidor
    • Diferencia: contenido, temas, complementos, etc.
    • Resultado: el sitio de prueba es rápido, el sitio completo es lento
    • Notas: en teoría, esta prueba debería ayudarlo a eliminar muchos aspectos de su configuración (DNS, red, incluso su configuración nginx / php / mysql), sin embargo, no es del todo 'justo'.
    • Conclusión: el contenido adicional está teniendo un impacto significativo en el rendimiento

La prueba ideal sería duplicar su sitio completo, pero luego eliminar todo el contenido, excepto un artículo y los comentarios asociados. El objetivo de esta prueba sería determinar de manera concluyente si la gran cantidad de contenido es el problema o si otros aspectos de su configuración (plugins de WordPress, tema, etc.) son la causa. Básicamente, compararía el rendimiento de sitios idénticos, en el mismo (nuevo) servidor, cargando la misma página (misma longitud, etc.), con la única diferencia de ser el contenido total del sitio (por ejemplo, existe una buena posibilidad de que algún complemento no funcione). escalar bien con mayor contenido).

Sin cambiar nada, hay algunas otras comparaciones que puede hacer:

  • Pruebe desde una ubicación remota frente a una local: esto ayudará a identificar si la causa es la red, la latencia, el DNS, etc.
    • Ya ha hecho (algo) esto y ha concluido principalmente que no tiene un problema de red.
  • Pruebe a través de Varnish (es decir, el puerto 80) frente a nginx directamente (puerto 8080); intente no cambiar su configuración entre pruebas, solo use el puerto correcto. Esto le mostrará el impacto del barniz. Dado que Varnish es una capa de almacenamiento en caché, debe atender todas las solicitudes después de la primera muy rápidamente, esencialmente, debe omitir el backend y el procesamiento que se necesita para generar una página dinámica, y servir la copia en caché muy rápidamente.
    • Lo ha hecho (aunque no localmente) y ha demostrado que Varnish tiene un impacto positivo significativo en su rendimiento.

Afinando tu Backend

En este punto, ya debería haber encontrado el problema o concluido que se encuentra en su backend. Eso te deja Nginx, PHP o MySQL.

(Debo mencionar aquí, que es siempre útil para saber si su cuello de botella es la CPU, RAM, o E / S - entre sar, top, iostat, vmstat, free., Etc usted debe ser capaz de llegar a una conclusión sobre este tema)

Nginx

Nginx solo acepta solicitudes y sirve contenido estático o cambia las solicitudes a PHP-FPM; por lo general, no hay mucho que optimizar con Nginx.

  • Establecer trabajadores = # núcleos de CPU
  • Habilitar keepalive (un valor de 10-15 es bueno)
  • Deshabilitar el registro innecesario
  • Aumente el tamaño del búfer si es necesario
  • Evite las declaraciones if (use nombres estáticos en lugar de expresiones regulares cuando sea posible, elimine las extensiones innecesarias)

Idealmente, su blog de prueba y su blog clonado tienen configuraciones idénticas, en cuyo caso, efectivamente ha eliminado Nginx como el problema.

Solicitud

En el caso en que intente identificar un problema en su código (por ejemplo, un complemento lento, etc.), los registros lentos son el lugar para comenzar.

  • Habilite el registro lento de MySQL y el registro lento de PHP-FPM ejecute su punto de referencia y vea lo que viene como lento.

MySQL

  • Aumente sus cachés y ejecute mysqltuner.pl para obtener un buen punto de partida.

PHP

  • deshabilitar extensiones innecesarias,
  • deshabilitar register_globals, magic_quotes_ *, expose_php, register_argc_argv, always_populate_raw_post_data
  • aumentar el límite de memoria
  • open_basedir y safe_mode tienen importantes implicaciones de rendimiento, pero también pueden proporcionar una capa adicional de defensa. Pruebe con y sin ellos para determinar si su impacto en el rendimiento es tolerable.

PHP-FPM

  • Ajuste los valores pm. *: Aumente para hacer frente a una carga alta

Vale la pena señalar que los resultados de htop muestran que php-fpm consume la mayor parte de la CPU, y su problema parece estar directamente relacionado con esto.

Almacenamiento en caché

Una vez que haya optimizado cada posible cuello de botella, comience a almacenar en caché.

  • Ya tiene un caché opCode (APC), asegúrese de que funciona (viene con un archivo de prueba), verifique las tasas de aciertos de su caché y, si es posible, tenga el caché APC en la memoria en lugar de en el disco.
  • Configure su código en caché (por ejemplo, usando un complemento para Wordpress como W3TC)
  • Con nginx puede configurar el almacenamiento en caché FastCGI, pero como tiene Varnish, es mejor evitarlo.
  • Configure una capa de almacenamiento en caché, como Barniz (que ya ha hecho) y asegúrese de que funciona (por ejemplo, use varnishstat, lea Lograr un alto índice de aciertos )
  • Agregue más almacenamiento en caché para los componentes de su sitio, por ejemplo, MemCached si corresponde

A veces, dadas las limitaciones de su aplicación y hardware, es posible que no pueda mejorar tanto el rendimiento del backend, sin embargo, ese es el punto del almacenamiento en caché, para minimizar el uso del backend.

Otras lecturas

cyberx86
fuente
2
Ese es un fantástico resumen de puntos para analizar. Muchas gracias por el comentario, intentaré realizar una prueba exhaustiva con todas estas sugerencias -algunas de ellas, como has dicho, ya están claras- y veré si finalmente puedo detectar el problema. Saludos cordiales, cyberx86.
javipas
Sobre el memory_limit, se señaló en otra publicación que no ayuda con el rendimiento.
forloop