2011-11-29 9 views
6

He leído el documento C10K y muchos documentos relacionados sobre la ampliación de un servidor de socket. Todos los caminos apuntan a lo siguiente:Modelo de subprocesamiento y escalado para servidor TCP con epoll

  1. Evite el error clásico de "hilo por conexión".

  2. Prefiero epoll sobre select.

  3. Del mismo modo, el mecanismo asincrónico heredado en Unix puede ser difícil de usar.

Mi servidor TCP simple simplemente escucha las conexiones del cliente en un socket de escucha en un puerto dedicado. Al recibir una nueva conexión, analiza la solicitud y devuelve una respuesta. Luego, con gracia, cierra el zócalo.

Creo que tengo un buen manejo sobre cómo escalar esto en un solo hilo usando epoll. Solo un ciclo que llama a epoll_wait para el socket de escucha, así como para las conexiones de cliente existentes. A su regreso, el código manejará las nuevas conexiones de clientes creando así nuevas, así como la administración del estado de las conexiones existentes, dependiendo de qué socket se haya señalado. Y quizás algo de lógica para administrar los tiempos de espera de conexión, el cierre elegante de los sockets y la asignación eficiente de recursos para cada conexión. Parece lo suficientemente sencillo.

Pero, ¿y si quiero escalar esto para aprovechar múltiples hilos y múltiples núcleos de CPU? La idea central que me viene a la mente es la siguiente:

Un hilo dedicado para escuchar las conexiones entrantes en el socket de escucha TCP. Luego, un conjunto de N subprocesos (o grupo de subprocesos) para manejar todas las conexiones de cliente simultáneas activas. A continuación, invente una forma segura de subprocesos en la que el subproceso de escucha "envíe" la nueva conexión (socket) a uno de los subprocesos de trabajo disponibles. (ala IOCP en Windows). El subproceso de trabajo utilizará un bucle de epoll en todas las conexiones que maneja para hacer lo que haría el enfoque de subproceso único.

¿Estoy en el camino correcto? ¿O hay un patrón de diseño estándar para hacer un servidor TCP con epoll en múltiples hilos?

Sugerencias sobre cómo el hilo de escucha distribuirá una nueva conexión al grupo de subprocesos?

+0

Si su elección de idioma es flexible, puede probar http://vibed.org/, que abstrae la naturaleza asincrónica de la programación asincrónica para que pueda programar de forma sincronizada. p. ubyte [] buf = new ubyte [] (1024); auto data = conn.read (buf); conn.write (datos); – rmc

Respuesta

-1

Supongo que está en el camino correcto. Pero también creo que los detalles dependen de la situación particular (bandwidh, patrones de solicitud, procesamiento de solicitudes indifidual, etc.). Creo que deberías intentarlo, y compararlo cuidadosamente.

2
  1. En primer lugar, tenga en cuenta que es C * 10K *. No se preocupe si tiene menos de 100 (en un sistema típico). Incluso entonces depende de qué están haciendo sus conectores.
  2. Sí, pero tenga en cuenta que la manipulación epoll requiere llamadas al sistema, y ​​su costo puede o no ser más costoso que el costo de administrar unos pocos fd_set s usted mismo. Lo mismo ocurre con poll. A bajo conteo es más barato hacer el procesamiento en el espacio de usuario de cada iteración.
  3. I/O asincrónico es muy doloroso cuando no está limitado a unos pocos zócalos que puede hacer malabares según sea necesario. La mayoría de las personas se las arregla mediante el uso de bucles de eventos, pero esto fragmenta e invierte el flujo de su programa.También suele requerir el uso de marcos grandes e inmanejables para este fin, ya que un ciclo de eventos confiable y rápido no es fácil de corregir.

La primera pregunta es, ¿la necesita? Si está lidiando fácilmente con el tráfico existente generando hilos para manejar cada solicitud entrante, entonces continúe haciéndolo de esta manera. El código será más simple para él, y todas sus bibliotecas jugarán muy bien.

Como mencioné anteriormente, hacer malabares con solicitudes simultáneas puede ser complejo. Si desea hacer esto en un solo bucle, también deberá hacer garantías sobre la inanición de CPU al generar sus respuestas.

El modelo de envío que ha propuesto es la solución de primer paso típica si sus respuestas son caras de generar. Puede bifurcar o usar hilos. El costo de bifurcación o generación de un hilo no debe ser una consideración al seleccionar un mecanismo de agrupamiento: en su lugar, debe utilizar dicho mecanismo para limitar o solicitar la carga colocada en el sistema.

Enchufar sockets en múltiples bucles epoll es excesivo. Usa múltiples procesos si estás desesperado. Tenga en cuenta que es posible accept en un socket de múltiples hilos y procesos.

+0

Matt, en realidad todavía no he escrito el núcleo de red TCP. Así que, obviamente, no veo ninguna razón para comenzar con el modelo de "hilo por conexión" si hay un mejor patrón de diseño para considerar primero. ¿Se dice que "seleccionar" es más barato que epoll para conteos de bajo conteo? ¿Puede profundizar en el tema de la "falta de CPU"? Estoy de acuerdo con el punto de diseño de equilibrio de carga. Y he considerado que todos los hilos múltiples bloqueados aceptan. – selbie

Cuestiones relacionadas