Sequel + ADO + Puma不是线程查询

时间:2017-01-17 19:11:25

标签: ruby sinatra puma sequel sequel-gem

我们有一个在Windows Server 2008 + SQLServer 2008 + Ruby + Sinatra + Sequel / Puma中运行的网站

我们为我们的网站开发了一个API。 当许多客户端请求访问点时,客户端同时开始获取RequestTimeout异常。

我调查了一下,我注意到Puma正在管理多线程。 但Sequel(或Sequel下面的任何一层)正在处理一个查询,即使它们来自不同的客户。

事实上,如果我启动许多Web服务器,每个侦听一个不同的端口,并为每个客户端分配一个不同的端口,则不会发生RequestTimeout异常。

我还不知道问题是Sequel,ADO,ODBC,Windows,SQLServer还是什么。 事实是,我无法切换到任何其他技术(如TinyTDS)

Bellow是一段代码,其中包含可用于复制错误的屏幕截图:

require 'sinatra'
require 'sequel'
CONNECTION_STRING =
 "Driver={SQL Server};Server=.\\SQLEXPRESS;" +
 "Trusted_Connection=no;" +
 "Database=pulqui;Uid=;Pwd=;"

DB = Sequel.ado(:conn_string=>CONNECTION_STRING)
enable :sessions
configure { set :server, :puma }
set :public_folder, './public/'
set :bind, '0.0.0.0'
get '/delaybyquery.json' do
 tid = params[:tid].to_s
 begin
 puts "(track-id=#{tid}).starting access point"
 q = "select p1.* from liprofile p1, liprofile p2, liprofile p3, liprofile p4, liprofile p5"
 DB[q].each { |row| # this query should takes a lot of time
 puts row[:id]
 }
 puts "(track-id=#{tid}).done!"
 rescue=>e
 puts "(track-id=#{tid}).error:#{e.to_s}"
 end
end
get '/delaybycode.json' do
 tid = params[:tid].to_s
 begin
 puts "(track-id=#{tid}).starting access point"
 sleep(30)
 puts "(track-id=#{tid}).done!"
 rescue=>e
 puts "(track-id=#{tid}).error:#{e.to_s}"
 end
end 

上面的代码中有2个访问点:

  1. delaybyquery.json ,通过加入同一个表生成延迟5 倍。请注意,该表必须大约1000行才能获得 查询工作真的很慢;以及

  2. delaybycode.json ,通过调用ruby睡眠产生延迟 功能。

  3. 两个接入点都接收tid(tracking-id)参数,并且都写入 在CMD中输出,所以你可以在同一个过程中跟踪两个过程的活动 窗口并检查哪个访问点阻止来自其他人的传入请求 浏览器。

    为了测试我在同一个Chrome浏览器中打开2个标签。 以下是我正在进行的2次测试。

    步骤1:运行网络服务器

    c:\ source \ pulqui> ruby​​ example.app.rb -p 81 我得到了

    以下的输出

    步骤2:按代码测试延迟

    我打电话给这个网址: 127.0.0.1:81/delaybycode.json?tid=123 5秒钟后,我调用了另一个URL 127.0.0.1:81/delaybycode.json?tid=456 下面是输出,您可以看到两个调用都是并行工作

    click here to see the screenshot

    步骤3:按查询测试延迟

    我打电话给这个网址: 127.0.0.1:81/delaybyquery.json?tid=123 5秒钟后,我调用了另一个URL 127.0.0.1:81/delaybyquery.json?tid=456 下面是输出,您可以在其中看到呼叫一次正常工作。 每次对访问点的调用都以查询超时异常结束。

    click here to see the screenshot

1 个答案:

答案 0 :(得分:0)

这几乎可以肯定是由于win32ole(Sequel的ado适配器使用的驱动程序)。它可能不会在查询期间释放GVL,这会导致您看到的问题。

如果您无法切换到TinyTDS或切换到JRuby,那么如果您想要并发查询,则唯一的选择是运行单独的Web服务器进程,并向他们发送反向代理服务器调度请求。