Làm thế nào để tôi xóa công nhân Resque bị mắc kẹt / cũ?


132

Như bạn có thể thấy từ hình ảnh đính kèm, tôi có một vài công nhân dường như bị mắc kẹt. Những quá trình đó không nên mất nhiều hơn một vài giây.

nhập mô tả hình ảnh ở đây

Tôi không chắc tại sao họ sẽ không xóa hoặc làm thế nào để loại bỏ chúng theo cách thủ công.

Tôi đang trên Heroku sử dụng Resque với Redis-to-Go và HireFire để tự động nhân rộng quy mô.


2
Xin chào, câu hỏi liên quan đến bán: làm thế nào bạn có được bảng điều khiển web resque qua heroku? Tôi dường như không thể tìm ra cách mở nó.
Aaron Marks

Câu trả lời:


215

Không có giải pháp nào trong số này làm việc cho tôi, tôi vẫn sẽ thấy điều này trong redis-web:

0 out of 10 Workers Working

Cuối cùng, điều này làm việc cho tôi để xóa tất cả các công nhân:

Resque.workers.each {|w| w.unregister_worker}

12
Điều này làm việc cho tôi. Nó không đăng ký tất cả các công nhân đó là một chút khó chịu. Nhưng điều này theo sau heroku restartdường như để làm các mẹo. Bây giờ nó cho thấy số lượng công nhân chính xác.
Brian Armstrong

Điều này đã loại bỏ các công nhân khỏi giao diện web, nhưng thực tế họ vẫn hiển thị dưới dạng các quy trình và cũng "đánh cắp" các công việc từ hàng đợi
txwikinger

20
Nếu bạn muốn hủy đăng ký chỉ những công nhân không phải là quy trình thực tế (và có thể xử lý công việc), bạn có thể muốn thử Resque.workers.each {|w| matches = w.id.match(/^[^:]*:([0-9]*):[^:]*$/); pid = matches[1]; w.unregister_worker unless w.worker_pids.include?(pid.to_s)}, điều này sẽ chỉ hủy đăng ký những công nhân đó không phải là một phần của các công việc đang chạy. Tôi không biết nếu nó hoạt động trong tất cả các môi trường nhưng nó hoạt động tốt trên Ubuntu. Điều này có thể chỉ hoạt động khi nhân viên của bạn ở trên cùng một máy mà bạn chạy mã này.
roychri

3
Là một tùy chọn Resque.workers.map &: unregister_worker
AB

Tại sao điều này không bao gồm kiểm tra xem liệu công nhân có nên đăng ký trước khi gọi unregister_workerkhông? Có cách nào để xác định điều này?
dùng5243421

53

Trong bảng điều khiển của bạn:

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

Nếu không, bạn có thể cố gắng giả mạo chúng như đã được thực hiện để loại bỏ chúng, với:

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

BIÊN TẬP

Rất nhiều người đã ủng hộ câu trả lời này và tôi cảm thấy rằng điều quan trọng là mọi người nên thử giải pháp của hagope mà không đăng ký công nhân ra khỏi hàng đợi, trong khi đoạn mã trên xóa hàng đợi. Nếu bạn vui vẻ giả chúng, thì tuyệt.


3
Nếu anh ta làm điều này, nó sẽ xóa toàn bộ hàng đợi, anh ta chỉ muốn xóa những cái bị kẹt ..
jBeas

1
Cập nhật nhỏ: Bây giờ bạn phải sử dụng Resque.redis.del thay vì Resque.redis.delete
James P McGrath

1
Hiện tại thực sự có một phương thức Resque.remove_queue ()
iainbeeston

28

Bạn có thể đã cài đặt đá quý resque, vì vậy bạn có thể mở bàn điều khiển và nhận nhân viên hiện tại

Resque.workers

Nó trả về một danh sách công nhân

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

chọn công nhân và prune_dead_workers, ví dụ người đầu tiên

Resque.workers.first.prune_dead_workers

1
Trên thực tế, trong lần thử thứ hai, điều này đã không làm gì cả.
Shpigford

2
Điều này làm việc tuyệt vời để dọn sạch những công nhân resque đã bị giết mà không đăng ký.
Lukas Eklund

3
Đây có vẻ như là câu trả lời mới nhất vì nó không đăng ký tất cả chúng. Không nên prune_dead_workers là một phương thức lớp? Nhưng trong bất kỳ sự kiện, giải pháp tuyệt vời! Cảm ơn.
Brian Armstrong

Đó chắc chắn là giải pháp cho 9 công nhân bị giết. Điều duy nhất tôi muốn thêm là bạn cần phải làm điều đó trên cùng một máy chủ nơi bạn đã giết với -9.
Stanislav O. Pogrebnyak

Làm điều đó cho tất cả bọn họ cùng một lúc: Resque.workers.each (&: prune_dead_workers)
Leo

24

Thêm vào câu trả lời của hagope, tôi muốn có thể chỉ những người lao động không đăng ký đã chạy trong một khoảng thời gian nhất định. Mã dưới đây sẽ chỉ hủy đăng ký nhân viên chạy trong hơn 300 giây (5 phút).

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

Tôi có một bộ sưu tập liên tục các nhiệm vụ Rake liên quan đến Resque mà tôi cũng đã thêm nó vào: https://gist.github.com/ewherrmann/8809350


