¿Cómo elimino a los trabajadores de Resque atascados / obsoletos?

132

Como puede ver en la imagen adjunta, tengo un par de trabajadores que parecen estar atascados. Esos procesos no deberían tomar más de un par de segundos.

ingrese la descripción de la imagen aquí

No estoy seguro de por qué no se borrarán o cómo eliminarlos manualmente.

Estoy en Heroku usando Resque con Redis-to-Go y HireFire para escalar automáticamente a los trabajadores.

Shpigford
fuente
2
Hola, pregunta semi-relacionada: ¿cómo obtuviste el tablero resque-web a través de heroku? Parece que no puedo entender cómo abrirlo.
Aaron Marks

Respuestas:

215

Ninguna de estas soluciones funcionó para mí, todavía vería esto en redis-web:

0 out of 10 Workers Working

Finalmente, esto funcionó para mí para despejar a todos los trabajadores:

Resque.workers.each {|w| w.unregister_worker}
hagope
fuente
12
Esto funcionó para mí. No registró a todos los trabajadores, lo cual fue un poco molesto. Pero esto seguido heroku restartparecía hacer el truco. Ahora muestra el número correcto de trabajadores.
Brian Armstrong
Esto eliminó a los trabajadores de la interfaz web, pero en realidad todavía aparecen como procesos y también "robaron" trabajos de la cola
txwikinger
20
Si desea anular el registro solo de los trabajadores que no son procesos reales (y tal vez procesar trabajos), es posible que desee probar Resque.workers.each {|w| matches = w.id.match(/^[^:]*:([0-9]*):[^:]*$/); pid = matches[1]; w.unregister_worker unless w.worker_pids.include?(pid.to_s)}cuál solo anulará el registro de aquellos trabajadores cuyos pids no forman parte de los pids en ejecución conocidos. No sé si esto funciona en todos los entornos, pero funciona bien en ubuntu. Esto solo puede funcionar cuando sus trabajadores están en la misma máquina en la que ejecuta este código.
roychri
3
Como opción Resque.workers.map &: unregister_worker
AB
¿Cómo es que esto no incluye una verificación de si el trabajador no debe estar registrado antes de llamar unregister_worker? ¿Hay alguna manera de determinar esto?
user5243421
53

En tu consola:

queue_name = "process_numbers"
Resque.redis.del "queue:#{queue_name}"

De lo contrario, puede intentar simularlos para eliminarlos, con:

Resque::Worker.working.each {|w| w.done_working}

EDITAR

Mucha gente ha votado a favor de esta respuesta y creo que es importante que la gente pruebe la solución de hagope que elimina el registro de los trabajadores de una cola, mientras que el código anterior elimina las colas. Si estás feliz de fingirlos, entonces genial.

Simplón
fuente
3
Si hace esto, eliminará toda la cola, solo quiere eliminar los que están atascados ..
jBeas
1
Pequeña actualización: ahora debe usar Resque.redis.del en lugar de Resque.redis.delete
James P McGrath el
1
En realidad, ahora hay un método Resque.remove_queue ()
iainbeeston
28

Probablemente tenga instalada la gema de resque, por lo que puede abrir la consola y obtener los trabajadores actuales

Resque.workers

Devuelve una lista de trabajadores.

#=> [#<Worker infusion.local:40194-0:JAVA_DYNAMIC_QUEUES,index_migrator,converter,extractor>]

elegir al trabajador y prune_dead_workers, por ejemplo, el primero

Resque.workers.first.prune_dead_workers
Shairon Toledo
fuente
1
En realidad, en el segundo intento, esto no hizo nada.
Shpigford
2
Esto funciona muy bien para eliminar a los trabajadores que fueron asesinados sin darse de baja.
Lukas Eklund
3
Esta parece ser la nueva mejor respuesta, ya que no anula el registro de todas ellas. ¿No debería ser prune_dead_workers un método de clase? Pero en cualquier caso, ¡gran solución! Gracias.
Brian Armstrong
Esa es definitivamente la solución para los trabajadores muertos -9. Lo único que agregaría es que debes hacerlo en el mismo servidor donde mataste con -9.
Stanislav O. Pogrebnyak
Hazlo a todos a la vez: Resque.workers.each (&: prune_dead_workers)
Leo
25

Agregando a la respuesta por hagope, quería poder cancelar el registro de los trabajadores que habían estado funcionando durante un cierto período de tiempo. El siguiente código solo anulará el registro de los trabajadores que se ejecutan durante más de 300 segundos (5 minutos).

Resque.workers.each {|w| w.unregister_worker if w.processing['run_at'] && Time.now - w.processing['run_at'].to_time > 300}

Tengo una colección continua de tareas de Rake relacionadas con Resque a las que también he agregado esto en: https://gist.github.com/ewherrmann/8809350

ewH
fuente
3
Puntos para mostrar cómo acceder a la hora de inicio del trabajo a través del procesamiento ['run_at']. He visto otras soluciones que están utilizando el método .started, pero esto realmente devuelve el momento en que se inició el trabajador , no el trabajo, que es el enfoque incorrecto para liberar a los trabajadores atascados. ¡Gracias!
Lachlan Cotter
10

Ejecute este comando donde sea que haya ejecutado el comando para iniciar el servidor

