¿Qué sucede si comienzo demasiados trabajos en segundo plano?

13

Necesito trabajar en 700 dispositivos de red con un script de esperar. Puedo hacerlo secuencialmente, pero hasta ahora el tiempo de ejecución es de alrededor de 24 horas. Esto se debe principalmente al tiempo que lleva establecer una conexión y al retraso en la salida de estos dispositivos (los antiguos). Puedo establecer dos conexiones y hacer que funcionen en paralelo muy bien, pero ¿hasta dónde puedo llevar eso?

No me imagino que podría hacer los 700 a la vez, seguramente hay un límite para el no. de conexiones telnet que mi VM puede administrar.

Si intenté iniciar 700 de ellos en algún tipo de bucle como este:

for node in `ls ~/sagLogs/`; do  
    foo &  
done

Con

  • CPU 12 CPU x Intel (R) Xeon (R) CPU E5649 @ 2.53GHz

  • Memoria 47.94 GB

Mi pregunta es:

  1. ¿Podrían todas las 700 instancias ejecutarse simultáneamente?
  2. ¿Hasta dónde podría llegar hasta que mi servidor alcance su límite?
  3. Cuando se alcanza ese límite, ¿esperará para comenzar la próxima iteración fooo la caja se estrellará?

Desafortunadamente, me estoy ejecutando en un entorno de producción corporativo, por lo que no puedo simplemente intentar ver qué sucede.

KuboMD
fuente
3
He tenido buena suerte con el paralleluso de alrededor de 50 trabajos simultáneos. Es un gran medio entre el paralelismo de 1 y 700. La otra cosa buena es que no tiene lotes. Una sola conexión bloqueada solo se bloqueará sola, no ninguna de las otras. El principal inconveniente es la gestión de errores. Ninguno de estos enfoques basados ​​en shell manejará con gracia los errores. Tendrá que verificar manualmente el éxito usted mismo y hacer sus propios reintentos.
Adam
1
Su cola de tareas puede ser 700 hoy, pero ¿puede expandirse el tamaño? Esté atento a que crezca el espacio de intercambio, eso es una indicación de que ha alcanzado el límite de memoria. Y cpu% no es una buena medida (para Linux / Unix), mejor considerar el promedio de carga (longitud de la cola de ejecución).
ChuckCottrill
1
La forma más reciente en que interrumpí la producción en mi trabajo aún un poco nuevo fue ejecutando accidentalmente más de un millón de trabajos de fondo de corta duración a la vez. Involucraban JVM (esperar, esperar, bajar las horquillas), por lo que las consecuencias estaban 'limitadas' a cientos de miles de archivos de informes de errores que los hilos no podían iniciarse.
michaelb958 - GoFundMonica
44
Nitpick: No analizar la lssalida
l0b0
1
@KuboMD Y mientras nadie más quiera usar tu código.
l0b0

Respuestas:

17

¿Podrían todas las 700 instancias ejecutarse simultáneamente?

Eso depende de lo que quieras decir al mismo tiempo Si estamos siendo exigentes, entonces no, no pueden a menos que tenga 700 hilos de ejecución en su sistema que pueda utilizar (probablemente no). De manera realista, sí, probablemente puedan, siempre que tenga suficiente RAM y / o espacio de intercambio en el sistema. UNIX y sus diversos niños son notablemente buenos en la gestión de grandes niveles de concurrencia, eso es parte de por qué son tan populares para el uso de HPC a gran escala.

¿Hasta dónde podría llegar hasta que mi servidor alcance su límite?

Esto es imposible de responder concretamente sin mucha más información. Más o menos, necesitas tener suficiente memoria para cumplir:

  • Los requisitos de memoria de tiempo de ejecución completo de un trabajo, multiplicado por 700.
  • Los requisitos de memoria de bash para administrar tantos trabajos (bash no es horrible sobre esto, pero el control del trabajo no es exactamente eficiente en memoria).
  • Cualquier otro requisito de memoria en el sistema.

