2017-02-03 10 views
15

मैं रेल 5 और रूबी 2.4 का उपयोग कर रहा हूं। मैं नीचे कैसे देखकर बता सकता हूं, या आप एक ही समय में चल रहे कई धागे चल रहे हैं?क्या समेकन तब भी होता है जब थ्रेड पूल में केवल एक धागा होता है?

pool = Concurrent::FixedThreadPool.new(1) 
promises = links.map do |link| 
    Concurrent::Promise.execute(executor: pool) do 
    result = process_link(link) 
    if result 
     if result.kind_of?(Array) 
     result.each do |my_obj| 
      my_obj.update_attributes({ :a => a }) 
      records_processed = records_processed + my_obj.matches.count 
     end 
     else 
     records_processed = records_processed + result.matches.count 
     result.update_attributes({ :a => a }) 
     end 
    end 
    end 
end 
promises.map(&:wait).map(&:value!) 

मैं अपने पूल के लिए निर्धारित किया है के रूप में "1" मेरी धारणा है कि कुछ भी नहीं समवर्ती चल रहा है, लेकिन मैं इस त्रुटि प्राप्त हो रही है ...

Error during processing: (ActiveRecord::ConnectionTimeoutError) could not obtain a connection from the pool within 5.000 seconds (waited 5.002 seconds); all pooled connections were in use 
/Users/nataliab/.rvm/gems/[email protected]/gems/activerecord-5.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:202:in `block in wait_poll' 
/Users/nataliab/.rvm/gems/[email protected]/gems/activerecord-5.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:193:in `loop' 
/Users/nataliab/.rvm/gems/[email protected]/gems/activerecord-5.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:193:in `wait_poll' 
/Users/nataliab/.rvm/gems/[email protected]/gems/activerecord-5.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:154:in `internal_poll' 
/Users/nataliab/.rvm/gems/[email protected]/gems/activerecord-5.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:278:in `internal_poll' 
/Users/nataliab/.rvm/gems/[email protected]/gems/activerecord-5.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:148:in `block in poll' 
/Users/nataliab/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/monitor.rb:214:in `mon_synchronize' 
/Users/nataliab/.rvm/gems/[email protected]/gems/activerecord-5.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:158:in `synchronize' 
/Users/nataliab/.rvm/gems/[email protected]/gems/activerecord-5.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:148:in `poll' 
/Users/nataliab/.rvm/gems/[email protected]/gems/activerecord-5.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:717:in `acquire_connection' 
/Users/nataliab/.rvm/gems/[email protected]/gems/activerecord-5.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:490:in `checkout' 
/Users/nataliab/.rvm/gems/[email protected]/gems/activerecord-5.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:364:in `connection' 
/Users/nataliab/.rvm/gems/[email protected]/gems/activerecord-5.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:883:in `retrieve_connection' 
/Users/nataliab/.rvm/gems/[email protected]/gems/activerecord-5.0.1/lib/active_record/connection_handling.rb:128:in `retrieve_connection' 

मैं ऊपर नहीं मिलता त्रुटि अगर मैं अपने कोड को संशोधित चलाने के लिए मैं कहाँ सकारात्मक नहीं संगामिति चल रहा है हूँ ...

links.each do |link| 
    result = process_link(link) 
    if result 
    if result.kind_of?(Array) 
     result.each do |race| 
     my_obj.update_attributes({ :a => a }) 
     records_processed = records_processed + my_obj.matches.count 
     end 
    else 
     records_processed = records_processed + result.matches.count 
     result.update_attributes({ :a => a }) 
    end 
    end 
end 

संपादित करें: यह मेरा विकास के माहौल के लिए मेरे डेटाबेस विन्यास है onment। यह भी ध्यान रखें कि यह सब रेल कंसोल में चलाया जा रहा है।

development: 
    adapter: postgresql 
    encoding: utf8 
    database: sims 
    username: postgres 
    password: password 
    pool: 5 
    timeout: 15000 
    host: 127.0.0.1 
+0

तो क्या आप अभी भी इसे पूरी तरह से साफ प्रतिलिपि पर प्राप्त करते हैं? – ndn

उत्तर

7

आपकी धारणा है कि एकाधिक थ्रेड को एक साथ चलाना चाहिए क्योंकि कनेक्शन पूल समाप्त हो रहा है, सही नहीं है। सिर्फ इसलिए कि कनेक्शन पूल से कनेक्शन अभी भी 'चेक आउट' है, इसका मतलब यह नहीं है कि थ्रेड में चेक-आउट कनेक्शन पर वर्तमान में एक क्वेरी निष्पादित की जा रही है, इसका मतलब यह है कि थ्रेड के कनेक्शन को वापस चेक नहीं किया गया है। थ्रेड निष्क्रिय बैठे जा सकते हैं लेकिन फिर भी कनेक्शन पूल से कनेक्शन पर पकड़ लेते हैं जब तक कि इसे स्पष्ट रूप से समाप्त नहीं किया गया हो।

