¿Cómo logró WhatsApp 2 millones de conexiones por servidor?
En Ubuntu, el número máximo de sockets que se pueden abrir parece regirse por lo siguiente:
$ cat /proc/sys/net/ipv4/tcp_max_orphans
262144
Según una de las presentaciones de Rick Reed (de WhatsApp), estos chicos lograron hasta 2 millones de conexiones simultáneas en un "único servidor" usando FreeBSD y ErLang. Tengo entendido que siempre necesitaremos algún soporte del kernel. Y sí, parece que FreeBSD se modificó para que tenga esta capacidad :
hw.machine: amd64
hw.model: Intel(R) Xeon(R) CPU X5675 @ 3.07GHz
hw.ncpu: 24
hw.physmem: 103062118400
hw.usermem: 100556451840
kb@c123$ uname -rps
FreeBSD 8.2-STABLE amd64
jkb@c123$ cat /boot/loader.conf.local
kern.ipc.maxsockets=2400000
kern.maxfiles=3000000
kern.maxfilesperproc=2700000
Entonces, parece que el kernel se puede modificar para admitir tantas conexiones físicas, dado que tenemos suficiente cantidad de memoria, ¿correcto? En caso afirmativo, entonces parece bastante simple, entonces ¿cuál es el revuelo al respecto? ¿O me falta algo?
Gracias.
Si tiene suficiente RAM, no es demasiado difícil manejar 1 millón o más de conexiones en Linux. Estos chicos manejaron 10 millones de conexiones con una aplicación Java en una sola caja usando el kernel CentOS normal con algunos ajustes de sysctl:
sysctl -w fs.file-max=12000500
sysctl -w fs.nr_open=20000500
ulimit -n 20000000
sysctl -w net.ipv4.tcp_mem='10000000 10000000 10000000'
sysctl -w net.ipv4.tcp_rmem='1024 4096 16384'
sysctl -w net.ipv4.tcp_wmem='1024 4096 16384'
sysctl -w net.core.rmem_max=16384
sysctl -w net.core.wmem_max=16384
También equilibraron los /proc/irq/ del adaptador de red y agregaron un ajuste para un mejor trabajo de JVM con páginas grandes:
sysctl -w vm.nr_hugepages=30720
Con dos CPU de 6 núcleos cargadas al 57%, ofrecieron 1 Gbps en conexiones de 12 millones en 2013.
Pero necesitas una GRAN cantidad de RAM para eso. La prueba anterior se realizó en un servidor con 96 GB de RAM, y el kernel utilizó 36 GB de ellos para buffers de sockets de 12 M.
Para servir conexiones de 1M con configuraciones similares, necesitará un servidor con al menos 8 GB de RAM y de 3 a 4 GB se usarían solo para buffers de socket.
Tenga en cuenta que aquí hay tres cosas:
Conseguir que el servidor admita dos millones de conexiones. Por lo general, esto consiste simplemente en ajustar el núcleo de modo que se permita la cantidad de conexiones simultáneas y de modo que el contexto asociado con cada conexión encaje en la memoria principal (cableada). Esto último significa que no se puede asignar un espacio de búfer de megabytes para cada conexión.
Hacer algo con cada conexión. Los asigna al espacio de usuario en un proceso (Erlang en este caso). Ahora, si cada conexión asigna demasiados datos a nivel de espacio de usuario, volvemos al punto de partida. No podemos hacerlo.
Conseguir que varios núcleos hagan algo con las conexiones. Esto es necesario debido a la enorme cantidad de trabajo que queda por hacer. También es el punto en el que desea evitar bloquear demasiado, etc.
Pareces estar concentrado solo en 1.