在发送capistrano“puma:restart”信号后,Puma服务器挂起

时间:2015-01-09 18:08:36

标签: ruby-on-rails nginx capistrano puma

当我第一次使用cap [env] deploy部署我的应用程序时,一切都按预期工作。部署代码并使用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配置文件中,重启将会起作用,但启动/停止不会。

在我目前的状态(没有工人),如果我做cap [env] puma:stop,它不会停止美洲狮。它还 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部署代码更新?

更新

我发现this issue谈到重新启动与ActionController::Live的美洲狮,但似乎没有解决方案。

1 个答案:

答案 0 :(得分:1)

使用我在this other Stack Overflow answer中找到的信息,我能够实现一个可以解决这种情况的心跳。我自己并没有完全理解所有的机制,但我开始使用初始化程序来启动心跳:

<强>配置/初始化/ 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

我相信会发生的是心跳被发布,如果出现错误,将调用ensure块并关闭订阅。然后puma按预期重新启动。如果有人有更好的解决方案或更多信息,请发表评论或添加其他答案。