2014-01-13 24 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 ...' –