2012-03-14 29 views
13

Tôi chỉ muốn hiểu các phương pháp hay nhất để khởi động lại công nhân làm việc bị trì hoãn bằng cách sử dụng capistrano. Tôi có một nhóm công nhân xử lý các công việc dài (lên tới 10 phút).Việc làm bị trì hoãn khởi động lại + Thực tiễn tốt nhất của Capistrano

tôi đã đi qua hai kịch bản trong một triển khai trong khi công nhân đang xử lý-

1)

tôi dừng lại trì hoãn công nhân công việc trước khi triển khai: nhiệm vụ khởi động lại và bắt đầu họ một lần nữa sau khi triển khai: nhiệm vụ khởi động lại . Tuy nhiên, trong kịch bản này, nó sẽ không khởi động lại ứng dụng của tôi cho đến khi các công việc bị trì hoãn kết thúc (điều này có thể ok - nhưng kịch bản lệnh triển khai thực hiện ở đó cho đến khi công việc được thực hiện và có thể ngừng tất cả công nhân) trước khi tiếp tục với nhiệm vụ khởi động lại ứng dụng.

2) Tôi cũng đã cố gắng dừng/khởi động công nhân bị trì hoãn sau khi khởi động lại - nhưng điều này đã gây ra tất cả các loại phim truyền hình theo đó các tác vụ sẽ bị dừng mà không đợi bảng bị trì hoãn. PID không tồn tại!

Bất kỳ tùy chọn nào khác? Hoặc tôi buộc phải đợi như đã đề cập trong kịch bản 1.

Rất cám ơn.

Chỉnh sửa: Tôi vừa mới nhận ra với trường hợp 1 .. không chờ! Nhiệm vụ ngăn chặn sẽ giết chết công nhân của tôi ngay cả khi nó chưa kết thúc!

** [out] delayed_job: trying to stop process with pid 9630... 
** [out] delayed_job: process with pid 9630 won't stop, we forcefully kill it... 
** [out] 
** [out] delayed_job: process with pid 9630 successfully stopped. 

Trả lời

0

Bạn có thể khắc phục kịch bản thứ hai để đưa tệp pid của mình vào một thư mục được chia sẻ để tránh nó biến mất. Kịch bản thứ hai có thể hoạt động và nếu bạn không có một số di chuyển đến có thể xung đột với công việc bị trì hoãn của bạn.

+0

Đúng vậy. Trong/chia sẻ/pids/giống như tất cả các tập tin được chia sẻ khác (hình ảnh & nhật ký vv). – Jamsi

1

Nếu thay đổi triển khai của bạn thay đổi giản đồ cơ sở dữ liệu, thì bạn buộc phải đợi.

Nếu không, bạn có thể đặt cờ mà người lao động kiểm tra ở cuối mỗi công việc. Khi triển khai, bạn thiết lập cờ, và một khi một nhân viên chạy dài kết thúc, nó sẽ tự thay thế bằng cách thực thi một công nhân mới. Bằng cách đó bạn sẽ không bao giờ thực sự bắt đầu và dừng công nhân - chúng chỉ chạy luôn và sẽ tải mã mới nhất khi bắt đầu công việc tiếp theo.

0

Tôi đã kết thúc việc chuyển "quy trình chạy dài" của mình sang tập lệnh Ruby tùy chỉnh bằng cách sử dụng đá quý daemon. Cảm ơn lời khuyên mặc dù guys!

-1

Câu hỏi hay - Tôi đã thử rất nhiều thứ khác nhau, nhưng chiến lược của tôi là giữ mọi thứ đơn giản.

  1. Không sử dụng Thiên Chúa hoặc Monit hoặc bất kỳ thứ gì chạy dưới gốc, yêu cầu cùng một người dùng chạy ứng dụng của bạn có quyền sudo khởi động lại. Với các sự kiện gần đây trong bảo mật đường ray, điều cuối cùng bạn muốn là người dùng ứng dụng của bạn có khả năng nhận root tốt.
  2. Thay vào đó, hãy sử dụng tác vụ rake hoặc thor để bắt đầu/dừng/khởi động lại tác vụ.
  3. Sử dụng nohup để sao chép quy trình.

Dưới đây là một số nhiệm vụ thor rất cơ bản mà có thể quản lý các nhiệm vụ nền đơn giản với resque, ví dụ:

class Resque < Thor 

    desc "start", "Starts resque workers" 
    def start 
    system('(PIDFILE=/tmp/resque-myapp.pid nohup rake resque:work QUEUES="*" &) &') 
    end 

    desc "stop", "Stops resque workers" 
    def stop 
    pidfile = '/tmp/resque-myapp.pid' 
    if File.exist?(pidfile) 
     pid = File.open(pidfile).first.to_i 
     puts "Killing process #{pid}..." 
     system("kill -QUIT #{pid}") 
     File.delete(pidfile) 
     sleep(5) 
    else 
     puts "No resque pidfile found" 
    end 
    end 