Suponiendo que cumple con eso (nuevamente, con solo 50 GB de RAM, todavía tiene que lidiar con otros problemas:

  • ¿Cuánto tiempo de CPU perderá bash en el control del trabajo? Probablemente no mucho, pero con cientos de trabajos, podría ser significativo.
  • ¿Cuánto ancho de banda de red va a necesitar esto? Solo abrir todas esas conexiones puede inundar su red durante un par de minutos, dependiendo de su ancho de banda y latencia.
  • Probablemente no haya pensado en muchas otras cosas.

Cuando se alcanza ese límite, ¿esperará para comenzar la próxima iteración o la caja se estrellará?

Depende de qué límite se alcanza. Si se trata de memoria, algo morirá en el sistema (más específicamente, el núcleo lo matará en un intento de liberar memoria) o el sistema en sí puede fallar (no es inusual configurar sistemas para que se bloqueen intencionalmente cuando se está quedando sin memoria). Si es tiempo de CPU, continuará sin problemas, será imposible hacer mucho más en el sistema. Sin embargo, si se trata de la red, podría bloquear otros sistemas o servicios.


Lo que realmente necesita aquí es no ejecutar todos los trabajos al mismo tiempo. En su lugar, divídalos en lotes y ejecute todos los trabajos dentro de un lote al mismo tiempo, déjelos terminar y luego comience el siguiente lote. Para esto se puede usar GNU Parallel ( https://www.gnu.org/software/parallel/ ), pero es menos que ideal a esa escala en un entorno de producción (si lo utiliza, no se ponga demasiado agresivo, como dije, podría inundar la red y afectar los sistemas que de otro modo no estaría tocando). Realmente recomendaría buscar una herramienta de orquestación de red adecuada como Ansible ( https://www.ansible.com/), ya que eso no solo resolverá sus problemas de concurrencia (Ansible procesa por lotes como mencioné anteriormente de forma automática), sino que también le brinda muchas otras características útiles para trabajar (como la ejecución idempotente de tareas, buenos informes de estado e integración nativa con una gran cantidad de otras herramientas).

Austin Hemmelgarn
fuente
Hay formas de ejecutar un número limitado de tareas en segundo plano (usando bash, perl, python, et al), monitorear la finalización de la tarea y ejecutar más tareas a medida que se completan las tareas anteriores. Un enfoque simple sería recopilar lotes de tareas representadas por archivos en subdirectorios y procesar un lote a la vez. Hay otras formas ...
ChuckCottrill
¿Esto también incluye sistemas similares a Unix? ¿Y qué es "PISTOLA paralela"?
Biswapriyo
2
@ChuckCottrill Sí, de hecho, hay otras formas en que esto podría hacerse. Sin embargo, dada mi propia experiencia al tratar con este tipo de cosas, casi siempre es mejor obtener una herramienta de orquestación real que intentar rodar su propia solución, especialmente una vez que haya pasado unas pocas docenas de sistemas en términos de escala.
Austin Hemmelgarn
3
@forest Sí, podría usar límites para evitar que el sistema se bloquee, pero hacerlos bien en un caso como este no es fácil (necesita saber cuáles son los requisitos de recursos para las tareas de antemano) y no protege el resto de la red por cualquier impacto que puedan causar estos trabajos (lo cual podría decirse que es un problema potencialmente mucho mayor que la caída del sistema local).
Austin Hemmelgarn
12

Es difícil decir específicamente cuántas instancias podrían ejecutarse como trabajos en segundo plano de la manera que usted describe. Pero un servidor normal ciertamente puede mantener 700 conexiones concurrentes siempre que lo haga correctamente. Los servidores web hacen esto todo el tiempo.

¿Puedo sugerirle que use GNU paralelo ( https://www.gnu.org/software/parallel/ ) o algo similar para lograr esto? Le daría una serie de ventajas al enfoque de trabajo en segundo plano:

  • Puede cambiar fácilmente la cantidad de sesiones concurrentes.
  • Y esperará hasta que se completen las sesiones antes de comenzar nuevas.
  • Es más fácil abortar.

Eche un vistazo aquí para comenzar rápidamente: https://www.gnu.org/software/parallel/parallel_tutorial.html#A-single-input-source

laenkeio
fuente
1
¡Interesante! Echaré un vistazo a esto. ¿Sabe si intentar este tipo de operación (sin la ayuda de Parallel) correría el riesgo de bloquear el hipervisor?
KuboMD
2
@KuboMD si puedes bloquear el hipervisor con algo tan mundano, es un error en el hipervisor :)
hobbs
Por otro lado, los servidores web a menudo usan subprocesos o procesamiento basado en eventos (ejemplo: gunicorn.org )
ChuckCottrill
10

El uso &para el procesamiento en paralelo está bien cuando se hacen algunos y al monitorear el progreso. Pero si está ejecutando en un entorno de producción corporativo, necesita algo que le brinde un mejor control.

ls ~/sagLogs/ | parallel --delay 0.5 --memfree 1G -j0 --joblog my.log --retries 10 foo {}

Esto se ejecutará foopara cada archivo en ~/sagLogs. Inicia un trabajo cada 0,5 segundos, ejecutará tantos trabajos en paralelo como sea posible siempre que 1 GB de RAM esté libre, pero respetará los límites de su sistema (por ejemplo, número de archivos y procesos). Por lo general, esto significa que ejecutará 250 trabajos en paralelo si no ha ajustado la cantidad de archivos abiertos permitidos. Si ajusta la cantidad de archivos abiertos, no debería tener problemas para ejecutar 32000 en paralelo, siempre que tenga suficiente memoria.

Si un trabajo falla (es decir, regresa con un código de error), se volverá a intentar 10 veces.

my.log le dirá si un trabajo tuvo éxito (después de posibles reintentos) o no.

Ole Tange
fuente
Esto parece muy prometedor, gracias.
KuboMD
Realicé una prueba simple haciendo cat ~/sagLogs/* >> ~/woah | parallely santo moly que fue rápido. 1,054,552 líneas en un abrir y cerrar de ojos.
KuboMD
3
El comando que le diste tiene doble redirección, así que no creo que haga lo que pretendes que haga. GNU Parallel tiene una sobrecarga de 10 ms por trabajo, por lo que 1M de trabajos debería tomar del orden de 3 horas.
Ole Tange
1
No es aplicable en absoluto si todo lo que quiere hacer es simplemente concatenar los archivos.
Ole Tange
1
@KuboMD, un circuito ocupado de CPU trivial como awk 'BEGIN{for(i=rand()*10000000; i<100000000;i++){}}' funcionaría para jugar. O pruébelo en una tarea como sleep 10ver que mantiene los ntrabajos en vuelo sin usar mucho tiempo de CPU. por ejemplo, time parallel sleep ::: {100..1}duerme desde 100 hasta 1 segundo.
Peter Cordes el
1

¿Qué sucede si comienzo demasiados trabajos en segundo plano?

el sistema se volverá lento e insensible, el peor de los casos es tan insensible que sería mejor presionar el botón de encendido y reiniciar con fuerza ... esto sería ejecutar algo como root donde tenía el privilegio de salirse con la suya. Si su escritura del golpe se ejecuta con privilegios de usuario normal, y la primera cosa que viene a la mente es /etc/security/limits.confy /etc/systemd/system.conf, y todas las variables en ella a [Idealmente hablando] prevenir usuario (s) de la sobrecarga del sistema.

  • cpu = xeon E5649, que es una cpu de 12 núcleos ; por lo tanto, tiene 12 núcleos para que 12 procesos se ejecuten simultáneamente utilizando cada uno de los doce núcleos al 100%. Si inicia 24 procesos, cada uno se ejecutará al 50% de utilización en cada uno de los doce núcleos, 700 procesos = 1.7%, pero es una computadora siempre que todo se complete correctamente en un período de tiempo correcto, entonces eso = éxito; ser eficiente no siempre es relevante.

    1. ¿Podrían todas las 700 instancias ejecutarse simultáneamente? Ciertamente, 700 no es un gran número; mi /etc/security/limits.conf maxprocpredeterminado es 4,135,275 por ejemplo

    2. ¿Hasta dónde podría llegar hasta que mi servidor alcance su límite? Mucho más allá de 700 estoy seguro.

    3. Límites ... lo que sucederá si el script se inicia con una cuenta de usuario [y generalmente la raíz también se limits.confaplica a casi todos] es que el script simplemente saldrá después de haber intentado hacerlo foo &700 veces; entonces esperaría ver 700 procesos foo , cada uno con un pid diferente, pero es posible que solo vea 456 (elección de número aleatorio) y los otros 244 nunca comenzaron porque se bloquearon por algún límite de seguridad o systemd.

Pregunta de millones de dólares: ¿cuántos debería ejecutar simultáneamente?

al estar involucrado con la red y usted dijo que cada uno hará una conexión telnet, una suposición educada es que se encontrará con los límites de la red y los gastos generales antes de hacerlo para los límites de CPU y RAM. Pero no sé qué está haciendo específicamente, lo que probablemente sucederá es que puede iniciar los 700 a la vez, pero las cosas se bloquearán automáticamente hasta que los procesos anteriores y las conexiones de red terminen y se cierren en función de varios límites del sistema, o algo así como los primeros 500 comenzarán, luego los 200 restantes no lo harán porque los límites del sistema o del núcleo lo impiden. Pero por más que corran a la vez, habrá algo de dulzura.lugar para hacer las cosas lo más rápido posible ... minimizando los gastos generales y aumentando la eficiencia. Con 12 núcleos (o 24 si tiene 2 CPU), comience con 12 (o 24) a la vez y luego aumente ese número de lote concurrente en 12 o 24 hasta que no vea una mejora en el tiempo de ejecución.

pista: conexiones de google max telnet y vea cómo esto se aplica a su (s) sistema (s). Tampoco te olvides de los firewalls. También haga un cálculo rápido de la memoria necesaria por proceso x 700; asegúrese de <RAM disponible (aproximadamente 50 gb en su caso) de lo contrario el sistema comenzará a usar SWAP y básicamente no responderá. Entonces, inicie 12, 24, N procesos a la vez y monitoree la RAM libre, luego aumente N ya teniendo algún conocimiento de lo que está sucediendo.

Por defecto, RHEL limita el número de conexiones telnet de un único host a 10 sesiones simultáneas. Esta es una característica de seguridad ... establecida en 10, /etc/xinetd.conf, cambie el valor "per_source".

ron
fuente