2014-01-13 25 views
0

我有一個西納特拉的應用程序,寫在模塊化的風格,在Heroku上運行。它使用Redis,並且我有有限數量(10)的Redis連接。我發現它經常會拋出錯誤,抱怨說它已經用完了Redis連接。所以我開始使用connection_pool來希望能夠解決問題;一個Redis連接池,應用程序會每次選擇其中一個,而不是嘗試爲每個請求創建一個新連接。創建每個實例的變量,而不是每個請求,與西納特拉模塊化風格

但我仍然得到同樣的問題。我可以在單個查詢中完成大量的Redis查詢,而無需投訴。但是,如果我重新加載了一個測試頁面,它只是執行一些Redis查詢,而且連續幾次,我又一次得到「Redis :: CommandError - ERR最大達到的客戶端數量」錯誤。

所以我猜想,也許,這是創造對每個請求connection_pool的新實例......我不知道。但它並不像我期望的那樣「彙集」。

我有這樣的事情:

# myapp.rb 
$LOAD_PATH.unshift(File.dirname(__FILE__)) 
$stdout.sync = true 

require 'thin' 
require 'myapp/frontend' 

MyApp::Frontend.run! 

而且西納特拉應用:

# myapp/frontend.rb 
require 'sinatra/base' 
require 'redis' 
require 'connection_pool' 
require 'uuid' 

module MyApp 
    class Frontend < Sinatra::Base 

    helpers do 
     def redis_pool 
     @redis_pool ||= ConnectionPool.new(:size => 8, :timeout => 5) do 
      redis_uri = URI.parse(ENV['REDISCLOUD_URL']) 
      client = ::Redis.new(:host => redis_uri.host, 
           :port => redis_uri.port, 
           :password => redis_uri.password) 
     end 
     end 
    end 

    get '/tester/' 
     redis_pool.with do |r| 
     id = UUID.generate 
     r.hset(:user, id, "Some data") 
     r.hget(:user, id) 
     r.hdel(:user, id) 
     end 
     p "DONE" 
    end 
    end 
end 

的Procfile樣子:

web: ruby myapp.rb 

任何想法?目前的網站流量很低,所以這應該是可能的。

回答

1

每次處理/tester/的獲取請求時都會創建@redis_pool的新實例,因爲每次都會調用幫助器方法redis_pool

可以使用Sinatra的設置幫手,只有一次初始化Redis的連接:

config do 
    redis_uri = URI.parse(ENV['REDISCLOUD_URL']) 
    set :redis, Redis.new(:host => redis_uri.host, 
         :port => redis_uri.port, 
         :password => redis_uri.password) 
end 

現在的應用程序的每個實例有一個持續的所有請求一個Redis的連接。訪問設置像這樣

get '/tester/' 
    id = UUID.generate 
    settings.redis.hset(:user, id, "some data") 
    settings.redis.hget(:user, id) 
    settings.redis.hdel(:user, id) 
    p "DONE" 
end 
+0

哦,輝煌的,謝謝盧卡斯!這似乎在我的小測試中起作用。看起來像我根本不需要使用connection_pool - 你認爲如何?一個小錯字:它是'settings.redis ...'而不是'setting.redis ...' –