【问题标题】:Does foreman restart processes gracefully?工头是否优雅地重新启动流程?
【发布时间】:2013-08-10 08:00:27
【问题描述】:

我即将在生产中使用 foreman 和 upstart export 来启动一些无限的 rake 任务。

我不起眼的“守护进程”就这么简单:

task magic: :environment do
  loop do
    make_stuff_happen

    sleep 10
  end
end

我想知道工头在被要求重新启动时是否不只是杀死进程(例如 capistrano 部署),因为我不希望因此发生任何损坏的操作。

如果是的话如何预防?

【问题讨论】:

    标签: ruby-on-rails capistrano foreman


    【解决方案1】:

    如果您进行导出,您可能在配置上有一个文件,例如 app-jekyll-1.conf 其中包含类似这样的内容

    start on starting app-jekyll                                                                                               
    stop on stopping app-jekyll
    respawn
    
    exec su - username -c 'cd /some/directory; export PORT=5000; bundle exec jekyll serve -w >> /tmp/a    pp.log/jekyll-1.log 2>&1'
    

    这基本上是ubuntu新贵的配置。

    现在当你用 upstart 重启服务时,它实际上会调用initctl restart

    http://upstart.ubuntu.com/cookbook/#restart

    调用initctl restart 将向作业发送 SIGTERM 信号

    https://serverfault.com/questions/189780/what-signal-does-upstart-initctl-use-to-restart-a-job

    现在清理资源取决于您的程序在收到 SIGTERM 信号时是否进行清理。

    当您要求重新启动时,工头是否会杀死 rake 进程的问题,然后 答案是是的,它将通过向 rake 进程发送 SIGTERM 来终止进程。

    rake默认收到SIGTEM后退出进程。

    例如,如果这是你的 Rakefile

    def do_some_magic
      puts "doing some magic.."
      sleep 5
    end
    
    task :magic do
      puts "Running the task wit PID #{$$}"
      loop do
        do_some_magic
    
        sleep 5
      end
    end
    

    然后如果你运行它

    $ rake magic
    Running the task wit PID 29527
    doing some magic..
    

    Separate 终端上,您可以使用给定的 PID 向 rake 进程发送 SIGTERM。它会抛出异常

    $ kill 29527
    

    在之前的终端上你会得到

    ...                         
    doing some magic..                                            
    rake aborted!                                                 
    SIGTERM                                                       
    /tmp/foo/Rakefile:11:in `sleep'                               
    /tmp/foo/Rakefile:11:in `block (2 levels) in <top (required)>'
    /tmp/foo/Rakefile:8:in `loop'                                 
    /tmp/foo/Rakefile:8:in `block in <top (required)>'            
    Tasks: TOP => magic                                           
    (See full trace by running task with --trace)
    

    所以这基本上是 rake 死了。它会立即停止一切。例如,如果do_some_magic 当前正在执行 DB 操作,您可能会留下不一致的状态。

    您当然可以处理这个信号来执行一些清理工作。 如果您想等到do_some_magic 完成,这就是您可以处理的方法

    def do_some_magic                          
      puts "doing some magic.."                
      sleep 5                                  
    end                                        
    
    task :magic do                             
      puts "Running the task wit PID #{$$}"    
      loop do                                  
        do_some_magic                          
    
        if $shutdown                           
          puts "shutting down..., exiting loop"
          break                                
        end                                    
      end                                      
    end                                        
    
    trap "TERM" do                             
      puts "SIG TERM received."                
      $shutdown = true                         
    end                                        
    

    然后再次运行它..

    $ rake magic
    Running the task wit PID 30150                     
    doing some magic..                                 
    

    在分离器终端上,您再次使用 pid 终止进程

    $ kill 30150
    

    在你以前的终端上,过程将是这样的

    ....
    doing some magic..             
    SIG TERM received.             
    shutting down..., exiting loop 
    

    结论

    • foreman export 只会创建一个 ubuntu upstart 脚本。
    • 重启机制将由操作系统处理。将 SIGTERM 发送到进程。
    • 它依赖于实际进程来维护系统的状态。
    • 默认情况下,Rake 不处理 SIGTERM。你必须自己做以确保任务是否被中断,你要进行清理以确保系统状态没有损坏

    希望对你有帮助

    【讨论】:

    • 非常感谢您提供的信息!但我不确定如何在生产 rake 任务中正确捕获和响应信号
    • 我最近对这个问题进行了更多的思考。我想这应该可以解决你的问题
    猜你喜欢
    • 1970-01-01
    • 2012-04-03
    • 1970-01-01
    • 2018-08-18
    • 2013-12-13
    • 1970-01-01
    • 2017-01-20
    • 1970-01-01
    • 2011-12-27
    相关资源
    最近更新 更多