Puma 服务器在发送 capistrano "puma:restart" 信号后挂起
Puma server hangs after capistrano "puma:restart" signal is sent
当我第一次使用 cap [env] deploy
部署我的应用程序时,一切都按预期进行。代码已部署,puma 服务器已成功启动 puma:start
。
puma 启动的 capistrano 输出
* 2015-01-09 12:19:37 executing `puma:start'
* executing "cd /path/to/app/current && bundle exec puma -q -d -e production -C ./config/puma/production.rb"
servers: ["example.com"]
[example.com] executing command
** [out :: example.com] Puma starting in single mode...
** [out :: example.com] * Version 2.9.2 (ruby 2.1.5-p273), codename: Team High Five
** [out :: example.com] * Min threads: 0, max threads: 16
** [out :: example.com] * Environment: production
** [out :: example.com] * Listening on unix:///path/to/app/shared/sockets/puma.sock
** [out :: example.com] * Daemonizing...
如果我更改代码并尝试重新部署,而不是调用 puma:start
,capistrano 会调用 puma:restart
,这就像成功一样,但实际上并没有重新启动 puma。
* 2015-01-09 12:27:56 executing `puma:restart'
* executing "cd /path/to/app/current && bundle exec pumactl -S /path/to/app/shared/sockets/puma.state restart"
servers: ["example.com"]
[example.com] executing command
** [out :: example.com] Command restart sent success
此时,如果我刷新网页,我会收到 504 Gateway Time-out 错误。它与 this issue..
非常相似
正如那个人所建议的那样,如果我将 workers 1
添加到我的 puma 配置文件中,重新启动会起作用,但 start/stop 不会。
在我目前的状态下(没有工人),如果我这样做 cap [env] puma:stop
,它不会阻止 puma。它还 NOT 删除以下任何文件:
/path/to/app/shared/pids/puma.pid
/path/to/app/shared/sockets/puma.sock
/path/to/app/shared/sockets/puma.state
重要提示
在我的 Rails 服务器中,我使用 ActionController::Live
和 Rails 4.1。我使用 Javascript / Redis 连接到事件流。我在我的 nginx 错误日志中注意到了这一点:
nginx错误日志
2015/01/09 12:29:32 [error] 8992#0: *371 upstream timed out (110:
Connection timed out) while reading response header from upstream,
client: [ip], server: example.com, request: "GET /build_configurations/refresh_workers HTTP/1.1",
upstream: "http://unix:///path/to/app/shared/sockets/puma.sock/build_configurations
/refresh_workers", host: "example.com", referrer: "https://example.com/"
总而言之,我怎样才能成功地使用 cap [env] deploy
将更新部署到我的代码,同时让 puma 启动和重新启动正常?
更新
我发现 this issue 谈到用 ActionController::Live
重启 puma,但似乎没有解决方案。
使用我在 this other Stack Overflow answer 中找到的信息,我能够实施似乎可以解决此问题的检测信号。我自己还没有完全理解所有的机制,但我从一个初始化器开始心跳:
config/initializers/redis.rb
REDIS = Redis.new(url: "redist://localhost:6379")
heartbeat_thread = Thread.new do
while true
REDIS.publish('heartbeat','thump')
sleep 2.seconds
end
end
at_exit do
# not sure this is needed, but just in case
heartbeat_thread.kill
REDIS.quit
end
我的控制器有:
def build_status_events
response.headers["Content-Type"] = "text/event-stream"
redis = Redis.new(url: "redist://localhost:6379")
# blocks the current thread
redis.psubscribe(['my_event', 'heartbeat']) do |on|
on.pmessage do |pattern, event, data|
response.stream.write("event: #{event}\n")
if event == 'heartbeat'
response.stream.write("data: heartbeat\n\n")
else
response.stream.write("data: #{data.to_json}\n\n")
end
end
end
rescue IOError
logger.info 'Events stream closed'
ensure
logger.info 'Stopping Events streaming thread'
redis.quit
response.stream.close
end
我相信发生的情况是心跳被发布,如果出现错误,将调用确保块并关闭订阅。然后 puma 按预期重新启动。如果谁有更好的解决方案,或者更多的信息,欢迎评论或者补充答案。
当我第一次使用 cap [env] deploy
部署我的应用程序时,一切都按预期进行。代码已部署,puma 服务器已成功启动 puma:start
。
puma 启动的 capistrano 输出
* 2015-01-09 12:19:37 executing `puma:start'
* executing "cd /path/to/app/current && bundle exec puma -q -d -e production -C ./config/puma/production.rb"
servers: ["example.com"]
[example.com] executing command
** [out :: example.com] Puma starting in single mode...
** [out :: example.com] * Version 2.9.2 (ruby 2.1.5-p273), codename: Team High Five
** [out :: example.com] * Min threads: 0, max threads: 16
** [out :: example.com] * Environment: production
** [out :: example.com] * Listening on unix:///path/to/app/shared/sockets/puma.sock
** [out :: example.com] * Daemonizing...
如果我更改代码并尝试重新部署,而不是调用 puma:start
,capistrano 会调用 puma:restart
,这就像成功一样,但实际上并没有重新启动 puma。
* 2015-01-09 12:27:56 executing `puma:restart'
* executing "cd /path/to/app/current && bundle exec pumactl -S /path/to/app/shared/sockets/puma.state restart"
servers: ["example.com"]
[example.com] executing command
** [out :: example.com] Command restart sent success
此时,如果我刷新网页,我会收到 504 Gateway Time-out 错误。它与 this issue..
非常相似正如那个人所建议的那样,如果我将 workers 1
添加到我的 puma 配置文件中,重新启动会起作用,但 start/stop 不会。
在我目前的状态下(没有工人),如果我这样做 cap [env] puma:stop
,它不会阻止 puma。它还 NOT 删除以下任何文件:
/path/to/app/shared/pids/puma.pid
/path/to/app/shared/sockets/puma.sock
/path/to/app/shared/sockets/puma.state
重要提示
在我的 Rails 服务器中,我使用 ActionController::Live
和 Rails 4.1。我使用 Javascript / Redis 连接到事件流。我在我的 nginx 错误日志中注意到了这一点:
nginx错误日志
2015/01/09 12:29:32 [error] 8992#0: *371 upstream timed out (110:
Connection timed out) while reading response header from upstream,
client: [ip], server: example.com, request: "GET /build_configurations/refresh_workers HTTP/1.1",
upstream: "http://unix:///path/to/app/shared/sockets/puma.sock/build_configurations
/refresh_workers", host: "example.com", referrer: "https://example.com/"
总而言之,我怎样才能成功地使用 cap [env] deploy
将更新部署到我的代码,同时让 puma 启动和重新启动正常?
更新
我发现 this issue 谈到用 ActionController::Live
重启 puma,但似乎没有解决方案。
使用我在 this other Stack Overflow answer 中找到的信息,我能够实施似乎可以解决此问题的检测信号。我自己还没有完全理解所有的机制,但我从一个初始化器开始心跳:
config/initializers/redis.rb
REDIS = Redis.new(url: "redist://localhost:6379")
heartbeat_thread = Thread.new do
while true
REDIS.publish('heartbeat','thump')
sleep 2.seconds
end
end
at_exit do
# not sure this is needed, but just in case
heartbeat_thread.kill
REDIS.quit
end
我的控制器有:
def build_status_events
response.headers["Content-Type"] = "text/event-stream"
redis = Redis.new(url: "redist://localhost:6379")
# blocks the current thread
redis.psubscribe(['my_event', 'heartbeat']) do |on|
on.pmessage do |pattern, event, data|
response.stream.write("event: #{event}\n")
if event == 'heartbeat'
response.stream.write("data: heartbeat\n\n")
else
response.stream.write("data: #{data.to_json}\n\n")
end
end
end
rescue IOError
logger.info 'Events stream closed'
ensure
logger.info 'Stopping Events streaming thread'
redis.quit
response.stream.close
end
我相信发生的情况是心跳被发布,如果出现错误,将调用确保块并关闭订阅。然后 puma 按预期重新启动。如果谁有更好的解决方案,或者更多的信息,欢迎评论或者补充答案。