चूंकि ActiveRecord कनेक्शन थ्रेड-लोकल हैं, इसलिए आप इस मामले में कर रहे हैं, जैसे कई थ्रेड पर ActiveRecord क्वेरी चलाकर कनेक्शन पूल को समाप्त कर सकते हैं। (हर बार Concurrent::FixedThreadPool.new(1) कहा जाता है, एक नया धागा बनाया जाता है।) भले ही आप एक समय में एक ही थ्रेड पर क्वेरी चला रहे हों, डिफ़ॉल्ट रूप से एक कनेक्शन तब भी समाप्त हो जाएगा जब तक कि वे समाप्त नहीं हो जाते हैं।

इससे बचने के लिए, आप या तो मैन्युअल रूप से कनेक्शन का उपयोग करने के बाद जांच कर सकते हैं, या सुनिश्चित कर सकते हैं कि आपके धागे समाप्त हो जाएं (मारे गए) ताकि उनके कनेक्शन पूल द्वारा पुनर्प्राप्त किए जा सकें (reaped)।

  • मैन्युअल कनेक्शन में जांच करने के लिए अपने विकल्पों के लिए ConnectionPool documentation को देखें।

    values = promises.map(&:value!) 
    pool.shutdown 
    pool.wait_for_termination 
    
    : के बाद आप इसे का उपयोग कर लेने

    Concurrent::Promise.execute(executor: pool) do 
        ActiveRecord::Base.connection_pool.with_connection do 
        # update_attributes, etc 
        end 
    end 
    
  • सुनिश्चित करने के लिए सभी थ्रेड समाप्त कर दिया जाता, #shutdown थ्रेड पूल पर #wait_for_termination के बाद कहते हैं: सबसे आसान तरीका है एक with_connection ब्लॉक में अपने ActiveRecord कोड रैप करने के लिए है

3

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

जब आपने अपना कोड कार्यान्वयन बदल दिया ताकि इसमें थ्रेड पूल न हो, तो पूल से थ्रेड पर प्रतीक्षा करने के कारण एप्लिकेशन को कनेक्शन टाइमआउट की संभावना के बिना स्पष्ट रूप से सिंगल थ्रेड किया गया था। अपने थ्रेड पूल (शायद 3 या 5 तक) के आकार को बढ़ाने का प्रयास करें और देखें कि क्या आपको अभी भी वही अपवाद मिल रहा है या नहीं।

+0

जब आप कहते हैं कि "पूल से उपलब्ध थ्रेड बहुत लंबे समय तक व्यस्त था और कनेक्शन टाइमआउट अपवाद का कारण बन गया", मैं इसका परीक्षण कैसे करूं - यानी मैं थ्रेड के लिए टाइमआउट अवधि कैसे निर्धारित करूं? –

4

आप मानते हैं कि केवल एक धागा गलत है। वहां दो हैं - थ्रेड पूल में से एक और मुख्य जो थ्रेड पूल में एक को जन्म देता है।

आप भ्रमित हो सकते हैं क्योंकि आपने मुख्य धागा इंतजार किया है और इसे डेटाबेस तक नहीं पहुंचना चाहिए। इसका मतलब यह नहीं है कि यह अभी भी कनेक्शन नहीं रखता है, इसलिए दूसरे धागे को एक प्राप्त करने से रोकता है।

एक सामान्य नियम के अपने डेटाबेस कनेक्शन पूल धागे के कम से कम नंबर करने के लिए सेट किया जाना चाहिए के रूप में पैदा की + 1. इस मामले में - 2.


कोड आसानी से पुन: पेश करने:

# migration 
class CreateFoos < ActiveRecord::Migration[5.0] 
    def change 
    create_table :foos do |t| 
     t.integer :bar 
    end 
    end 
end 

# model 
class Foo < ApplicationRecord 
end 

# rake task 
task experiment: :environment do 
    Foo.create 
    pool = Concurrent::FixedThreadPool.new(1) 
    promise = 
    Concurrent::Promise.execute(executor: pool) do 
     Foo.first.update_attributes!(bar: rand(-42..42)) 
    end 
    promise.wait.value! 
end 

अपने config/database.yml में pool से 1 सेट करें और कार्य चलाएं। आपको एक त्रुटि मिलेगी। इसे 2 पर सेट करें - यह ठीक होगा।

आप पूल में धागे की संख्या बढ़ा सकते हैं और प्रसंस्करण के लिए कम से कम वादे जोड़ सकते हैं। आप डेटाबेस कनेक्शन पूल = थ्रेड पूल में धागे की संख्या के लिए लगातार असफल रहेंगे और यदि आप config/database.yml में एक और जोड़ते हैं तो सफल होंगे।

+0

मैंने अपने प्रश्न में अपना डेटाबेस कॉन्फ़िगरेशन शामिल किया। आपने जो सुझाव दिया उससे ऊपर 5 पर सेट किया गया था। फिर भी, मुझे अभी भी त्रुटि मिलती है। मेरा मानना ​​है कि एक से अधिक धागे निष्पादित होते हैं, लेकिन अगर यह केवल 2 था, तो मेरा कनेक्शन पूल 5 पर सेट होने पर मुझे एरर क्यों मिलेगा? –

+0

@ नेटलिया, तो यह वास्तव में अजीब है। क्या आप प्यूमा जैसे बहु थ्रेडेड सर्वर का उपयोग कर रहे हैं? – ndn

+0

मैं इसे रेल कंसोल के माध्यम से चला रहा हूं। वह किसी भी वेबसर्वर का उपयोग नहीं करता है, है ना? –

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