Como limpo trabalhadores Resque presos ou obsoletos?

132

Como você pode ver na imagem em anexo, tenho alguns trabalhadores que parecem estar presos. Esses processos não devem demorar mais que alguns segundos.

insira a descrição da imagem aqui

Não sei por que eles não serão limpos ou como removê-los manualmente.

Estou no Heroku usando o Resque com Redis-to-Go e HireFire para dimensionar automaticamente os trabalhadores.

Shpigford
fonte
2
Olá, pergunta semi-relacionada: como você conseguiu o painel resque-web via heroku? Não consigo descobrir como abri-lo.
Aaron Marcas

Respostas:

215

Nenhuma dessas soluções funcionou para mim; eu ainda veria isso no redis-web:

0 out of 10 Workers Working

Finalmente, funcionou para mim limpar todos os trabalhadores:

Resque.workers.each {|w| w.unregister_worker}
hagope
fonte
12
Isso funcionou para mim. Não registrou todos os trabalhadores, o que foi um pouco chato. Mas isso seguido por heroku restartparecia fazer o truque. Agora, mostra o número correto de trabalhadores.
27712 Brian Armstrong
Isso levou os trabalhadores a partir da interface web, mas na verdade eles ainda aparecem como processos e também "roubou" trabalhos da fila
txwikinger
20
Se você deseja cancelar o registro apenas dos trabalhadores que não são processos reais (e talvez processando trabalhos), convém tentar Resque.workers.each {|w| matches = w.id.match(/^[^:]*:([0-9]*):[^:]*$/); pid = matches[1]; w.unregister_worker unless w.worker_pids.include?(pid.to_s)}que apenas cancelará o registro dos trabalhadores cujos pids não fazem parte dos pids em execução conhecidos. Não sei se isso funciona em todos os ambientes, mas funciona bem no ubuntu. Isso pode funcionar apenas quando seus funcionários estiverem na mesma máquina em que você executa esse código.
roychri
3
Como uma opção Resque.workers.map &: unregister_worker
AB
Por que isso não inclui uma verificação para verificar se o trabalhador deve ser registrado antes de ligar unregister_worker? Existe uma maneira de determinar isso?
User5243421 10/10
53

No seu console:

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

Caso contrário, você pode tentar falsificá-los como sendo feitos para removê-los, com:

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

EDITAR

Muitas pessoas estão votando positivamente nesta resposta e eu sinto que é importante que as pessoas tentem a solução do hagope que cancela o registro de trabalhadores de uma fila, enquanto o código acima exclui filas. Se você está feliz em falsificá-los, então legal.

Simplório
fonte
3
Se ele faz isso, ele vai apagar toda a fila, ele só quer remover os presos ..
jBeas
1
Pequena atualização: Você agora tem que usar Resque.redis.del vez de Resque.redis.delete
James P McGrath
1
Na verdade, há um método Resque.remove_queue () agora
iainbeeston
28

Você provavelmente tem a gem resque instalada, para poder abrir o console e obter trabalhadores atuais

Resque.workers

Retorna uma lista de trabalhadores

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

escolha o trabalhador e prune_dead_workers, por exemplo, o primeiro

Resque.workers.first.prune_dead_workers
Shairon Toledo
fonte
1
Na verdade, na segunda tentativa, isso não fez nada.
Shpigford 23/09
2
Isso funciona muito bem para limpar os trabalhadores que foram mortos sem cancelar o registro.
Lukas Eklund
3
Essa parece ser a nova melhor resposta, pois não cancela o registro de todas elas. Prune_dead_workers não deve ser um método de classe? Mas, de qualquer forma, ótima solução! Obrigado.
Brian Armstrong
Essa é definitivamente a solução para -9 trabalhadores mortos. A única coisa que eu acrescentaria é que você precisa fazer isso no mesmo servidor em que matou com -9.
Stanislav O. Pogrebnyak 27/03
Faça isso para todos eles de uma vez: Resque.workers.each (&: prune_dead_workers)
Leo
25

Além de responder por hagope, eu queria poder cancelar apenas o registro de trabalhadores que estavam em execução por um determinado período de tempo. O código abaixo cancelará o registro de trabalhadores em execução por mais 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}

Tenho uma coleção contínua de tarefas Rake relacionadas ao Resque às quais também adicionei isso: https://gist.github.com/ewherrmann/8809350

