Bagaimana cara saya membersihkan pekerja yang macet / basi?

132

Seperti yang Anda lihat dari gambar terlampir, saya punya beberapa pekerja yang tampaknya macet. Proses-proses itu seharusnya tidak lebih dari beberapa detik.

masukkan deskripsi gambar di sini

Saya tidak yakin mengapa mereka tidak menghapus atau cara menghapusnya secara manual.

Saya menggunakan Heroku menggunakan Resque dengan Redis-to-Go dan HireFire untuk secara otomatis mengukur pekerja.

Shpigford
sumber
2
Hai, pertanyaan semi-terkait: bagaimana Anda mendapatkan dasbor resque-web via heroku? Sepertinya saya tidak tahu cara membukanya.
Aaron Marks

Jawaban:

215

Tidak ada solusi ini yang bekerja untuk saya, saya masih akan melihat ini di redis-web:

0 out of 10 Workers Working

Akhirnya, ini berhasil bagi saya untuk membersihkan semua pekerja:

Resque.workers.each {|w| w.unregister_worker}
hagope
sumber
12
Ini berhasil untuk saya. Itu tidak terdaftar semua pekerja yang agak mengganggu. Tetapi ini diikuti oleh heroku restarttampaknya melakukan trik. Sekarang menunjukkan jumlah pekerja yang benar.
Brian Armstrong
Ini mengambil pekerja dari antarmuka web, tetapi sebenarnya mereka masih muncul sebagai proses dan juga "mencuri" pekerjaan dari antrian
txwikinger
20
Jika Anda ingin membatalkan pendaftaran hanya pekerja yang bukan proses aktual (dan mungkin memproses pekerjaan), Anda mungkin ingin mencoba Resque.workers.each {|w| matches = w.id.match(/^[^:]*:([0-9]*):[^:]*$/); pid = matches[1]; w.unregister_worker unless w.worker_pids.include?(pid.to_s)}yang hanya akan membatalkan registrasi pekerja yang tidak termasuk dalam pid berjalan yang dikenal. Saya tidak tahu apakah ini berfungsi di semua lingkungan tetapi berfungsi baik di ubuntu. Ini mungkin hanya bekerja ketika pekerja Anda berada di mesin yang sama dengan Anda menjalankan kode ini.
roychri
3
Sebagai opsi, Resque.workers.map &: unregister_worker
AB
Kenapa ini tidak termasuk cek apakah pekerja harus tidak terdaftar sebelum menelepon unregister_worker? Apakah ada cara untuk menentukan ini?
user5243421
53

Di konsol Anda:

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

Kalau tidak, Anda dapat mencoba memalsukannya dengan menghapusnya, dengan:

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

EDIT

Banyak orang telah memperbaiki jawaban ini dan saya merasa bahwa penting bagi orang untuk mencoba solusi hagope yang membatalkan pendaftaran pekerja dari antrian, sedangkan kode di atas menghapus antrian. Jika Anda senang memalsukannya, maka dinginkan.

Orang bodoh
sumber
3
Jika dia melakukan ini, itu akan menghapus seluruh antrian, dia hanya ingin menghapus yang macet ..
jBeas
1
Pembaruan kecil: Anda sekarang harus menggunakan Resque.redis.del alih-alih Resque.redis.delete
James P McGrath
1
Sebenarnya ada metode Resque.remove_queue () sekarang
iainbeeston
28

Anda mungkin memasang permata resque, sehingga Anda dapat membuka konsol dan mendapatkan pekerja saat ini

Resque.workers

Ini mengembalikan daftar pekerja

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

pilih pekerja dan prune_dead_workers, misalnya yang pertama

Resque.workers.first.prune_dead_workers
Shairon Toledo
sumber
1
Sebenarnya, pada percobaan kedua, ini tidak melakukan apa-apa.
Shpigford
2
Ini bekerja sangat baik untuk membersihkan pekerja resque yang terbunuh tanpa mendaftar.
Lukas Eklund
3
Ini sepertinya jawaban terbaik yang baru karena tidak membatalkan pendaftaran mereka semua. Bukankah seharusnya prune_dead_workers menjadi metode kelas? Namun bagaimanapun juga, solusi hebat! Terima kasih.
Brian Armstrong
Itu pasti solusi untuk pekerja -9 yang terbunuh. Satu-satunya hal yang akan saya tambahkan adalah bahwa Anda perlu melakukan itu di server yang sama di mana Anda membunuh dengan -9.
Stanislav O. Pogrebnyak
Lakukan untuk mereka semua sekaligus: Resque.workers.each (&: prune_dead_workers)
Leo
25

Menambahkan untuk menjawab dengan hagope, saya ingin hanya dapat membatalkan pendaftaran pekerja yang telah berjalan selama waktu tertentu. Kode di bawah ini hanya akan membatalkan pendaftaran pekerja yang berjalan selama lebih dari 300 detik (5 menit).

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

Saya memiliki koleksi tugas Rake terkait Resque yang sedang berlangsung yang juga telah saya tambahkan ini ke: https://gist.github.com/ewherrmann/8809350

