SO_REUSEPORT_LB: reparte conexiones entre workers

Publicado el: 11/10/2026
Tempo de leitura: 5 minutos
Rack de servidores que representa el balanceo de conexiones con SO_REUSEPORT_LB en Python

SO_REUSEPORT_LB es una opción de socket pensada para distribuir conexiones entrantes entre varios procesos que escuchan en la misma dirección y puerto. En plataformas compatibles, el sistema operativo realiza el reparto en el kernel, de modo que cada worker puede mantener su propio socket de escucha. Esto puede reducir la contención, aprovechar mejor varios núcleos y simplificar ciertos servidores de alto rendimiento.

Qué hace SO_REUSEPORT_LB

La constante aparece en el módulo socket cuando la versión de Python y el sistema operativo ofrecen soporte. Está relacionada con SO_REUSEPORT, pero no conviene asumir que ambas tienen semántica idéntica en todas las plataformas. El objetivo práctico es permitir varios listeners activos y distribuir nuevas conexiones entre ellos.

import socket

if hasattr(socket, "SO_REUSEPORT_LB"):
    print("compatible")
else:
    print("no disponible")

La detección es obligatoria. Una versión reciente de Python no garantiza que el kernel implemente la opción.

Configuración básica

El orden habitual es crear el socket, activar la opción antes de bind(), asociar la dirección y comenzar a escuchar.

import socket

HOST = "127.0.0.1"
PORT = 9000

servidor = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
servidor.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT_LB, 1)
servidor.bind((HOST, PORT))
servidor.listen()

print(f"Escuchando en {HOST}:{PORT}")

Definir la opción después de bind() puede no tener efecto o provocar un error. Por eso debe configurarse antes de vincular el puerto.

Cuándo utilizarla

Es útil en servidores multiproceso donde cada proceso ejecuta su propio bucle de aceptación. Algunos casos son servicios HTTP personalizados, gateways internos, colectores de métricas, servidores de baja latencia y aplicaciones que desean usar varios núcleos sin compartir un único descriptor de escucha.

También puede participar en reinicios graduales, pero no sustituye health checks, drenaje de conexiones, observabilidad ni una estrategia de despliegue bien definida.

Diferencia con SO_REUSEADDR

SO_REUSEADDR suele facilitar la reutilización de una dirección después de reiniciar un servicio, especialmente cuando quedan conexiones en estados como TIME_WAIT. SO_REUSEPORT_LB se centra en varios listeners simultáneos y en la distribución de carga entre ellos.

Las reglas exactas cambian según el sistema. Prueba siempre la combinación real de Python, kernel y configuración de red.

Varios workers en el mismo puerto

Un patrón común inicia varios procesos con la misma función de servidor. Cada worker crea su socket, activa la opción y hace bind sobre el mismo endpoint.

from multiprocessing import Process
import socket

HOST = "127.0.0.1"
PORT = 9000

def worker(numero):
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as servidor:
        servidor.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT_LB, 1)
        servidor.bind((HOST, PORT))
        servidor.listen()
        while True:
            conexion, direccion = servidor.accept()
            with conexion:
                conexion.sendall(f"worker {numero}\n".encode())

if __name__ == "__main__":
    procesos = [Process(target=worker, args=(i,)) for i in range(4)]
    for proceso in procesos:
        proceso.start()
    for proceso in procesos:
        proceso.join()

El ejemplo es didáctico. En producción se necesitan timeouts, señales, límites de recursos, registros estructurados, recuperación de errores y cierre ordenado.

El balanceo no es perfectamente uniforme

El kernel utiliza reglas propias. Cuatro workers no reciben necesariamente exactamente el veinticinco por ciento de las conexiones. La duración de las sesiones, el patrón de tráfico, el hashing y otros detalles pueden producir diferencias.

Mide conexiones aceptadas por proceso, latencia, bytes procesados, errores, CPU y conexiones activas. Lo importante es un equilibrio operativo suficiente.

Cómo probarlo

Una prueba útil crea muchas conexiones independientes. Una única conexión persistente no demuestra distribución porque permanece asociada al worker que la aceptó.

import socket
from collections import Counter

resultados = Counter()
for _ in range(200):
    with socket.create_connection(("127.0.0.1", 9000), timeout=2) as cliente:
        respuesta = cliente.recv(100).decode().strip()
        resultados[respuesta] += 1

print(resultados)

Repite la prueba y añade tráfico con keep-alive si el servicio real usa conexiones persistentes.

Portabilidad y alternativas

La portabilidad es la principal limitación. Referenciar directamente la constante puede fallar en sistemas sin soporte.