ewH
fonte
3
Pontos para mostrar como acessar o horário de início do trabalho através do processamento ['run_at']. Eu já vi outras soluções que estão usando o método .started, mas isso realmente retorna o horário em que o trabalhador foi iniciado, não o trabalho, que é a abordagem errada para limpar os trabalhadores presos. Obrigado!
Lachlan Cotter
10

Execute este comando onde quer que você tenha executado o comando para iniciar o servidor

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

você deve ver algo assim:

92102 resque: Processing ProcessNumbers since 1253142769

Anote o PID (identificação do processo) no meu exemplo. 92102

Em seguida, você pode encerrar o processo 1 de 2 maneiras.

  • Use graciosamente QUIT 92102

  • Use com força TERM 92102

* Não tenho certeza da sintaxe que éQUIT 92102 ouQUIT -92102

Deixe-me saber se você tiver algum problema.

jBeas
fonte
3
No console do Linux: kill -SIGQUIT 92102
Alexey
6

Eu apenas fiz:

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

Consegui a lista de trabalhadores.

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

... onde n é o índice baseado em zero do trabalhador indesejado.

user2811637
fonte
2

Eu tive um problema semelhante que o Redis salvou o banco de dados no disco que incluía trabalhadores inválidos (não em execução). Cada vez que o Redis / resque foi iniciado, eles apareciam.

Corrija isso usando:

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

Certifique-se de reiniciar o Redis e seus funcionários do Resque.

joost
fonte
2

Veja como você pode removê-los do Redis pelo nome do host. Isso acontece comigo quando eu desativo um servidor e os trabalhadores não saem normalmente.

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

Eu me deparei com esse problema e comecei a implementar muitas sugestões aqui. No entanto, eu descobri que a causa raiz que estava criando esse problema foi o uso do gem redis-rb 3.3.0 . A atualização para o redis-rb 3.2.2 impediu que esses trabalhadores ficassem presos em primeiro lugar.

Will Bryant
fonte
1

Começou a trabalhar em https://github.com/shaiguitar/resque_stuck_queue/ recentemente. Não é uma solução de como consertar trabalhadores presos, mas aborda a questão de resque pendurar / ficar preso, então achei que poderia ser útil para as pessoas desse segmento. Do README:

"Se o resque não executar trabalhos dentro de um determinado período de tempo, ele acionará um manipulador predefinido de sua escolha. Você pode usar isso para enviar um email, serviço de pager, adicionar mais trabalhadores do resque, reiniciar o resque, enviar um txt. ..qualquer combina com você. "

Foi usado na produção e funciona muito bem para mim até agora.

Shai
fonte
0

Também tive trabalhadores presos ou obsoletos aqui, ou devo dizer 'empregos', porque o trabalhador ainda está lá e funcionando bem, é o processo bifurcado que está preso.

Eu escolhi a solução brutal de matar o processo bifurcado "Processing" desde mais de 5 minutos, por meio de um script bash, então o trabalhador apenas gera o próximo na fila e tudo continua em andamento

dê uma olhada no meu script aqui: https://gist.github.com/jobwat/5712437

jobwat
fonte
0

Eu os limpei diretamente do redis-cli. Felizmente, redistogo.com permite acesso a partir de ambientes externos ao heroku. Obter ID do trabalhador morto da lista. O meu era

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

Execute este comando em redis diretamente.

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

Você pode monitorar o redis db para ver o que está fazendo nos bastidores.

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"

A segunda última linha exclui o trabalhador.

Andrei R
fonte
Não é uma boa ideia. Isso não chama ganchos de cancelamento de registro no Resque, não chamando de falha e possível código de limpeza que as pessoas possam ter.
Jeremy
Este foi útil com resque 2 anos atrás, quando ele estava mostrando trabalhos presos que eram impossíveis de apagar usando a interface e não havia nenhuma maneira limpa para fazê-lo em trilhos
Andrei R
0

Se você estiver usando versões mais recentes do Resque, precisará usar o seguinte comando, pois as APIs internas foram alteradas ...

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

Isso evita o problema, desde que você tenha uma versão resque mais recente que 1.26.0:

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

Lembre-se de que ele não permite que o trabalho atualmente em execução seja concluído.

Joakim Kolsjö
fonte
0

você também pode usar o comando abaixo para parar todos os rescuetrabalhadores

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

referência a partir deste link

uzaif
fonte