ewH
sumber
3
Poin untuk menunjukkan cara mengakses waktu mulai pekerjaan melalui pemrosesan ['run_at']. Saya telah melihat solusi lain yang menggunakan metode .started, tetapi ini sebenarnya mengembalikan waktu pekerja dimulai, bukan pekerjaan, yang merupakan pendekatan yang salah untuk membersihkan pekerja yang terjebak. Terima kasih!
Lachlan Cotter
10

Jalankan perintah ini di mana pun Anda menjalankan perintah untuk memulai server

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

Anda akan melihat sesuatu seperti ini:

92102 resque: Processing ProcessNumbers since 1253142769

Catat PID (id proses) dalam contoh saya itu adalah 92102

Kemudian Anda dapat keluar dari proses 1 dari 2 cara.

  • Gunakan dengan anggun QUIT 92102

  • Gunakan dengan paksa TERM 92102

* Saya tidak yakin sintaks itu baik QUIT 92102atauQUIT -92102

Beri tahu saya jika Anda memiliki masalah.

jBeas
sumber
3
Di konsol Linux: kill -SIGQUIT 92102
Alexey
6

Saya baru saja melakukannya:

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

Punya daftar pekerja.

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

... di mana n adalah indeks berbasis nol dari pekerja yang tidak diinginkan.

pengguna2811637
sumber
2

Saya memiliki masalah yang sama yaitu Redis menyimpan DB ke disk yang menyertakan pekerja yang tidak valid (tidak berjalan). Setiap kali Redis / resque dimulai mereka muncul.

Perbaiki ini menggunakan:

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

Pastikan Anda memulai ulang Redis dan pekerja Resque Anda.

joost
sumber
2

Inilah cara Anda dapat membersihkan mereka dari Redis dengan nama host. Ini terjadi pada saya ketika saya menonaktifkan server dan pekerja tidak keluar dengan anggun.

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

Saya mengalami masalah ini dan mulai menerapkan banyak saran di sini. Namun, saya menemukan akar penyebab yang menciptakan masalah ini adalah bahwa saya menggunakan permata redis-rb 3.3.0 . Penurunan peringkat ke redis-rb 3.2.2 mencegah para pekerja ini terjebak di tempat pertama.

Will Bryant
sumber
1

Mulai bekerja di https://github.com/shaiguitar/resque_stuck_queue/ baru-baru ini. Ini bukan solusi untuk bagaimana memperbaiki pekerja yang macet tetapi ini membahas masalah resque hanging / macet, jadi saya pikir itu bisa bermanfaat bagi orang-orang di utas ini. Dari README:

"Jika resque tidak menjalankan pekerjaan dalam jangka waktu tertentu, itu akan memicu penangan pilihan Anda yang telah ditentukan sebelumnya. Anda dapat menggunakan ini untuk mengirim email, tugas pager, menambahkan lebih banyak pekerja resque, memulai kembali resque, mengirimi Anda txt. ..apa pun yang cocok untukmu. "

Telah digunakan dalam produksi dan bekerja dengan cukup baik untuk saya sejauh ini.

Shai
sumber
0

Saya telah terjebak / basi resque pekerja di sini juga, atau haruskah saya mengatakan 'pekerjaan', karena pekerja itu sebenarnya masih ada dan berjalan dengan baik, itu proses bercabang yang macet.

Saya memilih solusi brutal untuk membunuh proses bercabang "Memproses" sejak lebih dari 5 menit, melalui skrip bash, maka pekerja hanya menelurkan berikutnya dalam antrian, dan semuanya terus berjalan

lihat skrip saya di sini: https://gist.github.com/jobwat/5712437

jobwat
sumber
0

Saya sudah membersihkan mereka dari redis-cli secara langsung. Untungnya redistogo.com memungkinkan akses dari lingkungan di luar heroku. Dapatkan ID pekerja yang sudah mati dari daftar. Milik saya

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

Jalankan perintah ini dengan redis secara langsung.

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

Anda dapat memonitor redis db untuk melihat apa yang dilakukannya di balik layar.

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"

Baris terakhir kedua menghapus pekerja.

Andrei R
sumber
Bukan ide yang bagus. Ini tidak akan memanggil kait tidak terdaftar di Resque, tidak menyebut kegagalan dan mungkin kode pembersihan yang mungkin dimiliki orang.
Jeremy
Ini berguna dengan resque 2 tahun lalu ketika menunjukkan pekerjaan macet yang tidak mungkin dihapus menggunakan antarmuka dan tidak ada cara bersih untuk melakukannya di rails
Andrei R
0

Jika Anda menggunakan versi Resque yang lebih baru, Anda harus menggunakan perintah berikut karena API internal telah berubah ...

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

Ini menghindari masalah selama Anda memiliki versi resque yang lebih baru dari 1.26.0:

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

Perlu diingat bahwa itu tidak membiarkan pekerjaan yang sedang berjalan selesai.

Joakim Kolsjö
sumber
0

Anda juga dapat menggunakan perintah di bawah ini untuk menghentikan semua rescuepekerja

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

referensi dari tautan ini

uzaif
sumber