but*_*ton 33 ruby multithreading connection-pooling ruby-on-rails actioncontroller
主要编辑:自从最初发现这个问题以来,我已将其削减到下面.我认为现在对这个问题的描述略微准确.因此,对OP的评论可能不完全相关.
编辑在rails/puma项目中发布的轻微修改版本:https://github.com/rails/rails/issues/21209,https://github.com/puma/puma/issues/758
编辑现在转载OS X和Rainbows
简介: 当使用Puma并运行长时间运行的连接时,我一直收到与跨越线程的ActiveRecord连接相关的错误.这表现在消息 message type 0x## arrived from server while idle
和锁定(崩溃)服务器中.
设置:
mysqld 5.6.25-0ubuntu0.15.04.1
)2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
/ Rubiniusrbx-2.5.8
4.2.3
,4.2.1
)2.12.2
,2.11
)pg-0.18.2
)/ mysql2请注意,并非所有上述版本的组合都已尝试过.首先列出的版本是我目前正在测试的版本.
rails new issue-test
get 'events' => 'streaming#events'
streaming_controller.rb
pool: 2
但看到不同的池大小)码:
class StreamingController < ApplicationController
include ActionController::Live
def events
begin
response.headers["Content-Type"] = "text/event-stream"
sse = SSE.new(response.stream)
sse.write( {:data => 'starting'} , {:event => :version_heartbeat})
ActiveRecord::Base.connection_pool.release_connection
while true do
ActiveRecord::Base.connection_pool.with_connection do |conn|
ActiveRecord::Base.connection.query_cache.clear
logger.info 'START'
conn.execute 'SELECT pg_sleep(3)'
logger.info 'FINISH'
sse.write( {:data => 'continuing'}, {:event => :version_heartbeat})
sleep 0.5
end
end
rescue IOError
rescue ClientDisconnected
ensure
logger.info 'Ensuring event stream is closed'
sse.close
end
render nothing: true
end
end
Run Code Online (Sandbox Code Playgroud)
Puma配置:
workers 1
threads 2, 2
#...
bind "tcp://0.0.0.0:9292"
#...
activate_control_app
on_worker_boot do
require "active_record"
ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])
end
Run Code Online (Sandbox Code Playgroud)
puma -e production -C path/to/puma/config/production.rb
测试脚本:
#!/bin/bash
timeout 30 curl -vS http://0.0.0.0/events &
timeout 5 curl -vS http://0.0.0.0/events &
timeout 30 curl -vS http://0.0.0.0/events
Run Code Online (Sandbox Code Playgroud)
这相当一致地导致应用程序服务器的完全锁定(在PostgreSQL中,请参阅注释).可怕的消息来自libpq
:
message type 0x44 arrived from server while idle
message type 0x43 arrived from server while idle
message type 0x5a arrived from server while idle
message type 0x54 arrived from server while idle
Run Code Online (Sandbox Code Playgroud)
在"现实世界"中,我有相当多的额外元素,这个问题随机出现.我的研究表明,这条消息来自libpq
于"通信问题,可能是在不同线程中使用连接"的潜台词.最后,在写这篇文章时,我在任何日志中都没有一条消息就锁定了服务器.
那么,问题是:
要么
MySQL的
如果运行MySQL,消息有点不同,应用程序恢复(虽然我不确定它是否处于某种未定义状态):
F, [2015-07-30T14:12:07.078215 #15606] FATAL -- :
ActiveRecord::StatementInvalid (Mysql2::Error: This connection is in use by: #<Thread:0x007f563b2faa88@/home/dev/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/actionpack-4.2.3/lib/action_controller/metal/live.rb:269 sleep>: SELECT `tasks`.* FROM `tasks` ORDER BY `tasks`.`id` ASC LIMIT 1):
Run Code Online (Sandbox Code Playgroud)
警告:将“答案”解读为“似乎有所作为”
如果我将控制器块更改为如下所示,我不会看到问题发生:
begin
#...
while true do
t = Thread.new do #<<<<<<<<<<<<<<<<<
ActiveRecord::Base.connection_pool.with_connection do |conn|
#...
end
end
t.join #<<<<<<<<<<<<<<<<<
end
#...
rescue IOError
#...
Run Code Online (Sandbox Code Playgroud)
但我不知道这是否真的解决了问题,还是只是让问题变得极不可能。我也无法真正理解为什么这会产生影响。
将此作为解决方案发布,以防有帮助,但仍在深入研究该问题。
归档时间: |
|
查看次数: |
1403 次 |
最近记录: |