gpt4 book ai didi

ruby-on-rails - 使用 `ActiveRecord with_connection do` 和 ActionController::Live 时出现线程错误

转载 作者:数据小太阳 更新时间:2023-10-29 06:24:56 32 4
gpt4 key购买 nike

主要编辑:自从最初发现此问题后,我已将其缩减为以下内容。我认为现在这是对问题的略微更精确的描述。因此,对 OP 的评论可能并不完全相关。

编辑 在 rails/puma 项目中发布的轻微修改版本:https://github.com/rails/rails/issues/21209 , https://github.com/puma/puma/issues/758

编辑 现在用 OS X 和 Rainbows 复制

总结: 当使用 Puma 并运行长时间运行的连接时,我一直收到与跨线程的 ActiveRecord 连接相关的错误。这在消息中表现出来,例如 消息类型 0x## 空闲时从服务器到达 和锁定(崩溃)的服务器。

设置:

  • Ubuntu 15/OSX 优胜美地
  • PostgreSQL (9.4)/MySQL (mysqld 5.6.25-0ubuntu0.15.04.1)
  • Ruby - MRI 2.2.2p95(2015-04-13 修订版 50295)[x86_64-linux]/Rubinius rbx-2.5.8
  • rails (4.2.34.2.1)
  • 美洲狮(2.12.22.11)
  • pg (pg-0.18.2)/mysql2

注意,并非以上版本的所有组合都已尝试。第一个列出的版本是我目前正在测试的版本。

  • rails 新问题测试
  • 添加路线 get 'events' => 'streaming#events'
  • 添加一个 Controller 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

美洲狮配置:

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
  • 运行服务器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

这相当一致地导致应用服务器的完全锁定(在 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

在“现实世界”中,我有很多额外的元素,问题是随机出现的。我的研究表明此消息来自 libpq 并且是“通信问题,可能在不同线程中使用连接” 的潜台词。最后,在写这篇文章时,我锁定了服务器,但在任何日志中都没有一条消息。

所以,问题:

  1. 我遵循的模式是否在某种程度上不合法?我误解了什么?
  2. 这里处理数据库连接的“标准”是什么,可以避免这些问题?
  3. 你能找到一种可靠地重现它的方法吗?

  1. 这里的根本问题是什么,我该如何解决?

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):

最佳答案

警告:将“答案”读作“似乎有所作为”


如果我将 Controller block 更改为如下所示,我看不到问题发生:

begin
#...
while true do
t = Thread.new do #<<<<<<<<<<<<<<<<<
ActiveRecord::Base.connection_pool.with_connection do |conn|
#...
end
end
t.join #<<<<<<<<<<<<<<<<<
end
#...
rescue IOError
#...

但我不知道这是否真的解决了问题,或者只是让它变得极不可能。我也无法真正理解为什么这会有所作为。

将此作为解决方案发布以防万一,但仍在深入研究这个问题。

关于ruby-on-rails - 使用 `ActiveRecord with_connection do` 和 ActionController::Live 时出现线程错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31535545/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com