$ ps -e -o pid,command | grep [r]esque

Debería ver algo como esto:

92102 resque: Processing ProcessNumbers since 1253142769

Tome nota del PID (id de proceso) en mi ejemplo, es 92102

Luego puede salir del proceso de 1 a 2 formas.

  • Usar con gracia QUIT 92102

  • Usar con fuerza TERM 92102

* No estoy seguro de la sintaxis que es QUIT 92102oQUIT -92102

Avísame si tienes algún problema.

jBeas
fuente
3
En la consola de Linux: kill -SIGQUIT 92102
Alexey
6

Lo acabo de hacer:

% rails c production
irb(main):001:0>Resque.workers

Tengo la lista de trabajadores.

irb(main):002:0>Resque.remove_worker(Resque.workers[n].id)

... donde n es el índice basado en cero del trabajador no deseado.

usuario2811637
fuente
2

Tuve un problema similar que Redis guardó la base de datos en el disco que incluía trabajadores no válidos (no en ejecución). Cada vez que se iniciaba Redis / resque aparecían.

Solucione esto usando:

Resque::Worker.working.each {|w| w.done_working}
Resque.redis.save # Save the DB to disk without ANY workers

Asegúrese de reiniciar Redis y sus trabajadores de Resque.

joost
fuente
2

Así es como puede purgarlos de Redis por nombre de host. Esto me sucede cuando desmantelo un servidor y los trabajadores no salen con gracia.

Resque.workers.each { |w| w.unregister_worker if w.id.start_with?(hostname) }
Rich Sutton
fuente
2

Me encontré con este problema y comencé a implementar muchas de las sugerencias aquí. Sin embargo, descubrí que la causa raíz que estaba creando este problema era que estaba usando la gema redis-rb 3.3.0 . La degradación a redis-rb 3.2.2 evitó que estos trabajadores se atascaran en primer lugar.

Will Bryant
fuente
1

Comenzó a trabajar en https://github.com/shaiguitar/resque_stuck_queue/ recientemente. No es una solución sobre cómo reparar a los trabajadores atascados, pero aborda el problema del bloqueo / bloqueo de resque, por lo que pensé que podría ser útil para las personas en este hilo. De README:

"Si resque no ejecuta trabajos dentro de un período de tiempo determinado, activará un controlador predefinido de su elección. Puede usar esto para enviar un correo electrónico, buscar localizador, agregar más trabajadores de resque, reiniciar resque, enviarle un mensaje de texto. ..lo que te venga bien."

Se ha utilizado en producción y funciona bastante bien para mí hasta ahora.

Shai
fuente
0

Aquí también tuve trabajadores atascados / atrasados, o debería decir 'trabajos', porque el trabajador todavía está allí y funciona bien, es el proceso bifurcado el que está atascado.

Elegí la solución brutal de matar el proceso bifurcado "Procesando" desde hace más de 5 minutos, a través de un script bash, luego el trabajador genera el siguiente en la cola, y todo continúa

Echa un vistazo a mi script aquí: https://gist.github.com/jobwat/5712437

Jobwat
fuente
0

Los eliminé de redis-cli directamente. Afortunadamente, redistogo.com permite el acceso desde entornos externos a heroku. Obtenga la identificación del trabajador muerto de la lista. El mío era

55ba6f3b-9287-4f81-987a-4e8ae7f51210:2

Ejecute este comando en redis directamente.

del "resque:worker:55ba6f3b-9287-4f81-987a-4e8ae7f51210:2:*"

Puede monitorear redis db para ver qué está haciendo detrás de escena.

redis xxx.redistogo.com> MONITOR
OK
1380274567.540613 "MONITOR"
1380274568.345198 "incrby" "resque:stat:processed" "1"
1380274568.346898 "incrby" "resque:stat:processed:c65c8e2b-555a-4a57-aaa6-477b27d6452d:2:*" "1"
1380274568.346920 "del" "resque:worker:c65c8e2b-555a-4a57-aaa6-477b27d6452d:2:*"
1380274568.348803 "smembers" "resque:queues"

La segunda última línea elimina al trabajador.

Andrei R
fuente
No es Buena idea. Esto no llamará a anzuelos para cancelar el registro en Resque, no llamará a la falla y al posible código de limpieza que las personas puedan tener.
Jeremy
Esto fue útil con resque hace 2 años cuando mostraba trabajos atascados que eran imposibles de eliminar usando la interfaz y no había una forma limpia de hacerlo en los rieles
Andrei R
0

Si está utilizando versiones más nuevas de Resque, deberá usar el siguiente comando ya que las API internas han cambiado ...

Resque::WorkerRegistry.working.each {|work| Resque::WorkerRegistry.remove(work.id)}
lloydpick
fuente
0

Esto evita el problema siempre que tenga una versión de revisión más reciente que 1.26.0:

resque: env QUEUE=foo TERM_CHILD=1 bundle exec rake resque:work

Tenga en cuenta que no permite que finalice el trabajo actualmente en ejecución.

Joakim Kolsjö
fuente
0

También puede usar el siguiente comando para detener a todos los rescuetrabajadores

sudo kill -9  `ps aux | grep resque | grep -v grep | cut -c 10-16`

referencia desde este enlace

uzaif
fuente