【问题标题】:How to detect and prevent spawning failing Unicorn workers如何检测和防止产生失败的独角兽工人
【发布时间】:2012-10-30 08:38:24
【问题描述】:

情况:我正在使用 Rails + Unicorn,使用 Capistrano 进行部署。有时 Rails 应用程序无法在生产模式下启动(尽管它不是真正的生产,而是一个暂存环境)。这通常是由于部署脚本或配置中的错误(因此通常无法通过测试检测到)而发生。发生这种情况时,独角兽主进程会杀死失败的工作人员并生成一个新的工作人员,该工作人员也会失败,依此类推。在那段时间里,unicorn 消耗大量 CPU 并使用相同的消息污染日志。

手动方式(不好):去你的主页看看是否有效。看看htop。跟踪日志。手动杀死独角兽。 缺点:容易忘记。日志被污染,CPU 在你反应的时候被加载。

另一种解决方案:使用独角兽的preload_app true。这将导致主进程快速失败。 缺点: 快乐场景中的内存消耗较高。

最佳实践: - ???

有什么方法可以巧妙地检测到独角兽主人无用地试图产生失败的孩子并阻止它?

【问题讨论】:

    标签: ruby-on-rails unicorn


    【解决方案1】:

    您的 Capistrano 脚本中有类似“独角兽开始”的内容,对吧?在调用该命令后立即让您的 Capistrano 脚本 ping Unicorn。如果 Unicorn 在超时内没有返回预期的响应,那么您就知道出了问题,您可以选择回滚部署或执行其他操作。

    至于如何 ping Unicorn,这取决于。如果你有 Unicorn 监听 TCP 套接字,那么你可以使用 curl。如果你有 Unicorn 监听 Unix 域套接字,那么你必须编写一个连接到它的小脚本,如下所示:

    require 'socket'
    sock = UNIXSocket.new('/path-to-unicorn.sock')
    sock.write("HEAD / HTTP/1.0\r\n")
    sock.write("Host: www.foo.com\r\n")
    sock.write("Connection: close\r\n")
    sock.write("\r\n")
    if sock.read !~ /something/
      exit 1
    end
    

    但听起来Phusion Passenger Enterprise 很好地解决了您的问题。它具有称为“抗部署错误”的特性。当您部署新版本并且 Phusion Passenger 检测到它无法为您的新代码库生成任何进程时,它将停止尝试生成您的新版本并无限期地保留旧版本的进程,直到您手动给出可以的信号为新版本生成进程。同时它会将所有错误记录到日志文件中,以便您分析问题。

    【讨论】:

    • 自动化“ping & kill”是一个很好的解决方案,可能monit 也可以做到。
    【解决方案2】:

    我建议你放弃你的 bash 技能。您需要的功能已经在 Unicorn 中,因为它利用了 Unix-y master/worker 进程。

    您需要一个 init.d 脚本。或者至少是 godrb 或 monit。我推荐 init.d 脚本路由和监控。它更复杂,但您的监控软件可以更轻松地利用它,并且还可以在重新启动时自动启动。

    它的要点是:

    1. 向独角兽主进程发送USR2信号,这将分叉主进程。
    2. 然后将 WINCH 发送到创建的旧主进程,这将杀死每个工作人员。
    3. 然后您可以向旧主进程发送 QUIT 信号。

    Unicorn Signals

    这将启动一个新的主进程运行新代码并将旧的标记为(旧)。如果它失败了,旧的应该返回到它以前的状态,你不应该遭受中断,只是一个重新启动错误。这就是独角兽的美丽。您几乎可以获得代码的即时部署。

    我使用了很多对冲词,因为一年多前我在我的应用上做过这项工作,所以楼上有很多蜘蛛网。希望这会有所帮助!

    这绝不是一个正确脚本。不过,这是一个很好的起点……如果您可以改进它,请随时更新要点! :-)

    Example Unicorn Control Script

    【讨论】:

    • 非常感谢您的回答。我正在使用独角兽示例中的 init.d 脚本。我的主要问题是:If it fails the old one should be returned to its prior state 如何检测新主人的工人正在失败,当它试图一次又一次地重生它们时?现在我认为独角兽内部没有解决方案,因为它的功能是重新创建失败的工人。它不能区分为继续提供服务而需要更换的偶然失败的工作人员,以及由于应用程序中的错误而无法启动的工作人员。
    • 或者你建议用monit来做?
    • IIRC 新主进程将死去,旧主进程将返回为主进程。所以你会在重启后看到独角兽主机上的 PID 没有变化,我也认为它会写入 STDERR。如果您的工人有竞争条件,那么 unicorn master 应该无法启动。或者,如果它确实开始了,您会看到竞争条件的迹象。对于这种竞争条件,我通常看到的警告信号是独角兽开始消耗大量 CPU 百分比。这部分可以通过监控来捕捉。 Godrb 相当容易上手,因此您可能希望从那里开始并设置 CPU 限制。 :-)
    • 还要确保你在你的独角兽配置文件​​中设置了日志路径。这样您就可以在错误发生时看到它们。
    • 您似乎在谈论不同的用例。如果你有一个错误的 Rails 应用程序是初始化程序,主程序不会死,因为它没有加载应用程序。它将产生一个工人,工人将启动一个应用程序,然后失败,主人将产生新的工人,依此类推,直到我手动杀死它。是的,我确实查看了日志和 CPU 负载,正如我所说的问题,但是厌倦了手动检查,所以监控可能是解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-04
    • 2016-08-01
    • 1970-01-01
    • 2015-12-01
    • 2018-08-24
    相关资源
    最近更新 更多