Consejos para pruebas de carga de servidores y proxies web

[spanish]Una de las tecnologías con las que me pego en el trabajo son los proxies web. En mi anterior trabajo, eran los servidores y aplicaciones web. En ambos casos antes de meter nada en producción (o antes de hacer una actualización de lo que ya hay) es una buena idea hacer pruebas de carga para conocer los límites de la tecnología y si hay que añadir servidores. Para hacer estas pruebas hay soluciones comerciales como el Avalanche de Spirent, pero con un poco de trabajo y software libre se puede montar un sistema igual de bueno.

En primer lugar y antes de comenzar cualquier test, hace falta una herramienta para tomar medidas. No vale simplemente meterle carga al Apache y pegarle un vistazo a los logs, free, ps y el server-status, es mucha información en bruto como para tratarla a mano. Una herramienta que a mi me ha resultado extremadamente útil, tanto para analizar el comportamiento de un sistema durante una prueba de carga como para la monitorización del día a día en operaciones es el Cacti.

Cacti es una aplicación LAMP que ejecuta una serie de sondas (programables) en los diferentes sistemas a monitorizar, y hace gráficas con los resultados, gráficas de distintos periodos de tiempo: las últimas horas, los últimos días, meses, etc. de forma que tienes una visión histórica de la evolución del servicio. La información que proporciona esta visión histórica es crítica, al hacer una prueba de carga normalmente no quieres sólo saber cuán bien funciona el sistema con la última versión del software, si no cómo funciona en comparación con la versión anterior. O si estás monitorizando un sistema en producción, quieres analizar la diferencia entre el pico de tráfico web que hay un lunes por la mañana frente a la calma de un domingo por la tarde. Ejecutar un test y tomar cuatro medidas puntuales no vale de nada si no se pone en contexto y perspectiva con los resultados de tests anteriores o los valores que haya en producción. Y como Cacti te permite desarrollar tus propias sondas en el lenguaje de programación que quieras, no hay nada que pueda ser medido (uso de CPU o memoria, latencia, carga de I/O, conexiones concurrentes, etc.) de lo que no se pueda hacer un gráfico. De hecho lo más normal es que vayas añadiendo más y más gráfico conforme vayas haciendo más pruebas y detectando más posibles puntos de fallo y variables a monitorizar. Detectar regresiones de rendimiento, memory leaks, etc. es muy fácil (de hecho, muy visual) con Cacti.

Una vez que ya tenemos nuestra herramienta para tomar mediciones, podemos empezar con las pruebas. Si el sistema a probar es un servidor web, sólo hace falta un programa que simule varios clientes; si es un proxy, tanto eso como un servidor web al que atacar. La parte del servidor es fácil, se puede usar Apache o (incluso mejor) lighttpdnginx. En este caso lo que queremos es estresar el proxy, no el servidor web que tiene que haber detrás, así que queremos un servidor web tan rápido como sea posible. Se debería pensar incluso en poner la «nube» (el juego de páginas html que van a pedir los clientes) en un disco ram y en desactivar el access.log del servidor, para minimizar los accesos a disco y así aumentar el rendimiento. ¡Hay que asegurarse de que el servidor web no se convierte en un cuello de botella, de lo contrario no estaríamos estresando al proxy!

Respecto al software para simular clientes, hay varias opciones: desarrollar uno desde cero, hacerlo a base de scripts y wget o curl, o usar alguno de los programas que ya hay a tal efecto como curl-loader, Apache’s JMeter o cualquier otro. Busca en Google.

Independientemente de qué software uses para simular los clientes, hay que tener una cosa en cuenta: estos programas generalmente van a generar una carga muy alta pero bajo condiciones ideales. Es decir: todo el sistema (cliente-proxy-servidor) va a estar en una red local, probablemente con velocidades de Giga, sin pérdida de paquetes, retransmisiones, paquetes fuera de secuencia, etc. Eso no es lo que te vas a encontrar «ahí fuera» cuando pases el sistema a producción. Según lo que quieras probar, si el límite máximo teórico de carga o cuán bien el nuevo desarrollo va a funcionar con tráfico real, deberás adaptar el tráfico a ese caso.

Consejos útiles a la hora de cacharrear con el tráfico:

  • Si tu simulador de clientes te lo permite, ¡no lo ejecutes a tope de velocidad! trickle puede ser útil en estos casos. Como mínimo haz dos pruebas: una sin límite de velocidad y otra p.ej. a 3mbps por cliente para simular usuarios con una línea ADSL. Ten en cuenta que esto es sólo un límite de velocidad, todavía conseguiremos meterle bastante carga al servidor porque a menos velocidad, probablemente acabe teniendo más conexiones concurrentes (¿bloqueantes?). He visto programas aguantar como unos campeones cargas altísimas en condiciones ideales y petar en cuestión de segundos en producción con tráfico real… y lento.
  • Pierde paquetes. Reordena paquetes. Mete un router/bridge linux entre el cliente y el equipo a probar y juega con el sistema tc de Linux. Pégale un vistazo a estoestoestoesto.
  • Simula varias IPs cliente distintas. Elige toda una clase B o C, asegúrate de configurar bien las rutas en todos los sistemas para que sean coherentes, y ejecuta algo como esto en el cliente (o el router/bridge del punto anterior). Es un poco sucio pero funciona:
    while :
    do
      I=$((1+RANDOM%254))
      J=$((1+RANDOM%254))
      /sbin/iptables -t nat -F
      /sbin/iptables -t nat -A POSTROUTING -d 1.1.1.1 -o eth1 -j SNAT --to-source 10.10.$I.$J
      sleep 0.1s
    done