3
Điểm cho thấy cách truy cập thời gian bắt đầu công việc thông qua xử lý ['run_at']. Tôi đã thấy các giải pháp khác đang sử dụng phương pháp .started, nhưng điều này thực sự trả về thời gian công nhân được bắt đầu, chứ không phải công việc, đó là cách tiếp cận sai để xóa công nhân bị mắc kẹt. Cảm ơn!
Lachlan Cotter

10

Chạy lệnh này bất cứ nơi nào bạn chạy lệnh để khởi động máy chủ

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

bạn sẽ thấy một cái gì đó như thế này:

92102 resque: Processing ProcessNumbers since 1253142769

Ghi chú của PID (id quá trình) trong ví dụ của tôi là 92102

Sau đó, bạn có thể thoát khỏi quá trình 1 trong 2 cách.

  • Sử dụng duyên dáng QUIT 92102

  • Sử dụng mạnh mẽ TERM 92102

* Tôi không chắc về cú pháp, QUIT 92102hoặcQUIT -92102

Hãy cho tôi biết nếu bạn có bất kỳ rắc rối.


3
Trong bảng điều khiển Linux: kill -SIGQUIT 92102
Alexey

6

Tôi vừa làm:

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

Có danh sách công nhân.

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

... Trong đó n là chỉ số dựa trên số 0 của công nhân không mong muốn.


2

Tôi gặp một vấn đề tương tự là Redis đã lưu DB vào đĩa bao gồm các nhân viên không hợp lệ (không chạy). Mỗi khi Redis / resque được bắt đầu, chúng xuất hiện.

Khắc phục sự cố này bằng cách sử dụng:

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

Hãy chắc chắn rằng bạn khởi động lại Redis và nhân viên Resque của bạn.


2

Đây là cách bạn có thể lọc chúng khỏi Redis bằng tên máy chủ. Điều này xảy ra với tôi khi tôi ngừng hoạt động một máy chủ và công nhân không thoát ra một cách duyên dáng.

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

2

Tôi gặp vấn đề này và bắt đầu con đường thực hiện rất nhiều đề xuất ở đây. Tuy nhiên, tôi phát hiện ra nguyên nhân gốc rễ tạo ra vấn đề này là do tôi đang sử dụng gem redis-rb 3.3.0 . Việc hạ cấp xuống redis-rb 3.2.2 đã ngăn những công nhân này bị mắc kẹt ngay từ đầu.


1

Bắt đầu làm việc trên https://github.com/shaigphin/resque_stuck_queue/ gần đây. Đây không phải là một giải pháp để khắc phục các công nhân bị mắc kẹt nhưng nó giải quyết vấn đề treo / bị kẹt lại, vì vậy tôi cho rằng nó có thể hữu ích cho mọi người trong chủ đề này. Từ README:

"Nếu resque không chạy các công việc trong một khung thời gian nhất định, nó sẽ kích hoạt trình xử lý được xác định trước mà bạn chọn. Bạn có thể sử dụng điều này để gửi email, nhiệm vụ nhắn tin, thêm nhân viên bán lại, khởi động lại, gửi cho bạn một txt. .. bất cứ điều gì phù hợp với bạn. "

Được sử dụng trong sản xuất và hoạt động khá tốt đối với tôi cho đến nay.


0

Tôi cũng đã bị kẹt / cũ công nhân bán lại ở đây, hoặc tôi nên nói 'công việc', bởi vì công nhân thực sự vẫn còn ở đó và chạy tốt, đó là quá trình ngã ba bị mắc kẹt.

Tôi đã chọn giải pháp tàn bạo là giết chết quá trình "Xử lý" rẽ nhánh từ hơn 5 phút, thông qua một tập lệnh bash, sau đó công nhân chỉ sinh ra hàng tiếp theo trong hàng đợi và mọi thứ vẫn tiếp tục

hãy xem kịch bản của tôi ở đây: https://gist.github.com/jobwat/5712437


0

Tôi đã xóa chúng khỏi redis-cli trực tiếp. May mắn thay redistogo.com cho phép truy cập từ các môi trường bên ngoài heroku. Nhận ID công nhân chết từ danh sách. Tôi đã

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

Chạy lệnh này trong redis trực tiếp.

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

Bạn có thể theo dõi redis db để xem những gì nó đang làm đằng sau hậu trường.

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"

Dòng cuối cùng thứ hai xóa công nhân.


Không phải là một ý tưởng tốt. Điều này sẽ không gọi các móc nối không đăng ký trong Resque, không gọi thất bại và có thể làm sạch mã mọi người có thể có.
Jeremy

Điều này rất hữu ích với resque 2 năm trước khi nó hiển thị các công việc bị kẹt không thể xóa bằng giao diện và không có cách nào rõ ràng để thực hiện trong đường ray
Andrei R

0

Nếu bạn đang sử dụng các phiên bản Resque mới hơn, bạn sẽ cần sử dụng lệnh sau vì các API nội bộ đã thay đổi ...

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

0

Điều này tránh được vấn đề miễn là bạn có phiên bản resque mới hơn 1.26.0:

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

Hãy nhớ rằng nó không để công việc hiện đang chạy kết thúc.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.