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

jicheng1014 · 2021年08月26日 · 266 次阅读

今天有小伙伴又在问 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
需要 登录 后方可回复, 如果你还没有账号请 注册新账号