opcion = getattr(socket, "SO_REUSEPORT_LB", None)
if opcion is None:
    raise RuntimeError("SO_REUSEPORT_LB no está soportado")

Como alternativas puedes usar un listener único compartido, paso de descriptores, un servidor de aplicaciones que administre workers, un proxy inverso o un balanceador externo.

Seguridad

Todos los procesos que participan en el grupo de listeners deben ejecutarse con identidades y permisos controlados. No permitas que procesos no confiables se unan al mismo puerto. Vincula una interfaz específica cuando el servicio no deba ser público.

La opción no ofrece cifrado, autenticación, validación ni aislamiento. TLS, límites de entrada, control de acceso y protección de recursos siguen siendo necesarios.

Cierre ordenado

Durante un despliegue, un worker debe dejar de aceptar conexiones nuevas, terminar las activas y cerrar su socket. Los demás listeners pueden continuar atendiendo. Las conexiones persistentes permanecen ligadas al proceso original hasta finalizar.

Gestiona señales de terminación, plazos de cierre y métricas de conexiones activas. Evita reiniciar todos los workers al mismo tiempo.

Integración con selectors y asyncio

El socket ya configurado puede registrarse en selectors o integrarse con infraestructura asíncrona. En asyncio, revisa si la API permite pasar un socket preconfigurado para conservar el control del bind.

Como lectura relacionada, consulta asyncio en Python, HTTPSServer en Python, os.timerfd_create en Python y concurrent.interpreters en Python.

Buenas prácticas

Detecta soporte, activa la opción antes de bind, registra qué worker acepta cada conexión, usa timeouts, maneja señales y prueba sobre el sistema objetivo. Documenta la plataforma mínima y conserva una ruta alternativa.

Supervisa límites de archivos abiertos, backlog, errores de accept, memoria y CPU. Más workers no siempre significan más rendimiento.

Errores comunes

Los fallos habituales son activar la opción después de bind, confundirla con SO_REUSEADDR, asumir soporte universal, iniciar demasiados procesos, probar una sola conexión e ignorar el cierre ordenado. También es un error pensar que reemplaza la observabilidad o la planificación de capacidad.

Referencias

Consulta la documentación oficial de socket y la documentación de setsockopt del sistema. Comprueba siempre la versión exacta usada en producción.

Conclusión

SO_REUSEPORT_LB puede ofrecer un modelo claro para listeners multiproceso y repartir nuevas conexiones entre workers independientes. Su utilidad depende de soporte real, medición, cierre ordenado y una alternativa probada. Debe tratarse como una herramienta específica de arquitectura de red, no como una solución automática para todos los problemas de escalabilidad.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Código Python asíncrono en un portátil para inspect.markcoroutinefunction
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    markcoroutinefunction: detecta wrappers async

    Aprende inspect.markcoroutinefunction en Python para identificar wrappers asíncronos, integrar frameworks y evitar detecciones incorrectas.

    Ler mais

    Tempo de leitura: 5 minutos
    10/10/2026
    Código Python para recorrer carpetas y archivos con Path.walk
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    Path.walk: recorre directorios con seguridad

    Aprende Path.walk en Python para recorrer directorios, filtrar archivos, tratar errores y controlar la travesía con seguridad.

    Ler mais

    Tempo de leitura: 5 minutos
    10/10/2026
    Depuración de un proceso Python en terminal con código
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pdb -p: depura procesos Python en ejecución

    Aprende a conectar pdb a un proceso Python en ejecución, inspeccionar la pila y diagnosticar bloqueos de forma segura.

    Ler mais

    Tempo de leitura: 6 minutos
    09/10/2026
    Código Python para representar fracciones exactas
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    fractions.from_number: convierte números en fracciones

    Aprende fractions.from_number en Python para convertir números en fracciones exactas, controlar precisión, validar entradas y evitar redondeos inesperados.

    Ler mais

    Tempo de leitura: 4 minutos
    09/10/2026
    Desarrollador configurando un servidor HTTPS y certificado TLS con Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    HTTPSServer: crea un servidor HTTPS local en Python

    Aprende HTTPSServer en Python para crear servicios HTTPS locales, configurar certificados, usar hilos y comprender sus límites.

    Ler mais

    Tempo de leitura: 4 minutos
    08/10/2026
    Archivos protegidos que representan extracción segura de TAR con Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    tarfile extraction_filter: extrae TAR con seguridad

    Aprende tarfile extraction_filter en Python para extraer archivos TAR con validación, seguridad y control de rutas.

    Ler mais

    Tempo de leitura: 6 minutos
    08/10/2026