Con todo esto, deberías ser capaz de montar una infraestructura de pruebas bastante decente.[/spanish]

[english]At work, one of the technologies I work with are web proxies. On my previous work, web servers and web applications. On both cases before going into production (or before rolling an update) it’s wise doing some stress-testing, trying to assess the limits of the technology or the need for more servers. There are commercial solutions available, like e.g. Spirent‘s Avalanche, but with some work you can roll out your own stress-testing infrastructure using free software.

On the first place, before beginning with the test, you need a measuring tool. Just throwing some load to Apache and then taking a look at the logs, free, ps, and server-status by hand is plain crazy, too much raw information to deal with. One tool I’ve found extremely useful, both for analyzing stress-tests results and for everyday operations monitoring is Cacti.

Cacti is a LAMP-based software which runs a series of (programmable) probes on your systems and makes graphs out of them, graphs of different time periods: the last hours, last days, months, etc. so that you have an historic view of the evolution of the service. Having this historic information is critical, when doing these kind of tests you not only want to know how well the latest release works but how does it compare to the previous one. Or in operations, you want to know the difference between the web traffic spike on a Monday morning compared to the calm of the Sunday afternoon. Just running a test and taking a measure in that moment is not enough, you need to put it in perspective with your previous tests and what you have in your production environment. And you can develop your own probes in whatever programming language you want, so there’s nothing that can be measured (CPU or memory usage, latency, I/O load, concurrent connections, etc.) that you can’t get on the graphs. You’ll add more and more probes and graphs as you go testing and discovering new variables that can affect system performance. Detecting regressions, memory leaks, etc. is very easy (well… visual) when using Cacti.

After having some measuring tool in place, we can start stress testing the systems. If you’re dealing with a web server, you only need a client-simulation program; if a proxy, both that and a server. The server part is easy, just use Apache or (even better) lighttpd or nginx. You want to stress test your proxy application, not the web server behind it, so you want a web server as fast as possible. Even think of putting your cloud (the set of web pages you’re going to test with) in a ramdisk and disabling the server’s access.log. Make sure that the web server doesn’t become a bottleneck or you won’t be really stressing the proxy!

As for the client-simulation software, you have several options: develop your own from the ground up, develop a series of scripts with wget or curl, or use some of the existent solutions available out there, like curl-loader, Apache’s JMeter. or may others. Just Google them.

No matter which software you use for the test, one consideration: These programs usually generate a very high load but under ideal conditions. I mean: you’re running them on a local network, likely with Gbps speeds, without packet loss or rearrangements … That’s not what you’ll find «out there». Depending on what you want to test, either the theoretical top performance or how a new development would cope with real traffic, you need to adapt the traffic of your test to that.

Things you’ll find useful for tweaking your traffic:

  • If your client-simulation software allows you, don’t run it at full network speed! trickle may come in handy here. At least run two tests: one without speed limit, and another with e.g. a 3mbps limit simulating a DSL line. Bear in mind that this is just a speed limit, the server will still have a high load because at a lesser speed it’ll likely have to cope with more concurrent (blocking?) connections. I’ve seen some software do great on a high speed laboratory test and choke in seconds with slow, real-world traffic.
  • Lose packets. Rearrange them. Insert a router/bridge linux server between your client and your test object and use Linux’s tc system. Take a look here, here, here and here.
  • Simulate multiple origin IPs. Take a whole B or C class network, make sure the routes in all your systems are coherent, and run something like this to randomize the clients’ IP addresses (a bit hacky, but it works):
    while :
    do
      I=$((1+RANDOM%254))
      J=$((1+RANDOM%254))
      /sbin/iptables -t nat -F
      /sbin/iptables -t nat -A POSTROUTING -d 1.1.1.1 -o eth1 -j SNAT --to-source 10.10.$I.$J
      sleep 0.1s
    done

With all this in place, you should have a pretty decent testing framework going.[/english]

2 comentarios sobre “Consejos para pruebas de carga de servidores y proxies web”

  1. Hola Bisente.
    He realizado pruebas con ese script del SNAT, y tengo que decirte que si la maquina destino no responde en menos de 0.1s, ya no vas ha tener respuesta, pues haces flush de la tabla SNAT y los paquetes que vuelven con una 10.10.x.x sin su regla en SNAT, se pierden en el limbo.
    Lo que he montado ahora para las pruebas que necesito, es lo siguiente: basandome en el rango de puertos (ip_local_port_range del /proc), he creado un bucle que genera la regla SNAT siguiente:
    10.10.puerto_origen/256.puerto_origen%256
    las reglas tardan un rato en crearse, pero al ser permanentes, y como una conexion http cliente no cambia de puerto… pues pita bien.
    iptables -t nat -p tcp –sport $puerto -d 172.10.10.10 -i ethx -SNAT 10.10.puerto/256.puerto%256
    Los resultados pasan de 56 peticiones/seg a 700.
    De todas formas, estoy estudiando el webpolygraph, un software con cliente http y server http con nube dinamica y un porron de opciones para simular trafico real. Si tienes FreeBSD puede usar el NET Dummy para hacer de forma elegante las perturbaciones de trafico. En vez de usar el traffic control. Es un todo en uno, pues tambien puede manejar pools de ips clientes.

    Saludos.

  2. Hombre Mario! Tu por aquí! :D
    Pues está bien la idea de montar una peazo-tabla basada en puertos, vale que tardará en generarse pero total, sólo lo vas a hacer una vez.
    Me apunto la idea yo del webpolygraph para cuando haga pruebas en el nuevo curro. :-)

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.