2010-04-10 34 views
20

Tôi có trang web chạy ứng dụng đường ray và công nhân resque chạy trong chế độ sản xuất, trên Ubuntu 9.10, Rails 2.3.4, ruby-ee 2010.01, PostgreSQL 8.4.2Rails Resque công nhân thất bại với PGError: máy chủ đóng kết nối bất ngờ

Công nhân liên tục tăng lỗi: PGError: máy chủ đóng kết nối bất ngờ. Dự đoán tốt nhất của tôi là quá trình resque chính thiết lập kết nối với db (ví dụ authlogic thực hiện điều đó khi sử dụng User.acts_as_authentic), trong khi tải các lớp ứng dụng đường ray và kết nối đó bị hỏng trong quá trình fork() ed (khi thoát?) , vì vậy những đứa trẻ được chia rẽ tiếp theo có thể bị phá vỡ toàn cầu ActiveRecord :: Base.connection

Tôi có thể tái tạo hành vi rất giống với điều này sample code bắt chước/xử lý trong công nhân resque. (AFAIK, người dùng libpq được đề nghị tạo lại kết nối trong quá trình chia đôi, nếu không nó không an toàn)

Nhưng điều kỳ lạ là khi tôi sử dụng pgbouncer hoặc pgpool-II thay vì kết nối pgsql trực tiếp, lỗi đó không xuất hiện .

Vì vậy, câu hỏi là ở đâu và làm thế nào tôi nên đào để tìm hiểu lý do tại sao nó bị hỏng cho kết nối đồng bằng và đang làm việc với các hồ bơi kết nối? Hoặc giải pháp hợp lý?

Trả lời

12

Khi tôi tạo Nestor, tôi đã có cùng một loại vấn đề. Giải pháp là thiết lập lại kết nối trong quá trình chia đôi. Xem mã có liên quan tại http://github.com/francois/nestor/blob/master/lib/nestor/mappers/rails/test/unit.rb#L162

Từ rất cái nhìn hạn hẹp của mình vào mã Resque, tôi tin rằng một cuộc gọi đến #establish_connection nên được thực hiện đúng về ở đây: https://github.com/resque/resque/blob/master/lib/resque/worker.rb#L123

+6

Cảm ơn, vì vậy tôi chỉ cần thêm hook: Resque.after_fork = Proc.new {ActiveRecord :: Base.establish_connection} –

+1

Tôi có thể gặp phải sự cố tương tự. Bạn có thể cho tôi biết làm thế nào và nơi bạn đã thêm "móc"? –

+0

liên kết dưới cùng bị hỏng – botbot

9

Bạn không thể vượt qua một tham chiếu libpq qua một ngã ba () (hoặc một chủ đề mới), trừ khi ứng dụng của bạn rất cẩn thận khi không sử dụng nó theo các cách xung đột. (Giống như, một mutex xung quanh mọi nỗ lực duy nhất để sử dụng nó, và bạn không bao giờ phải đóng nó). Điều này là như nhau cho cả kết nối trực tiếp và sử dụng pgbouncer. Nếu nó làm việc trong pgbouncer, đó là may mắn tinh khiết trong việc thiếu một điều kiện chủng tộc vì lý do nào đó, và cuối cùng sẽ phá vỡ.

Nếu chương trình của bạn sử dụng forking, bạn phải tạo kết nối sau ngã ba.

55

Sau khi thực hiện một chút nghiên cứu/thử nghiệm và lỗi. Đối với bất kỳ ai đang gặp phải vấn đề tương tự. Để làm rõ những gì gc đã đề cập.

Resque.after_fork = Proc.new { ActiveRecord::Base.establish_connection } 

Trên mã nên được đặt trong: /lib/tasks/resque.rake

Ví dụ:

require 'resque/tasks' 

task "resque:setup" => :environment do 
    ENV['QUEUE'] = '*' 

    Resque.after_fork do |job| 
    ActiveRecord::Base.establish_connection 
    end 

end 

desc "Alias for resque:work (To run workers on Heroku)" 
task "jobs:work" => "resque:work" 

Hope this helps một ai đó, nhiều như nó đã làm cho tôi.

+6

bạn là một quý ông và một học giả, đã cứu tôi một số nhức đầu cho chắc chắn – Jimmy

+1

Điều này là hoàn hảo! ... nhưng bạn có thể muốn loại bỏ dòng 'ENV ['QUEUE']', vì điều đó sẽ làm nảy sinh bất kỳ công nhân cụ thể xếp hàng nào bằng cách đặt chúng thành '*' – nessur

+0

của tôi: nhiệm vụ thiết lập được cho là bên trong : resque task. (Không phải là một resque: thiết lập bên trong: resque!) Vì điều đó lúc đầu, điều này đã không làm việc cho tôi. Tôi chỉ muốn nói với mọi người để tăng gấp đôi kiểm tra kế thừa nhiệm vụ. – scaryguy

0

Thay đổi Apache cấu hình và thêm

PassengerSpawnMethod conservative 
0

Tôi có vấn đề này với tất cả các lớp mailer của tôi và tôi cần phải gọi ActiveRecord::Base.verify_active_connections! trong phương pháp bưu phẩm để đảm bảo một kết nối đã được thực hiện.

Các vấn đề liên quan