Rails 如何 0 downtime 重启? puma 的重启方式讲解

jicheng1014 · August 26, 2021 · 679 hits

今天有小伙伴又在问 puma 在部署时候的重启方式,怎样做到 0 downtime,我这刚好整理了一篇笔记 分享给大家

参考文章

puma/restart.md at master · puma/puma puma 关于 systemd 的 0down 方案

puma 的重启种类

  • Normal Restart
  • Hot Restart
  • Phased-Restart to rescue

Normal Restart

就是完全正常的重启

优势

完全的生命周期,跟 stop 之后 start 一样,所有的东西都会重新加载

劣势

服务中断,会有 503 Service Unavailable 的情况

Hot Restart

通过额外的 Server socket,确保 puma 在重启的过程中,可以持续的接受请求,并等待处理,puma 重启成功之后,将 socket 堆积的请求再发送出去

优势

不会终止服务,请求连接也会得到保留。cluster 模式 和 simple 模式均可以使用,个人认为比较简单

使用 preload_app!可以加快启动速度

啥是 preload_app! 在 cluster 模式下 preload_app! 实现 将 master 进程的所有代码 在 fork 之前都 load 起来,这样就可以使用操作系统的 copy-on-write 技术,有效的降低内存使用。

劣势

在重启期间,进来的连接处于挂起状态 hanging, 如果时间过长,则上层如 nginx 会来个 502

启动方式

满足任意条件即可启动

  • 给 puma 进程发送 SIGUSR2 信号 即 kill -SIGUSR2 进程号
  • 向 puma status/control server 请求 /restart

    什么是 puma status/control server? 在 puma 启动的时候 可以带入参数来启动一个控制 url 类似 puma --control-url tcp://127.0.0.1:9293 --control-token foo

  • pumactl restart

Phased restart

Phased restart 名为 阶段重启,这种重启方式只适合跑在 cluster 模式下。工作机制是 : 先杀死一个老版本的 worker,再启动一个新的 worker,以此重复,直至所有的 worker 都是新版本,这种方式 master process 即 puma 的控制进程本身,是不会重启的,重启的只有 worker 进程。这种方式不适合配置有更新,以及添加新 Gem 的情况

优势

在 puma 重启过程中,系统也是可以真正的处理请求,即 既接受了新的请求进来,请求进来后也会有 worker 来处理并返回结果(但是 是新是旧 worker 是随机的)

劣势

  • 只支持 puma 的 cluster 模式
  • 因为 puma 的 master process 没有重启,所以 gem 以及配置文件的更新(puma 的配置文件)是不行的,且 puma 的事件 on_restart 也是不会产生的
  • puma.rb 配置文件,是禁止使用 preload_app! 而需要使用 prune_bundler 的

    为啥不能用 preload_app! ?因为主进程不重启,只是单启 worker

    prune_bundler 代替了 preload, 来进行 gem 的装载

启动方式

  • kill -SIGUSR1 主进程
  • 向 puma status/control server 请求 /phased-restart
  • pumactl restart
You need to Sign in before reply, if you don't have an account, please Sign up first.