我在Puma / Rack服务器上使用Sequel和Sinatra。
我希望将Sequel数据库连接对象存储在会话中 - 而不是全局 - 这样我就可以为每个登录用户创建一个单独的数据库连接池。目的是为每个Web服务器登录设置一个数据库服务器。
我无法弄清楚如何执行此操作,因为Sequel数据库对象似乎是全局单例。例如,如果我尝试序列化数据库对象并存储在会话中,我将收到一条错误消息:TypeError - can't dump anonymous class:
我不想在每个路由请求上连接到数据库。
我该怎么做?以下是一些示例代码,希望能够指出我想要实现的目标:
require 'sinatra/base'
require 'pp'
require 'sequel'
require 'json'
require 'java'
require 'sqljdbc4.jar'
require 'yaml'
class MyApp < Sinatra::Base
set :sessions, true
use Rack::Session::Cookie, :key => 'rack.session',
:expire_after => 2592000,
:secret => 'sydasx'
get '/' do
db = session[:db]
DB = YAML::Load(db)
response = ''
DB['select * from SEC_USER'].each do |row|
response += row.to_s
end
response.to_json
end
get '/login/:username' do
username = params['username']
puts "username: #{username}"
conn_str = "jdbc:sqlserver://localhost:1434;databaseName=#{username};integratedSecurity=true;"
DB = Sequel.connect(conn_str)
puts "DB: #{DB.pretty_inspect}"
db = YAML::dump(DB)
puts "db: #{db}"
session[:db] = db
"logged in"
end
end
答案 0 :(得分:2)
您无法序列化Sequel :: Database对象。你有一些不错的选择:
使用机架中间件,每个请求创建一个Sequel :: Database对象,仅对请求使用该对象。在这种情况下,您不会将Sequel.connect的结果分配给常量,您将传递一个块并调用该块内的下一个变量。
在顶层创建一个Sequel :: Database对象并将其存储在DB常量中。将arbitrary_servers和server_block扩展到Sequel :: Database对象中。然后使用机架中间件在块的持续时间内检出与相应服务器的连接。
如果客户很少,可以使用Sequel的分片支持,只使用server_block扩展名而不使用arbitrary_servers。这样做的一个优点是可以缓存连接,因此您不会为每个请求建立单独的数据库连接(对于1.和2都是如此)。
如上所述使用全局哈希,键是用户名,值是Sequel :: Database对象。如果这样做,您需要确保有足够的内存来存储要跟踪的所有对象。