2024年注:这篇博文实际上是一个反例。查问题不应该像这样查个似是而非就认为大功告成了。印象里这篇文章发出后不久,RMQ 又 OOM 了。

按今天的眼光来看,这篇文章至少有这些槽点:

  1. 为什么 Redis 的带宽使用高企?替换 RMQ 从理论上能解决 Redis 作为 Broker 时带宽高的问题吗?
  2. 有证据能证明是 Socket Buffer 导致的内存使用量过高吗?
  3. 线上冒烟测试

还好当年做掌上武大的时候对崩溃的宽容度比较高,不然有够被喷的。把这篇文章放在这里谨以纪念在自强Studio的时光,文章的内容就别参考了。

刚刚接手自强Studio的后台开发,碰到了Redis做Celery的broker时大量占用Redis服务器宽带资源的问题。面对有限的经费,我决定把和Celery搭档的做Broker的Redis更换为RabbitMQ。

刚切换到RabbitMQ以后,流量是有显著下降,但是却发现了一个奇怪的问题:服务器内存资源占用总是从50%在两三天的时间内飙升至80%,之后服务器内存调度缓慢,几乎处于宕机的状态。

起先怀疑是服务器配置不足(服务器只有1G内存),然而在咨询了@liby、@iceboy和@twd2等大神以后,得知RabbitMQ在1G的内存下跑完全可行。

在百度和必应上搜索无果。搜到的大多是关于vm_memory_high_watermark的内容。修改后无效。之后细致的分析了RabbitMQ的内存,发现高涨的是binary部分。遂修改关键词,重新选择合适的搜索引擎,搜到了这篇文章

解决方法就是,在RabbitMQ配置文件 rabbitmq.config中修改 tcp_listen_options中有关Socket Buffer的配置。该问题提供的参数如下:

[{rabbit, [{tcp_listen_options, [binary,
                                  {sndbuf,        1024},
                                  {recbuf,        1024},
                                  {buffer,        1024},
                                  {packet,        raw},
                                  {reuseaddr,     true},
                                  {backlog,       128},
                                  {nodelay,       true},
                                  {linger,        {true, 0}},
                                  {exit_on_close, false}]}]}].

未强制指定时,系统会自动指定Buffer的大小(想想一堆数据全部丢进去,着实可怕)。具体的体现就是Binary内存使用高涨。RabbitMQ的文档里没有详尽介绍这个参数,然而这个参数尽然会带来这么大的内存使用差!

修改此参数后,RabbitMQ已正常运行一个多星期。