限制 unicorns 的数量、内存使用和交换

我运行着一个小型服务器(1G 内存)和一个小型网站(官方 Discourse 安装,已运行近 8 年)。我发现内存交换比我期望的要多,所以我开始查看内存使用情况。

我注意到我之前将 unicorn 的数量设置为 2,以限制内存使用(并减少交换)。运行的 Discourse 版本是 3.1.0

然而,当我运行 htop 时,我看到有 20 个 unicorn 正在运行(worker 0 有 10 个,worker 1 有 10 个)。

我这里有什么遗漏的吗?为什么会有 20 个 unicorn 在运行,而 app.yml 中却写着 2 个?

另外,还有其他方法可以减少内存使用吗(例如,如果我将 db_shared_buffers 减少到 128MB 会有什么副作用?)?我能减少 sidekiq 的内存使用吗?

这是 vmstat 5 5 的输出:
image

这是 free -h 的输出:
image

1 个赞

我怀疑 htop 显示的是线程而不是进程——无论如何,我在 htop 上看到和你一样的东西,但根据

ps uaxf|egrep unicorn.?worker

只有两个 unicorn。

另外,我的 free 和你的一样:

# free -h
              total        used        free      shared  buff/cache   available
Mem:           985M        782M         61M         60M        141M         32M
Swap:          2.0G        992M        1.0G

顺便说一句,看到一些交换(swap)在使用本身并不是问题。真正的问题是实际的交换(paging)。尝试 vmstat 5 5 并查看 si 和 so 列。

# vmstat 5 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0 1041832  63176   5716 127408  367  325   601   393    8   10  2  1 95  2  0
 0  0 1041576  60976   5724 127408  399    0   399    21  212  653  1  1 96  2  0
 0  0 1043544  77036   2296 120688  807  803   807   837  404 1144  1  2 94  3  0
 0  0 1043288  65040   3704 129476  254    0  2292     5  255  780  1  1 96  2  0
 0  0 1048736  81936   2916 119016  762 1499   919  1565  470 1171  3  2 90  5  0

我希望不要看到任何超过 1000 的值,但我并不太担心。第二次运行显示的情况要平静得多:

# vmstat 5 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0 1048452  82712   2532 120848  367  325   601   393    8   10  2  1 95  2  0
 0  0 1047684  74552   2548 124816  285    0  1049    10  230  655  2  1 95  2  0
 0  0 1046660  66556   3692 129008  196    0  1261    16  219  672  1  1 96  2  0
 1  0 1046404  65812   3700 129284   54    0    97    13  137  364  1  0 98  0  0
 0  0 1046148  65280   3700 129288   50    0    50     3  132  344  1  0 98  0  0

编辑:htop 中的 H 键将在线程和进程之间切换:

  CPU[                                                       0.0%]   Tasks: 66; 1 running
  Mem[||||||||||||||||||||||||||||||||||||||||||||||||||824M/985M]   Load average: 0.19 0.12 0.05
  Swp[||||||||||||||||||||||||||||||                  1015M/2.00G]   Uptime: 52 days, 00:50:42

  PID USER      PRI  NI  VIRT   RES   SHR S CPU% MEM%   TIME+  Command
13246 1000       20   0  966M  362M  6448 S  0.0 36.8 51:01.52 unicorn worker[0] -E production -c config/unicorn.conf.rb
13237 1000       25   5 1004M  194M  3780 S  0.0 19.8 22:38.19 sidekiq 6.5.9 discourse [0 of 5 busy]
13258 1000       20   0  919M 70176  3632 S  0.0  7.0  5:02.87 unicorn worker[1] -E production -c config/unicorn.conf.rb
12412 systemd-r  20   0  212M 60928 56916 S  0.0  6.0  0:00.23 postgres: 13/main: discourse discourse [local] idle
12818 systemd-r  20   0  212M 39228 34868 S  0.0  3.9  0:00.07 postgres: 13/main: discourse discourse [local] idle
12719 systemd-r  20   0  211M 28400 25336 S  0.0  2.8  0:00.03 postgres: 13/main: discourse discourse [local] idle
13117 1000       20   0  541M 13768  2048 S  0.0  1.4  1:08.11 unicorn master -E production -c config/unicorn.conf.rb

编辑:我早就设置了 db_shared_buffers: "128MB",并且没有遇到任何问题。

1 个赞

谢谢,非常有帮助。将工作进程迁移到单个 Unicorn 工作进程有什么缺点?这会改善响应时间还是会使其变差(一个 Unicorn 工作进程是否仅限于一个传入连接,即 2 个工作进程是否会使单个传入连接的处理速度更快?),假设我每分钟只有几个连接?

当我浏览网站时,vmstat 5 5 的输出如下,有什么建议可以减少交换(我已经将 swappiness 设置为 10)?

编辑:有什么方法可以在不影响性能的情况下减少 Sidekiq 的内存使用量?

如果您的网站有更多的内存,它肯定会运行得更快。但如果响应时间不是问题,那就没有问题。只需考虑您的个人成本/效益方程式。

您可能对阅读 MKJ 的主观 Discourse 部署配置 感兴趣。有一些系统级别的内核调整是不错的选择。我不知道它们是否会有所不同。

我不知道,但我认为每个 unicorn 可以处理一个请求。所以,如果您只有一个 unicorn,并且在第一个请求完成之前有足够的流量来处理第二个请求,那么第二个请求将不得不等待。您可以从我的 htop 输出中看到,一个 unicorn 的 CPU 时间是另一个的 10 倍。我认为这意味着我的论坛 90% 的时间只需要一个 unicorn,而 10% 的时间第二个 unicorn 会有所帮助。我感觉没有必要添加第三个,如果减少到一个,我的论坛成员可能也不会觉得有什么大不了的。但我也没理由这样做:它可能会占用内存,但如果它处于空闲状态,它将被交换出去。没关系:让虚拟内存系统处理它。

编辑:我从未调整过 swappiness。它似乎是 60。更积极的交换可能有助于为 I/O 缓冲区释放更多内存。我不知道。

2 个赞

如果我更改 db_shared_buffersUNICORN_WORKERS,是否有一种方法可以仅重新启动而不通过 ./launcher rebuild app 进行重建?