13 votos

Rendimiento de Apache se degrada dramáticamente por encima de ~ 256 peticiones simultáneas

Estoy corriendo un relativamente bajos-el sitio de tráfico que experimenta un gran aumento en los visitantes una vez a la semana después de una actualización del sitio. Durante este pico, el rendimiento del sitio es muy pobre en comparación con el resto de la semana. La realidad de la carga en los servidores sigue siendo muy baja, de forma fiable en el 10% de la CPU y menos de 30% de RAM (el hardware debe ser completa excesivo para lo que realmente estamos haciendo), pero por alguna razón Apache parece ser incapaz de lidiar con la cantidad de solicitudes. Estamos ejecutando apache 2.2.3 en RHEL 5.7, kernel 2.6.18-274.7.1.el5, x86_64.

Intentar reproducir este comportamiento durante las horas de descanso con ab, estoy encontrando una importante caída en el rendimiento cuando se excede aproximadamente 256 usuarios. Ejecución de la prueba con el menor uso posible caso que se me ocurrió (archivo de texto estático ser recuperada, de 223 bytes en total) rendimiento es siempre normal, con 245 solicitudes simultáneas:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       15   25   5.8     24      37
Processing:    15   65  22.9     76      96
Waiting:       15   64  23.0     76      96
Total:         30   90  27.4    100     125

Percentage of the requests served within a certain time (ms)
  50%    100
  66%    108
  75%    111
  80%    113
  90%    118
  95%    120
  98%    122
  99%    123
 100%    125 (longest request)

Pero tan pronto como me trinquete hasta 265 solicitudes simultáneas, un subconjunto de ellos empezar a tomar una absurda cantidad de tiempo para completar:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       13  195 692.6     26    3028
Processing:    15   65  21.3     72     100
Waiting:       15   65  21.3     71      99
Total:         32  260 681.7    101    3058

Percentage of the requests served within a certain time (ms)
  50%    101
  66%    108
  75%    112
  80%    116
  90%    121
  95%   3028
  98%   3040
  99%   3044
 100%   3058 (longest request)

Estos resultados son muy consistentes a través de múltiples pistas. Ya que no hay otro tráfico que va a la caja, no estoy seguro de que, precisamente, donde el duro de corte sería, si es que la hay, pero parece ser sospechosamente cerca de 256.

Naturalmente, yo supuse que esto era causado por el hilo límite en prefork, así que me fui por delante y ajustar la configuración para duplicar el número de subprocesos disponibles y para evitar que el grupo de subprocesos de crecimiento y reducción de unneccessarily:

<IfModule prefork.c>
StartServers     512
MinSpareServers  512
MaxSpareServers  512
ServerLimit      512
MaxClients       512
MaxRequestsPerChild  5000
</IfModule>

mod_status confirma que ahora estoy corriendo con 512 subprocesos disponibles

8 requests currently being processed, 504 idle workers

Sin embargo, el intento de 265 solicitudes simultáneas sigue arrojando resultados casi idénticos a los de antes

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       25  211 714.7     31    3034
Processing:    17   94  28.6    103     138
Waiting:       17   93  28.5    103     138
Total:         57  306 700.8    138    3071

Percentage of the requests served within a certain time (ms)
  50%    138
  66%    145
  75%    150
  80%    161
  90%    167
  95%   3066
  98%   3068
  99%   3068
 100%   3071 (longest request)

Después de fregar la documentación (y de Intercambio de la Pila) estoy en una pérdida para más opciones de configuración para intentar resolver este cuello de botella. Hay algo que me estoy perdiendo? Debo empezar a buscar respuestas fuera de apache? Ha alguien más visto este comportamiento? Cualquier ayuda sería muy apreciada.

EDITAR:

Como por Ladadadada los consejos, me encontré con strace en contra de apache. He probado con-tt y-T un par de veces, y no podía encontrar nada fuera de lo normal. Luego traté de correr strace-c en contra de la ejecución de todos los procesos de apache, y obtuve esto:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 22.09    0.317836           5     62128      4833 open
 19.91    0.286388           4     65374      1896 lstat
 13.06    0.187854           0    407433           pread
 10.70    0.153862           6     27076           semop
  7.88    0.113343           3     38598           poll
  6.86    0.098694           1    100954     14380 read

(...abdridged)

Si estoy leyendo este derecho (y tener paciencia conmigo, ya que yo no uso strace muy a menudo) ninguna de las llamadas al sistema pueden tener en cuenta la cantidad de tiempo que estas solicitudes se están tomando. Casi parece como si el cuello de botella se produce antes de las solicitudes, incluso, llegar a los subprocesos de trabajo.

EDIT 2:

Como varias personas sugirieron, me encontré de nuevo la prueba en el servidor web (anteriormente, la prueba se ejecuta a partir de un punto neutro de internet de la ubicación). Los resultados fueron sorprendentes:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   11   6.6     12      21
Processing:     5  247 971.0     10    4204
Waiting:        3  245 971.3      7    4204
Total:         16  259 973.3     21    4225

Percentage of the requests served within a certain time (ms)
  50%     21
  66%     23
  75%     24
  80%     24
  90%     26
  95%   4225
  98%   4225
  99%   4225
 100%   4225 (longest request)