end 

Sau đó, trong tập tin deploy.rb của bạn:

after 'deploy',   "resque:restart" 

namespace :resque do 
    task :restart do 
    puts "Stopping resque workers.." 
    run("cd #{current_path} && thor resque:stop", :options => { :pty => true }) 
    puts "Starting resque workers.." 
    run("cd #{current_path} && thor resque:start > /dev/null 2>&1 &", :options => { :pty => true }) 
    end 
end 

Chiến lược này thậm chí có thể làm việc với RVM, nếu đó là sự quan tâm. Bạn sẽ cần một cái gì đó như thế này trước khi lệnh khởi động lại, ngoài các rvm-capistrano nhiệm vụ thông thường:

after 'deploy:setup', 'thor:install' 
namespace :thor do 
    task :install do 
    puts "Installing thor..." 
    run_locally('cap rvm:install_gem GEM=thor') 
    end 
end 

after "deploy",   "rvm:trust_rvmrc" 
namespace :rvm do 
    task :trust_rvmrc do 
    run "rvm rvmrc trust #{release_path}" 
    end 
end 

Và cuối cùng nhưng không kém, với RVM đó là tốt nhất để đưa vào ~/.bashrc gì trình cài đặt bình thường chia tách giữa các tập tin và .bash_profile , và chắc chắn rằng chế độ của tập tin là 0400 vì vậy nó sẽ không nhận được clobbered bởi RVM cài đặt chương trình:

PATH=$HOME/.rvm/bin:/usr/local/bin/:$PATH # Add RVM to PATH for scripting 
export PATH 
export RAILS_ENV=production 
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" 
+0

Tôi không đồng ý với việc không sử dụng monit. Monit bắt đầu công nhân khi triển khai người dùng và người dùng triển khai chỉ có quyền truy cập sudo vào lệnh monit. – rubish

+0

Nhưng không phải là tệp cấu hình đơn nguyên được tìm thấy trong chính cấu hình ứng dụng, có thể ghi bởi người dùng triển khai trong 'config/recipes/templates/monit/*'? Mọi người luôn đề cập đến "người dùng triển khai" nhưng trên thực tế đó là "người dùng chạy ứng dụng". Vì vậy, nếu bạn cho sudo quyền truy cập vào monit, và cấu hình của monit, trên thực tế, thế giới có thể ghi được nếu ứng dụng của bạn bị tấn công ... Xin lỗi, tôi không thấy điều này như một giải pháp an toàn. – platforms

+0

Quan điểm của tôi là, nếu bạn đưa ra bất kỳ đặc quyền sudo nào cho người dùng ứng dụng chạy, bạn cũng đưa cho họ bất kỳ hacker tiềm năng nào từ trình duyệt web. Ngay cả khi bạn giới hạn quyền truy cập đó vào một chương trình, tôi chưa bao giờ thấy bất kỳ giao thức bảo mật nào sẽ đề xuất cho kẻ tấn công khả năng chạy bất cứ thứ gì là root. – platforms

-2

tôi sẽ khuyên bạn kiểm tra whenever - có lẽ đá quý tốt nhất để quản lý công việc bị trì hoãn. Tôi đã thử các giải pháp khác nhau bắt đầu với cron + wget cũ bị lãng quên, nhưng bất cứ khi nào kiểm soát tốt nhất điều này. Và nó tích hợp tuyệt vời với Capistrano. HTH

+1

OP đang nói về https://github.com/collectiveidea/delayed_job –

1

Thực sự không chắc chắn rằng giải pháp của tôi là đủ tốt. Nhưng dù sao nó cũng có cơ hội để sống. Chỉ cần tạo một nhiệm vụ Rake và bắt đầu nhiệm vụ đó trong quá trình triển khai:

desc 'Wait for delayed job completion' 
    task wait_for_complete_background_jobs: :environment do 
    loop do 
     exit unless Delayed::Job.where(locked_at: nil).exists? 
     sleep 2 
    end 
    end 

Nhiệm vụ cào chờ đợi công việc bị khóa và thoát ngay sau khi danh sách nhiệm vụ bị khóa trống. Đây là cách tôi tưởng tượng sử dụng của nó (lưu ý, trình tự của các hoạt động là rất quan trọng):

  1. Dừng máy chủ web
  2. Bắt đầu nhiệm vụ cào
  3. Dừng trì hoãn công việc
  4. cập nhật mã
  5. Bắt đầu bị trì hoãn việc làm
  6. Khởi động máy chủ web
Các vấn đề liên quan