Rails Nginx + Unicorn 部署重启的性能问题

kafka0102 · 2016年04月17日 · 最后由 kafka0102 回复于 2016年05月12日 · 3568 次阅读

配置是 8G 内存 +2 核 CPU 的云主机,12 个 nginx 进程,unicorn 的 worker 是 20 个。

发布新版本时先

rake RAILS_ENV=production RAILS_GROUPS=assets assets:precompile

然后 rake stop 大概需要 10 几秒钟,之后 rake start 又是 10 几秒。

问题似乎在并发多时(低峰期也有每秒 10 多个请求),rake start 后 cpu 就满了,看 rails log 是有处理请求的,但 nginx 基本就是 499 和 502 之类的响应。

尝试的解决方法是,kill 掉 nginx 进程,重新 start unicorn 再 start nginx 后恢复正常了。而且,看 rails log 有时会有 missing views 文件的信息(这个很让人费解,因为文件是存在的)。如果部署时并发不多就不会出现这种问题。个人猜测,因为请求比较多,unicorn 启动后 20 个 worker 进程同时处理请求,但因为加载 rails 环境什么的都在占用资源,结果是很多 worker 都没有起来(log 里有 killed 的日志)。我在想,配置再升级到 4 核 CPU 是否能好些?但平时 CPU 利用率只是 30% 左右的。现在每次部署都很闹心啊,该如何能只几十秒停服务的部署啊?

这一大段的... 就不能换行么!

首先你的部署有问题,Unicorn 官方的建议是多少个 CPU 核部署多少个进程 + 1,你的机器 2 核,合理的数量应该是 3 - 4 个 worker。

Nginx 的 worker 也是一样的概念

本来 Rails 第一次启动的时候就是挺慢的,这个很正常,它需要预加载 N 多的库,计算 Assets 的 Digest 信息等。

此外 Unicorn 重启的机制是 Copy 一份新的进程列表出来,你 20 个,它重启的时候会变成 40 个,内存随着也增加了,如果你内存不足,那重启的过程必然缓慢,Unicorn 一直到新的 20 个进程完全启动成功以后,才会杀掉 Old 的 20 个进程。

以楼主的场景来看,我认为问题就在于 worker 太多了,重启的时候内存不够用,所以启动缓慢。

解决方案:

  1. 换机器,成 4 核 4 G 或更大;
  2. 合理设定 Unicorn Worker 数量;
  3. 合理设定 Nginx worker 数量;

2 核 CPU,woker20 个,nginx 和 unicorn 的 woker 数都是和 cpu 数直接相关的,核心数 + 1 就行了,多了多占用内存也调度不到,https://www.digitalocean.com/community/tutorials/how-to-optimize-unicorn-workers-in-a-ruby-on-rails-app ,用 unicorn 的话最好也加上 unicorn-worker-killer 这个 gem,控制每个 worker 的内存占用。

#3 楼 @huacnlee #4 楼 @zhang_soledad

多谢回复。 内存是够用的,每个 worker 是占了 200M 左右的内存。之前是 12 个 woker,4G 的内存,后来内存升级了。worker 加多也是不得已的事情,因为像搜索等请求耗时就是长,统计到每天是有不少响应时间超过 1 秒的请求,然而又不好优化。后续会尝试加 CPU 看看效果。

6 楼 已删除

nginx 进程过多了,试试 2 个

以前遇到过 worker 过多导致 load 极高的情况,worker 不是越多越好,nginx 如果参数优化好本身没问题的,瓶颈在于硬件和后端的软件。

#10 楼 @netqyq worker 数量平时运行是没问题的,现在就是部署时启动太慢,打算周末稍微减少下 worker 数量,再提高下 cpu 看下效果。也打算测试下 puma。因为下午高峰期并发有些多时,之前 worker 少时 nginx log 里不少请求响应时间有些长。那个 nginx worker 数量确实没必要那么多,瓶颈不在那里。

nginx 这么多 workers 一般就是和内核数量相同

#12 楼 @zouyu nginx 的 workers 因为历史原因没改(后来改掉了),主要还是 rails 的 worker 数太多。现在换成 4 核的 CPU 后,重启顺爽多了。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号