2018-8-3 解决 puma 重启时 CPU 占用 100% 问题

结论:用 nginx load banlancer 来切换指向。服务器上跑2个 puma。

2018-8-3 解决 puma 重启时 CPU 占用 100% 
 问题

这篇文章是什么

解决 Ruby on Rails 5.2.0,Puma 服务器(版本 3.11) phased-restart 时重启会占用 100% CPU 持续很长时间(4-10分钟)才重启成功的问题。
(Ruby 版本 2.4.1) (Ubuntu 16.04)

解决这个问题是为了什么

为了部署新代码上线时,部署期间网站不会挂掉。
因为一天会部署很多次新版本,每次都中断一分钟以上是无法接受的。

本文适合谁看

遇到同样问题的 Ruby on Rails 程序员

先上结论

  1. 我解决不了 CPU 占用 100% 的问题
    (在机器1(测试环境)上可以,但是机器2(生产环境)上不行,详情请看"具体过程")
  2. 最后解决方案:用 nginx 的 load banlancer。
    做法是服务器上跑 2 个 puma。一个在 9292 端口,一个在 9696 端口。
    nginx 只指向其中一个(比如9292)。需要更新时就更新另一个(9696),
    更新完毕后然后让 nginx 指向另一个(9696)。如此交替。
upstream app_witt {
  # server 127.0.0.1:9292;
  server 127.0.0.1:9696;
}

具体过程(有点长)

0. 先讲背景

服务器用的是 UCloud。有两台服务器(2个UCloud 账号各自一台服务器)
配置是 CPU 2核 + 内存4G。
写这个只是为了提供更多信息,不是说 UCloud 有问题。完全不是 UCloud 的锅。

为了方便,两台机器在下文统一叫“机器1”和“机器2”

  • "机器1":只放了2个个人项目(yuzhu.meCC 速成班
  • "机器2":是线上的生产环境(网站地址就不放了)

1. 为了解决这个问题做了什么尝试

做这个实验不能到线上生产环境上弄(机器2),因为已经有用户在用了,所以在(机器1)上测试。
(机器1)上一切正常,
mina deploy --verbose 部署成功后就运行 mina puma:phased_restart
(我用了mina-puma gem 所以有这个 mina task 可以跑)

大概等3-5秒就可以了。期间 CPU 最多涨到 60%~80%, 或者不足1秒的100%(用htop命令看的)
一切非常正常,完美。

但是(机器2)生产环境上就不行。
tail -f puma.stderr.log 也没有什么有用的信息。
一开始我以为是编码错误,因为之前在(机器1)(非生产环境)上解决过:
Unable to load application: ArgumentError: invalid byte sequence in US-ASCII
当时运行 puma 会在 puma.stderr.log 里大量输出这个 log 刷屏,然后占用 100% CPU。

解决方法是在 ~/.profile 里面写入

export LANGUAGE=en_US.UTF-8
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8

解决编码问题即可。(用 vim 或者 nano 来编辑文件)

我另一篇文章里写了具体情况,这里就不重复细节了。

总之,我花了整整1天时间(2018-8-3)试图定位问题。
在谷歌上搜,在 Github 上找类似问题,看官方文档,看官方 issue,去 issue 提问。
看环境变量是否有差异。
想解决机器1上 puma 做 phased-restart 会占用 100% CPU 的问题。
就是解决不了。无法具体定位到问题是什么,看 log 也看不到有帮助的信息。

决定不再浪费时间处理这类奇葩问题了。
这类问题就是时间黑洞,不知道多久能解决。

最后

最后决定用 nginx 的 load banlancer 来解决问题。

具体解决方法:
服务器上跑两个 puma(假设叫 A 和 B),nginx 指向其中 A。
需要更新的时候,先更新另一个(B)。然后让 nginx 指向 B。
如此来回交替。

这篇文章写得有点仓促因为只是赶紧写完然后继续干活。如果有错字或哪里希望补充更多信息,请联系 [email protected]

全文完。感谢阅读。