2011-10-05 16 views
7

मैं एक ऐसा फ़ंक्शन लिखने का प्रयास कर रहा हूं जो डिफ़ॉल्ट टीसीपी सेटिंग्स का उपयोग करके रेडिस से कनेक्ट करने का प्रयास करता है, और यदि यह विफल हो जाता है, तो यूनिक्स सॉकेट के माध्यम से रेडिस से कनेक्ट करने का प्रयास करता है। मेरा इरादा एक एकल कनेक्शन स्क्रिप्ट है जो मेरे सभी सिस्टम पर काम करता है, जिनमें से कुछ टीसीपी और अन्य जो सॉकेट का उपयोग करते हैं।रेडिस कनेक्शन से इनकार करने में असमर्थ

हालांकि, मैं असफल टीसीपी कनेक्शन से बचाव नहीं कर सकता। यहां मेरी टेस्ट स्क्रिप्ट है।

require "redis" 

def r 
    begin 
    $redis ||= Redis.new 
    rescue 
    $redis = Redis.new(:path => "/tmp/redis.sock") 
    end 
end 

puts "You have #{r.keys.count} redis keys" 

rescue ब्लॉक कभी निष्पादित नहीं होता है और इसके बजाय एक अपवाद उठाया जाता है। यहां इस स्क्रिप्ट का आउटपुट है।

 
/usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:236:in `rescue in establish_connection': Connection refused - Unable to connect to Redis on 127.0.0.1:6379 (Errno::ECONNREFUSED) 
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:222:in `establish_connection' 
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:23:in `connect' 
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:247:in `ensure_connected' 
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:137:in `block in process' 
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:206:in `logging' 
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:136:in `process' 
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:46:in `call' 
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis.rb:246:in `block in keys' 
    from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/monitor.rb:201:in `mon_synchronize' 
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis.rb:245:in `keys' 
    from scripts/redis.rb:11:in `<main>' 

मैंने सत्यापित किया है कि Redis.new(:path => "/tmp/redis.sock") अपेक्षित काम करता है। मैंने rescue Errno::ECONNREFUSED का उपयोग करके मेरे बचाव ब्लॉक के साथ अधिक विशिष्ट होने की कोशिश की है। मुझे यकीन नहीं है कि मैं इस अपवाद को क्यों नहीं पकड़ सकता।

कोई विचार?

उत्तर

5

यह पता चला है कि Redis.new पर कॉल करते समय अपवाद नहीं फेंक दिया जा रहा है। कनेक्शन ऑब्जेक्ट पर कुछ विधियों (इस मामले में, Redis#keys) तक अपवाद नहीं फेंक दिया जाता है। यह संशोधित कनेक्शन फ़ंक्शन चाल करने लगता है।

require "redis" 

def r 
    begin 
    $redis ||= Redis.new 
    $redis.inspect # needed to know if connection failed 
    rescue 
    $redis = Redis.new(:path => "/tmp/redis.sock") 
    end 
    $redis 
end 
+4

मैं जानता हूँ कि यह एक पुरानी जवाब है लेकिन सिर्फ क्यों ऐसा होता है पर प्रकाश का एक सा डाला। रेडिस कनेक्शन आलसी भरा हुआ है, इसलिए जब तक आप पहली कमांड नहीं करते हैं तब तक आप कनेक्ट नहीं होंगे। –

+0

ऐसा लगता है कि आप सबसे अच्छी चीज की तरह '$ redis.ping' कॉल कर सकते हैं। जैसा कि दूसरे उत्तर में बताया गया है, '.inspect' पर्याप्त नहीं है और' .keys 'रेडिस में सभी आइटम पुनर्प्राप्त करता है, जिससे आप थोड़ी देर प्रतीक्षा कर सकते हैं (रेडिस में प्रविष्टियों के # के आधार पर) और बहुत सारी मेमोरी पर कब्जा कर रहा है कचरा इकट्ठा नहीं किया जा सकता है (क्योंकि यह किसी भी चर के लिए असाइन नहीं किया गया है)। – lucke84

2

मैंने पाया कि $redis.inspect वास्तव में REDIS कनेक्शन का प्रयोग नहीं किया। मैंने इसे $redis.keys के साथ बदल दिया और यह सही ढंग से अपवाद फेंक दिया। नोट, Heroko पर चल रहा है और यह पर्यावरण चर में गुजरता है। उसके बाद मेरे पास निरंतर REDIS है जो मैं पूरे एप्लिकेशन में उपयोग करता हूं।

मेरी config/initializers/redis.rb में:

uri = URI.parse(ENV['REDISTOGO_URL']) 
begin 
    redis ||= Redis.new(:host => uri.host, :port => uri.port, :password => uri.password) 
    redis.keys # needed to know if connection failed 
    REDIS = redis 
rescue 
    puts("Redis not loaded on #{uri.port}") 
    REDIS = nil 
end 
+0

'$ redis.inspect' ऐसा करने का एक अच्छा तरीका नहीं हो सकता है क्योंकि सभी रेडिस रत्न इस कॉल से कनेक्ट नहीं होंगे। 'redis.keys' हालांकि सभी रेडिस कुंजियों को पुनः प्राप्त करने का प्रयास करेगा, जो आपके पास वास्तव में बड़ा डेटाबेस है, तो चकित होगा। मैं इसके बजाय '$ redis.info' या' $ redis.get ("कुछ-कुंजी-वह-करता-या-अस्तित्व में नहीं है") का उपयोग करेगा। उन आदेशों को अभी भी दुनिया को वापस लाने की कोशिश किए बिना, रेडिस सर्वर पर भेजा जाएगा। –

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