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 程序员
先上结论
- 我解决不了 CPU 占用 100% 的问题
(在机器1(测试环境)上可以,但是机器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),因为已经有用户在用了,所以在(机器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。
如此来回交替。
这篇文章写得有点仓促因为只是赶紧写完然后继续干活。如果有错字或哪里希望补充更多信息,请联系 guokrfans@gmail.com
全文完。感谢阅读。