2014-04-03 8 views
5

मेरे पास एक साइडकीक कार्यकर्ता है जिसे 30 सेकंड से अधिक समय नहीं लेना चाहिए, लेकिन कुछ दिनों के बाद मुझे पता चलेगा कि संपूर्ण कार्यकर्ता कतार निष्पादित हो जाती है क्योंकि सभी मजदूरों को बंद कर दिया गया है।साइडकीक कार्यकर्ता हजारों सेकंड के लिए चल रहा है, भले ही टाइमआउट

class MyWorker 
    include Sidekiq::Worker 
    include Sidekiq::Status::Worker 
    sidekiq_options queue: :my_queue, retry: 5, timeout: 4.minutes 

    sidekiq_retry_in do |count| 
    5 
    end 

    sidekiq_retries_exhausted do |msg| 
    store({message: "Gave up."}) 
    end 

    def perform(id) 
    begin 
     Timeout::timeout(3.minutes) do 
     got_lock = with_semaphore("lock_#{id}") do 
      # DO WORK 
     end 
     end 
    rescue ActiveRecord::RecordNotFound => e 
     # Handle 
    rescue Timeout::Error => e 
     # Handle 
     raise e 
    end 
    end 

    def with_semaphore(name, &block) 
    Semaphore.get(name, {stale_client_timeout: 1.minute}).lock(1, &block) 
    end 
end 

और सेमाफोर वर्ग हम का उपयोग करें:

यहाँ मेरी कार्यकर्ता है। (Redis-सेमाफोर मणि)

class Semaphore 
    def self.get(name, options = {}) 
    Redis::Semaphore.new(name.to_sym, 
     :redis => Application.redis, 
     stale_client_timeout: options[:stale_client_timeout] || 1.hour, 
    ) 
    end 
end 

मूल रूप से मैं कार्यकर्ता बंद कर देंगे और यह किया राज्य होगा: 10000 सेकंड है, जो कार्यकर्ता कभी नहीं के लिए चलना चाहिए।

किसी के पास इस बारे में कोई विचार है कि इसे कैसे ठीक किया जाए या इसके कारण क्या हो रहा है? कर्मचारी इंजन पर चल रहे हैं।

संपादित करें: एक अतिरिक्त टिप्पणी। # DO WORK को PostgresSQL फ़ंक्शन को बंद करने का मौका है। मैंने लॉग इन में कुछ उल्लेख किया है पीजी :: TRDeadlockDetected: ERROR: डेडलॉक का पता चला। क्या यह कार्यकर्ता को टाइमआउट सेट के साथ भी पूरा नहीं करेगा?

+0

कोई विशिष्ट कारण आप कार्यकर्ता "प्रदर्शन" विधि के अंदर एक सेमाफोर लॉक का प्रयोग कर रहे है? मैं यह पूछ रहा हूं क्योंकि मुझे लगता है कि साइडकीक + लॉकिंग का यह मिश्रण थोड़ा खतरनाक है। [साइडकीक लोगों की सिफारिश] [https://github.com/mperham/sidekiq/wiki/Best-Practices) नौकरियों को जितना संभव हो उतना अलग किया जाना चाहिए, इसलिए #perform –

+0

के दौरान सामान लॉक करके कोई बाधाएं या संभावित डेडलॉक्स नहीं हो सकते हैं सिडेटिक के साथ संयोजन में मैंने देखा कि कभी-कभी एक ही आईडी को कतार में फेंक दिया जाएगा, यह इसे दो बार संसाधित होने से रोकता है। – Geesu

उत्तर

1

आप अद्वितीय काम निष्पादन सुनिश्चित करना चाहते हैं को देखते हुए, मैं सभी ताले को दूर करने का प्रयास और तरह Sidekiq Unique Jobs

इस मामले में एक प्लगइन के लिए काम विशिष्टता नियंत्रण प्रतिनिधि होता है, भले ही sidetiq एक ही काम आईडी दो बार enqueue, इस प्लगइन सुनिश्चित इसे एक ही समय में लगाया/संसाधित किया जाएगा।

+0

तो क्या आपको विश्वास है कि यह मुद्दा रेडिस-सेमफोर है? मुझे अभी भी नहीं पता कि टाइमआउट को क्यों नजरअंदाज कर दिया जाएगा। – Geesu

0

तुम भी ActiveRecord with_lock तंत्र की कोशिश कर सकते: http://api.rubyonrails.org/classes/ActiveRecord/Locking/Pessimistic.html

+0

मुझे वास्तव में संदेह है कि यह समस्या का वास्तविक कारण हो सकता है: http://blog.headius.com/2008/02/rubys-threadraise-threadkill-timeoutrb.html – Geesu

+0

आह, हाँ, ऐसा लगता है। स्वयं को नोट करें, डेटाबेस लॉक के साथ टाइमआउट न करें। क्या आपके पास समय निकालने की कोई वजह है? हो सकता है कि रिकॉर्ड को तोड़ने का एक तरीका है ताकि रिकॉर्ड के बीच में प्रवेश की अनुमति मिल सके। – lobati

+0

बीटीडब्ल्यू, आपको अपने प्रश्न का उत्तर देने पर विचार करना चाहिए। – lobati

संबंधित मुद्दे