【问题标题】:Creating a variable per instance, rather than per request, with Sinatra modular style使用 Sinatra 模块化风格为每个实例而不是每个请求创建一个变量
【发布时间】:2014-02-01 15:09:45
【问题描述】:

我有一个 Sinatra 应用程序,以模块化风格编写,在 Heroku 上运行。它使用 Redis,我的 Redis 连接数量有限(10)。我发现它经常会抛出错误,抱怨它已经用完了 Redis 连接。所以我开始使用connection_pool,希望能解决问题;单个 Redis 连接池,应用程序每次都会选择其中一个,而不是尝试在每个请求上创建新连接。

但我仍然遇到同样的问题。我可以对单个查询执行大量 Redis 查询而不会产生任何抱怨。但是,如果我重新加载一个测试页面,它只执行一些 Redis 查询,连续几次,我会再次收到“Redis::CommandError - ERR max number of clients reached”错误。

所以我假设它可能会在每个请求上创建一个新的 connection_pool 实例......我不知道。但这不是我所期望的“池化”。

我有这样的事情:

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

require 'thin'
require 'myapp/frontend'

MyApp::Frontend.run!

还有 Sinatra 应用程序:

# 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

有什么想法吗?当前站点的流量非常低,因此应该可以。

【问题讨论】:

    标签: ruby heroku redis sinatra connection-pooling


    【解决方案1】:

    每次处理/tester/ 的get 请求时都会创建一个新的@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
    

    【讨论】:

    • 哦,太棒了,谢谢卢卡斯!这似乎对我的小测试有效。看起来我根本不需要使用 connection_pool - 你觉得呢?一个小错字:是settings.redis... 而不是setting.redis...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    • 2012-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-14
    • 1970-01-01
    相关资源
    最近更新 更多