2010-02-06 13 views
29

Muchos libros de programación y tutoriales de Linux/Unix hablan sobre el "Thundering Herd Problem" que ocurre cuando se bloquean varios hilos u horquillas en una llamada select() esperando la legibilidad de un socket de escucha. Cuando la conexión entra, todos los hilos y las horquillas se despiertan, pero solo uno "gana" con una llamada exitosa a "accept()". Mientras tanto, se desperdicia mucho tiempo de CPU despertando todos los hilos/tenedores sin ningún motivo.¿Ya existe el problema del rebaño Thundering en Linux?

Me di cuenta de un project que proporciona una "solución" para este problema en el kernel de Linux, pero este es un parche muy antiguo.

Creo que hay dos variantes; Uno donde cada tenedor selecciona() y luego acepta(), y uno que simplemente acepta().

¿Los kernels modernos de Unix/Linux aún tienen el problema Thundering Herd en estos casos o solo en la versión "select() then accept()"?

+1

nunca oído hablar de esto, pero un montón de cosas el "núcleo de Linux hace mal", definitivamente no es cierto por más tiempo! –

+1

Esa es una pregunta muy interesante. Sería realmente difícil manejarlo bien en el caso de 'seleccionar' y luego 'aceptar' porque no puede garantizar que el proceso que está haciendo 'seleccionar' eventualmente 'acepte'.Creo que alguien debería hacer una prueba para averiguarlo, y quizás probar 'epoll' también. – Omnifarious

Respuesta

9

Durante años, la mayoría de los kernels de Unix/Linux serializan la respuesta para aceptar (2) s, en otras palabras, solo un subproceso se activa si hay más de uno bloqueando accept (2) contra una sola descripción de archivo abierto.

OTOH, muchos (si no todos) los kernels todavía tienen el problema del rebaño atronador en el patrón de seleccionar y aceptar que usted describe.

He escrito un script simple (https://gist.github.com/kazuho/10436253) para verificar la existencia del problema, y ​​descubrí que el problema existe en Linux 2.6.32 y Darwin 12.5.0 (OS X 10.8.5).

+0

¡Gracias por la breve prueba! Como referencia, intenté ejecutarlo en modo select-accept en Linux 3.2.0-58: $ perl thundering-herd.pl seleccionar-aceptar conectado! at thundering-herd.pl línea 49. accept failed: Recurso temporalmente no disponible en thundering-herd.pl línea 52. - Y en modo 'accept', no hay truenos. – jdkoftinoff

+0

Esto me dice que el problema del rebaño atronador todavía existe y esto significa que uno debe tener todos los hilos aceptando() sin seleccionar() o tener un hilo haciendo select() y luego accept() y luego pasar el fd a un hilo de trabajo para el procesamiento. – jdkoftinoff

+0

Este problema también existe en mi ubuntu 8.04 (linux 2.6.24) – ASBai

10

Este es un problema muy antiguo, y en su mayor parte ya no existe. El kernel de Linux (en los últimos años) ha tenido una serie de cambios en la forma en que maneja y enruta los paquetes en la pila de red, e incluye muchas optimizaciones para garantizar baja latencia y equidad (es decir, minimizar la inanición).

Dicho esto, sistema select tiene una serie de problemas de escalabilidad simplemente a través de su API. Cuando tiene una gran cantidad de descriptores de archivos, el costo de una llamada de selección es muy alto. Esto se debe principalmente a tener que construir, verificar y mantener los conjuntos de FD que se transfieren ay desde la llamada al sistema.

Hoy en día, la forma preferida de hacer asincrónico IO es con epoll. La API es mucho más simple y escala muy bien en varios tipos de carga (muchas conexiones, gran cantidad de rendimiento, etc.)

+0

Estoy pensando en la situación en la que solo hay un socket por horquilla y el socket está bloqueando. Así que epoll() vs poll() vs select() no importa aquí. ¿Tiene linux un comportamiento especial de activación de tareas para los sockets de escucha ahora? – jdkoftinoff

+0

Sí, IIRC, la implementación ahora solo despierta un hilo (en lugar de despertar todos los hilos y hacer que compitan). Cómo selecciona el hilo es complicado, pero la respuesta simple es: se basa en la prioridad, por lo que depende en el programador para mantener la equidad. De todos modos, ese problema de pastoreo específico ya no existe, por lo que la situación no es tan grave en caso de sobrecarga. Dicho todo esto, usar select en lugar de epoll implica un costo de CPU más alto (tanto en el kernel como en el espacio de usuario), que es, IMO, insignificante para su caso de uso. – 0xfe

+0

¿Y qué pasa si ese hilo no hace un 'aceptar'? – Omnifarious

2

Recientemente vi probado un escenario en el que varios subprocesos sondearon en un socket de dominio de dominio de escucha y luego aceptaron el conexión. Todos los subprocesos se activaron con la llamada al sistema poll().

Esta fue una compilación personalizada del núcleo de Linux en lugar de una compilación de distribución, por lo que tal vez haya una opción de configuración del kernel que la cambie, pero no sé cuál sería.

No probamos epoll.

2

Consulte el siguiente enlace que habla sobre banderas separadas para epoll para evitar este problema.

http://lwn.net/Articles/632590/

+1

y también en http://lwn.net/Articles/633422/ que se refiere a la nueva bandera EPOLLEXCLUSIVE que se agregará ... –

Cuestiones relacionadas