La parte inferior de la línea de tiempo, es similar a la prueba basada en internet, pero parece que siempre será un poco peor cuando se ejecuta localmente. Más curiosamente, el perfil ha cambiado drásticamente. Mientras que antes la mayor parte de las solicitudes de' tiempo que se gastó en "conectar" ahora el cuello de botella parece estar en el procesamiento o en espera. Yo soy de izquierda a sospechar que en realidad, esto puede ser un tema aparte que anteriormente se estaba enmascarada por la red limitaciones.

Ejecución de la prueba de nuevo desde otra máquina de la misma red local como el host de Apache, estoy viendo mucho más razonable de los resultados:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        1    2   0.8      2       4
Processing:    13  118  99.8    205     222
Waiting:       13  118  99.7    204     222
Total:         15  121  99.7    207     225

Percentage of the requests served within a certain time (ms)
  50%    207
  66%    219
  75%    220
  80%    221
  90%    222
  95%    224
  98%    224
  99%    225
 100%    225 (longest request)

Estas dos pruebas juntas plantear una serie de preguntas, pero, aparte de eso, hay ahora un caso convincente para algún tipo de grave cuello de botella de la red pasando por debajo de cierta cantidad de carga. Creo que los próximos pasos serán la investigación de la capa de red por separado.

3voto

Brad Puntos 3206

Qué haría yo en esta situación se ejecuta

strace -f -p <PID> -tt -T -s 500 -o trace.txt

en uno de sus procesos de Apache durante el ab de la prueba hasta que la captura de una de las respuestas lentas. A continuación, echar un vistazo a través de la trace.txt.

El -tt y -T opciones de dar la hora de inicio y duración de cada llamada al sistema para ayudar a identificar a los más lentos.

Usted puede encontrar una sola lento llamada al sistema, tales como open() o stat() o usted podría encontrar una llamada rápida con (posiblemente varias) poll() llamadas directamente después de ella. Si usted encuentra uno que está operando en un archivo o una conexión de red (bastante probable) mirar hacia atrás a través de la traza hasta que encuentre el archivo o identificador de conexión. Los llamamientos anteriores en ese mismo identificador debe darle una idea de lo que el poll() estaba esperando.


Buena idea mirar en la -c opción. ¿Asegúrese de que el hijo de Apache que se seguimiento servido al menos una de las solicitudes lentas durante ese tiempo? (Ni siquiera estoy seguro de cómo se haría esto aparte de correr strace de forma simultánea en todos los niños.)

Por desgracia, strace no nos da la imagen completa de lo que un programa en ejecución que está haciendo. Sólo las pistas de llamadas al sistema. Muchas cosas pueden suceder dentro de un programa que no requiere pedir el kernel para nada. Para averiguar si esto sucede, usted puede ver las marcas de tiempo del inicio de cada llamada al sistema. Si ves carencias importantes, que es donde se va el tiempo. Esto no es fácil de greppable y siempre hay pequeños huecos entre el sistema de llamadas de todos modos.

Ya se dijo que el uso de CPU se mantiene baja, probablemente no excesivo de las cosas que suceden entre las llamadas del sistema, pero es digno de la comprobación.


Mirando más de cerca a la salida de ab:

El salto repentino en los tiempos de respuesta (parece que no hay tiempos de respuesta en cualquier lugar entre 150ms y 3000ms) sugiere que hay un tiempo de espera específico sucediendo en algún lugar que se activa por encima de alrededor de 256 conexiones simultáneas. Una suave degradación sería de esperar si se ejecuta fuera de la RAM o ciclos de CPU normal IO.

En segundo lugar, la lenta ab de respuesta muestra que el 3000ms se pasó en el connect fase. Casi todos ellos tomó alrededor de 30ms pero el 5% tuvo 3000ms. Esto sugiere que la red es el problema.

Dónde están ejecutando ab ? Se puede tratar de la misma red que el Apache de la máquina?

Para más datos, intente ejecutar tcpdump , en ambos extremos de la conexión (de preferencia con ntp ejecución en ambos extremos, de modo que usted puede sincronizar las dos capturas). y busca cualquier retransmisiones de tcp. Wireshark es particularmente buena para el análisis de los vertederos porque pone de retransmisiones de tcp en un color diferente, haciendo que sean fáciles de encontrar.

También podría ser vale la pena mirar los registros de los dispositivos de red que tienen acceso. Recientemente me encontré con un problema con uno de nuestros firewalls donde se puede controlar el ancho de banda en términos de kb/s, pero no podía controlar el número de paquetes por segundo que estaba recibiendo. Se llegó al 140,000 paquetes por segundo. Rápida de las matemáticas en su ab de ejecución me lleva a creer que hubiera sido ver a alrededor de 13.000 paquetes por segundo (ignorando el 5% de las solicitudes lentas). Tal vez este es el cuello de botella que han alcanzado. El hecho de que esto sucede alrededor de 256 podría ser una mera coincidencia.

EnMiMaquinaFunciona.com

EnMiMaquinaFunciona es una comunidad de administradores de sistemas en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros sysadmin, hacer tus propias preguntas o resolver las de los demás.

Powered by: