2012-03-10 23 views
24

Chúng tôi sử dụng Celery với ứng dụng web Django của chúng tôi để quản lý các tác vụ ngoại tuyến; một số tác vụ này có thể chạy tới 120 giây.Cách khởi động lại Celery một cách duyên dáng mà không làm chậm công việc

Bất cứ khi nào chúng tôi thực hiện bất kỳ sửa đổi mã nào, chúng tôi cần phải khởi động lại Celery để yêu cầu tải lại mã Python mới. Giải pháp hiện tại của chúng tôi là gửi một SIGTERM đến quy trình Celery chính (kill -s 15 `cat /var/run/celeryd.pid`), sau đó đợi nó chết và khởi động lại nó (python manage.py celeryd --pidfile=/var/run/celeryd.pid [...]).

Do nhiệm vụ dài hạn, điều này thường có nghĩa là việc tắt máy sẽ mất một hoặc hai phút, trong đó không có nhiệm vụ mới nào được xử lý, gây ra sự chậm trễ đáng chú ý cho người dùng hiện tại trên trang web. Tôi đang tìm cách bảo Celery tắt máy, nhưng sau đó ngay lập tức khởi chạy một thể hiện Celery mới để bắt đầu chạy các nhiệm vụ mới.

Những điều mà không công việc:

  • Gửi SIGHUP đến quá trình chính: điều này gây ra cần tây để cố gắng "khởi động lại", bằng cách thực hiện một shutdown ấm và sau đó việc tái giới thiệu bản thân. Điều này không chỉ mất một thời gian dài, nó thậm chí không hoạt động, bởi vì dường như quá trình mới ra mắt trước khi cái cũ chết, vì vậy cái mới than phiền ERROR: Pidfile (/var/run/celeryd.pid) already exists. Seems we're already running? (PID: 13214) và chết ngay lập tức. (Điều này giống như một lỗi trong chính Celery; tôi đã let them know về nó.)
  • Gửi SIGTERM đến quy trình chính và sau đó ngay lập tức khởi chạy một cá thể mới: cùng một vấn đề với Pidfile.
  • Vô hiệu hóa Pidfile hoàn toàn: không có nó, chúng tôi không có cách nào để nói quá trình Celery nào là quá trình chính cần gửi SIGTERM khi chúng ta muốn tắt máy. Chúng tôi cũng không có cách nào đáng tin cậy để kiểm tra xem quy trình chính vẫn còn sống hay không.
+0

Có lẽ câu trả lời của tôi về http://stackoverflow.com/questions/9764913/how-do-i-restart-celery-workers-gracefully/16717128#16717128 sẽ giúp bạn. – guettli

Trả lời

0

Bạn có thể khởi chạy nó bằng tên tệp pid tùy chỉnh không. Có thể timestamped, và chìa khóa để biết rằng PID để giết?

CELERYD_PID_FILE="/var/run/celery/%n_{timestamp}.pid"

^Tôi không biết cú pháp dấu thời gian nhưng có lẽ bạn làm hoặc bạn có thể tìm thấy nó?

sau đó sử dụng thời gian hệ thống hiện tại để loại bỏ bất kỳ thẻ cũ nào và khởi chạy một phiên bản mới?

+0

Tôi nghi ngờ bạn sẽ cần một sự kết hợp của một trong những kỹ thuật trong câu hỏi với điều này. Tùy thuộc vào nhà môi giới của bạn, bạn có thể bắt đầu một cần tây mới với một pidfile dựa trên dấu thời gian (bằng cách sử dụng '--pidfile ='), sau đó gửi 'SIGTERM' cho tất cả các quy trình cần thiết đang chạy khác để tắt chúng. lưu ý rằng có thực sự chỉ có một, trừ khi bạn thử điều này trong khi một celeryd cũ vẫn đang đi qua tắt máy ấm áp). –

4

celeryd có tùy chọn --autoreload. Nếu được kích hoạt, nhân viên cần tây (quy trình chính) sẽ phát hiện những thay đổi trong mô-đun cần tây và khởi động lại tất cả các quy trình công nhân. Ngược lại với tín hiệu SIGHUP, tự động tải lại khởi động lại từng quá trình một cách độc lập khi tác vụ thực thi hiện tại kết thúc. Nó có nghĩa là trong khi một quy trình công nhân đang khởi động lại các tiến trình còn lại có thể thực hiện các nhiệm vụ.

http://celery.readthedocs.org/en/latest/userguide/workers.html#autoreloading

+14

Mặc dù '--autoreload' được đánh dấu là không được thông báo để triển khai trực tiếp. –

+1

Trong quá trình sản xuất, nó có thể được sử dụng với bộ nạp lại tùy chỉnh như thế này http://www.indelible.org/ink/python-reloading/ – mher

3

Tôi vừa mới sửa lỗi với SIGHUP: https://github.com/celery/celery/pull/662

+0

Cảm ơn! Tuy nhiên, bản sửa lỗi của bạn không thay đổi thực tế là SIGHUP đợi tất cả các tác vụ hoàn tất trước khi chấm dứt và khởi chạy lại, lại gây ra sự chậm trễ mà tôi đang cố tránh. Ý tưởng về cách tận dụng lợi thế của bản sửa lỗi của bạn mà vẫn làm cho nó khởi chạy lại mà không chờ đợi sẽ là tuyệt vời ... – nitwit

+0

Đây là cách tôi giải quyết vấn đề. Tôi đặt mọi tác vụ chạy dài (chuyển đổi video, gửi email) trong một hàng đợi riêng biệt, được xử lý bởi một nhân viên riêng biệt. Vì vậy, khi tôi gửi SIGHUP cho tất cả công nhân, tôi biết rằng các công việc xử lý công việc từ hàng đợi mặc định không chặn trong một thời gian dài, bởi vì chỉ có các nhiệm vụ nhỏ. Chuyển đổi video không chặn các tác vụ nhỏ. Chỉ có hàng đợi chuyển đổi video bị chặn trong một thời gian. Nhưng điều này là chấp nhận được trong trường hợp của tôi. –

+0

Vì vậy, sau một số thử nghiệm, tôi phát hiện ra bản sửa lỗi của bạn cũng khắc phục được sự cố SIGTERM. Vì vậy, cuối cùng tôi đã giải quyết vấn đề này một lần và cho tất cả bằng cách hợp nhất sửa chữa và khởi động lại Celery bằng cách sử dụng: 'kill -s SIGTERM' 'cat/var/run/celeryd.pid'' && python manage.py celeryd --pidfile =/var/run/celeryd.pid [...] ' Nếu bạn có thể đặt câu trả lời đó vào câu trả lời của mình, tôi sẽ chấp nhận nó! – nitwit

2
rm *.pyc 

Điều này làm cho nhiệm vụ cập nhật để được nạp lại. Tôi đã phát hiện ra thủ thuật này gần đây, tôi chỉ hy vọng không có tác dụng phụ khó chịu nào.

0

Bạn sử dụng SIGHUP (1) để tắt máy cần tây. Tôi không chắc chắn nếu nó thực sự gây ra một tắt máy ấm áp. Nhưng SIGINT (2) sẽ gây tắt máy. Hãy thử SIGINT thay cho SIGHUP và sau đó bắt đầu cần tây theo cách thủ công trong kịch bản của bạn (tôi đoán).

1

Một chút trễ, nhưng điều đó có thể được sửa bằng cách xóa tệp có tên celerybeat.pid.

Đã làm việc cho tôi.