tutorial the programming program language golang for example http go osx-yosemite

http - the - ¿Por qué ApacheBench aplasta mi servidor Hello World go?



golang step by step (1)

package main import ( "io" "net/http" ) func hello(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "Hello world!/n") } func main() { http.HandleFunc("/", hello) http.ListenAndServe(":8000", nil) }

Tengo un par de servidores HTTP increíblemente básicos, y todos ellos presentan este problema.

$ ab -c 1000 -n 10000 http://127.0.0.1:8000/ This is ApacheBench, Version 2.3 <$Revision: 1604373 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 127.0.0.1 (be patient) Completed 1000 requests Completed 2000 requests Completed 3000 requests Completed 4000 requests Completed 5000 requests apr_socket_recv: Connection refused (61) Total of 5112 requests completed

Con un valor de concurrencia menor, las cosas aún se caen. Para mí, el problema parece aparecer alrededor de la marca 5k-6k generalmente:

$ ab -c 10 -n 10000 http://127.0.0.1:8000/ This is ApacheBench, Version 2.3 <$Revision: 1604373 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 127.0.0.1 (be patient) Completed 1000 requests Completed 2000 requests Completed 3000 requests Completed 4000 requests Completed 5000 requests Completed 6000 requests apr_socket_recv: Operation timed out (60) Total of 6277 requests completed

Y, de hecho, puede eliminar la concurrencia por completo y el problema aún (a veces) ocurre:

$ ab -c 1 -n 10000 http://127.0.0.1:8000/ This is ApacheBench, Version 2.3 <$Revision: 1604373 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 127.0.0.1 (be patient) Completed 1000 requests Completed 2000 requests Completed 3000 requests Completed 4000 requests Completed 5000 requests Completed 6000 requests apr_socket_recv: Operation timed out (60) Total of 6278 requests completed

No puedo evitar preguntarme si estoy alcanzando algún tipo de límite del sistema operativo en alguna parte. ¿Cómo lo diría? ¿Y cómo mitigaría?


En resumen, te estás quedando sin puertos.

El rango de puerto efímero predeterminado en osx es 49152-65535, que es solo 16,383 puertos. Como cada solicitud ab es http/1.0 (sin keepalive en sus primeros ejemplos), cada nueva solicitud toma otro puerto.

A medida que se utiliza cada puerto, se pone en una cola donde espera el tcp "Duración máxima del segmento", que está configurado para ser 15 segundos en osx. Entonces, si usa más de 16,383 puertos en 15 segundos, el sistema operativo lo estrangulará en conexiones adicionales. Dependiendo de qué proceso se quede sin puertos primero, obtendrá errores de conexión del servidor o se bloquea desde ab .

Puede mitigar esto usando un generador de carga compatible con http/1.1 como wrk , o usando la opción keepalive ( -k ) para ab , de modo que las conexiones se reutilicen según la configuración de concurrencia de la herramienta.

Ahora, el código del servidor que está comparando hace tan poco, que el generador de carga está sujeto a impuestos tanto como el servidor en sí, con el sistema operativo local y la pila de red haciendo una buena contribución. Si desea comparar un servidor http, es mejor hacer un trabajo significativo de varios clientes que no se ejecutan en la misma máquina.