RabbitMQ队列slave进程内存飙高

问题

最近线上出现了一起消费重试导致集群节点内存飙高,生产者消息发送失败。
现象:集群中一个队列的slave进程疯狂占用内存,master进程内存正常

RMQ如何实现消费重试

实现重试、延时消费的关键

Dead-Lettered Messages(死信消息)主要来源于:

rejected - the message was rejected with requeue=false
expired - the TTL of the message expired

Dead Letter Exchanges(死信转发的Exchange)
Dead Letter Routing Key(死信转发的Routing Key)

消息被发到一个中转队列(#retry 或者 #delay),然后经过TTL后, 消息被死信Exchange路由到目标队列中,从而达到重试或延时消费的效果。

消费重试

分析

  1. 服务消费异常,大量消息进入重试队列(retry#1 retry#2 retry#3)
  2. 由于重试利用上述的消息 TTL 机制,然后通过死信转发到原队列。三个Level的重试消息 TTL 后打入原队列,由于 QPS 较高,大量消息消费失败进行重试的极端情况下,原队列需要多承受上面3倍的流量。而 RMQ 队列实现本身是一个 Erlang 进程,QPS 过高,队列进程可能来不及处理。

为什么队列slave进程内存飙高,master进程正常

初步猜测

retry队列中的消息经过TTL后,被内部死信转发到原始队列(队列master、slaves进程都会收到)。slaves 进程收到消息后,会缓存在内存中。正常情况下
master 进程通过 gm 把消息通过环状链表广播到 slaves 进程。当 master 对应的 gm 进程再次收到其广播的消息时,会再次广播 ack 消息,其作用是通知 slaves 进程可以清除缓存的消息。

由于线上采用惰性队列,队列进程收到消息会尽可能早地进行持久化到磁盘(通过 rabbit_msg_store 进程),而当内部重试流量叠加导致大量消息打到队列,rabbit_msg_store 持久化进程可能处理不过来,造成队列进程阻塞。因此 master 进程内存没有出现飙高现象,而 slaves 进程收到消息先进行缓存,等待 master 进程广播 ack 消息后才能进行清除。但由于 master 进程可能被阻塞,而内部重试过来的流量(没有credit_flow)连续发往 slaves 进程,导致 slaves 进程一直在缓存发往它的消息,造成其进程内存继续飙高。

为什么会影响生产者发送消息

channel 进程向队列进程发消息一般采用了credit_flow机制

case Flow of
        %% Here we are tracking messages sent by the rabbit_channel
        %% process. We are accessing the rabbit_channel process
        %% dictionary.
        flow   -> [credit_flow:send(QPid) || QPid <- QPids],
                  [credit_flow:send(QPid) || QPid <- SPids];
        noflow -> ok
    end,

由于内部重试流量叠加,队列进程来不及处理,会很快耗尽 rabbit_channel 进程的 credit 值,造成 rabbit_channel 进程被限流阻塞;同理限流过程会往rabbit_channel进程上游传播,进而阻塞rabbit_reader进程,从而导致服务端读取 socket 消息变慢,导致接收缓冲区不足,与线上监控的TcpExt.pruneCalled指标告警一致。这样导致了生产者发送消息异常。

解决方法

  1. 启动远程Shell
erl -name sj@test -setcookie  $COOKIE

  1. 打印节点 N 占用内存 Top 5 进程列表
rpc:call(N, erlang, apply, [fun()->lists:sublist(lists:reverse(lists:keysort(2, [{P, process_info(P, memory)} || P <- processes()])), 5) end, []]).

结合 rabbitmq_top 插件 Top Processes 进程列表,确认问题进程后,接下来进行 Kill 操作。

  1. Kill异常slave进程
exit(pid(x1,x2,x3),kill).

推荐阅读

进程pid构成
镜像队列

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269