偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Topic太多!RocketMQ炸了!

開發(fā) 架構
我們的RocketMQ集群為4.6.0版本,按照3個Nameserver,2個broker,每個Broker為主從雙節(jié)點部署。

網(wǎng)上博客常說,kafka的topic數(shù)量過多會影響kafka,而RocketMQ不會受到topic數(shù)量影響。

但是,果真如此嗎?

最近排查一個問題,發(fā)現(xiàn)RocketMQ穩(wěn)定性同樣受到topic數(shù)量影響?。?/p>

好了,一起來回顧下這次問題排查吧,最佳實踐和引申思考放在最后,千萬不要錯過。

1、問題描述

我們的RocketMQ集群為4.6.0版本,按照3個nameserver,2個broker,每個broker為主從雙節(jié)點部署。

圖片

部署架構

某天收到警報,broker-b突然從nameserver掉線,且主從雙節(jié)點都無法重新注冊。

2、初步排查

(1)檢查進程存活&網(wǎng)絡

因為控制臺上顯示broker-a正常,因此可以認為 nameserver、broker-a都是正常的,問題出在broker-b上。

當時第一反應是broker-b進程掛了,或者網(wǎng)絡不通了。

登陸broker節(jié)點,看到進程依然存活。

然后通過telnet檢查和nameserver的聯(lián)通性,顯示正常,網(wǎng)絡沒有問題。

(2)檢查日志

檢查broker日志,馬上發(fā)現(xiàn)了異常。

2023-01-09 14:07:37 WARN brokerOutApi_thread_3 - registerBroker Exception, mqnameserver3:xxxx
org.apache.rocketmq.remoting.exception.RemotingSendRequestException: send request to <qnameserver3/xx.xx.xx.xxx:xxxx> failed
at org.apache.rocketmq.remoting.netty.NettyRemotingAbstract.invokeSyncImpl(NettyRemotingAbstract.java:429) ~[rocketmq-remoting-4.6.0.jar:4.6.0]
at org.apache.rocketmq.remoting.netty.NettyRemotingClient.invokeSync(NettyRemotingClient.java:373)
......

異常比較明確,broker請求nameserver失敗,所以導致無法注冊到集群中。

那為什么會注冊失敗呢?沒有非常明確的提示,因此去看下nameserver上的日志信息。

2023-01-09 14:09:26 ERROR NettyServerCodecThread_1 - decode exception, xx.xxx.xx.xxx:40093
io.netty.handler.codec.TooLongFrameException: Adjusted frame length exceeds 16777216: 16777295 - discarded
at io.netty.handler.codec.LengthFieldBasedFrameDecoder.fail(LengthFieldBasedFrameDecoder.java:499) [netty-all-4.0.42.Final.jar:4.0.42.Final]
......

這個異常看起來是nameserver上的netty拋出的,請求過大拋出了異常。

根據(jù)日志關鍵字,直接定位到了源碼,確實有默認的大小限制,并且可以通過com.rocketmq.remoting.frameMaxLength進行控制。

(3)源碼分析

雖然找到了異常的直接原因,但是為什么broker突然會有這么大的請求?是什么帶來的?

從broker的warning日志中,并沒有辦法看到更多有效信息。

因此,還是得深入分析下broker上的源碼。根據(jù)日志關鍵字,很快找到broker中的異常位置

圖片

broker異常位置

注意!這里通過遍歷nameserverlist,在線程池中異步注冊,跟后面的一個小知識點有關。

從源碼中可以分析出,如果有過大的請求的話,應該就是這個requestBody引起,它攜帶了大量topic信息topicConfigWrapper。

但是我們在控制臺上看到當前集群中,只有300+topic(這里其實是一個誤區(qū),最后會解釋),理論上來說是非常小的,為什么會超出容量限制呢?

看了下源碼上下文,并沒有對reqeustBody或者topicConfigWrapper有相關日志的記錄,因此,還是需要arthas來看看了。

(4)arthas定位

直接通過arthas定位實際內(nèi)存值。

watch org.apache.rocketmq.broker.out.BrokerOuterAPI registerBrokerAll {params,returnObj} -x 3

查看結(jié)果:

圖片

內(nèi)存中實際topic數(shù)量

啥玩意?!

topicConfigTable的map大小為size=71111??。?/p>

進一步看看這些topic里面都是些啥?我們調(diào)整下arthas的參數(shù)-x為4,改變watch變量的深度。

圖片

內(nèi)存中相關topic名稱

發(fā)現(xiàn)問題了!

我們看到了大量%RETRY%開頭的topic。

3、根本原因

至此,根本原因就能明確了。

RETRY topic過多,導致 broker 向 nameserver 發(fā)送心跳(定時發(fā)送注冊請求)時,心跳請求中攜帶的 body 上的 topic 信息過大,超過了 nameserver 上使用的 NettyDecoder.java 限制的 16M (默認值),心跳請求失敗,所以broker掉線。

4、恢復

既然問題基本確定了,那么先嘗試恢復吧。

前面已經(jīng)看到了對最大請求體的配置,因此,我們在bin/runserver.sh中添加一個JAVA_OPTION對com.rocketmq.remoting.frameMaxLength進行配置。然后重啟nameserver。

重新觀察broker,果然重啟成功了。

2023-01-09 16:03:55 INFO brokerOutApi_thread_3 - register broker[0]to name server mqnameserver4:9876 OK
2023-01-09 16:03:55 INFO brokerOutApi_thread_4 - register broker[0]to name server mqnameserver2:9876 OK

當然,這只是臨時恢復措施,后面重點要思考以下問題并進行優(yōu)化:

  • RETRY topic數(shù)量這么多是否正常?是否可以清理無效topic?
  • 如何做好后續(xù)的topic數(shù)量監(jiān)控告警?

5、最佳實踐

(1)定時刪除無效RETRY topic

考慮使用定時任務掃描所有業(yè)務topic下的消費組,再根據(jù)消費組狀態(tài)(狀態(tài)為not_online的消費組),拼出對應RETRY topic進行刪除。以上步驟均有開源MQ sdk 的 api 可以調(diào)用。

即使后續(xù)消費組重新使用,RETRY topic 也會重新創(chuàng)建,不影響消費。

(2)topic總數(shù)監(jiān)控

前面說到在控制臺上看到當前集群中只有300+topic,這里其實是一個誤區(qū),只勾選了NORMAL類型的topic,并沒有注意RETRY、DLQ、SYSTEM類型的topic。

圖片

控制臺誤區(qū)

而這次幾萬個topic基本都是RETRY類型的。

后續(xù)需要添加topic數(shù)量監(jiān)控(包括RETRY類型),防止由于topic數(shù)量過多,導致broker注冊失敗。

6、引申思考

(1)RETRY topic是什么?為什么有這么多?

這需要從RocketMQ的重試機制與死信機制說起。

RocketMQ 提供了自帶的重試機制,消息消費失敗或超時,會被投遞到 RETRY topic。RETRY topic 里的消息會按照延時隊列的延時時間進行消費,這樣也避免了有問題的消息阻塞正常消費。

RETRY topic 里保存的是消費狀態(tài)為 consumer_later 的消息,在重試達到 16 次(默認值)以后,消息會進入死信隊列(本質(zhì)上也是一個新的topic類型,DLS topic)。

DLQ topic在使用時才會創(chuàng)建,因此不會像RETRY topic 這樣大量膨脹。

但是,RETRY topic不一樣。它是由RocketMQ服務端自動創(chuàng)建,創(chuàng)建的時機有兩個:

  • 消費失敗的時候,將消息發(fā)送回 broker,這時候會在服務端創(chuàng)建RETRY topic。

圖片

消費失敗創(chuàng)建RETRY topic

  • consumer client 和服務端保持心跳時創(chuàng)建RETRY topic

圖片

心跳時創(chuàng)建 retry topic

線下環(huán)境的消費組存在大量的臨時測試group,而 RocketMQ會給每個實際存在的消費組創(chuàng)建RETRY topic,導致 RETRY topic 大量膨脹。

(2)如果所有消息自動重試,順序消息會亂序嗎?

我們知道,RocketMQ中包含三種消息類型:普通消息、普通有序消息、嚴格有序消息。

三種消息的類型介紹如下:

  • 普通消息:消息是無序的,任意發(fā)送發(fā)送哪一個隊列都可以。
  • 普通有序消息:同一類消息(例如某個用戶的消息)總是發(fā)送到同一個隊列,在異常情況下,也可以發(fā)送到其他隊列。
  • 嚴格有序消息:消息必須被發(fā)送到同一個隊列,即使在異常情況下,也不允許發(fā)送到其他隊列。

對于這三種類型的消息,RocketMQ對應的提供了對應的方法來分別消息:

//發(fā)送普通消息,異常時默認重試
public SendResult send(Message msg)

//發(fā)送普通有序消息,通過selector動態(tài)決定發(fā)送哪個隊列,異常默認不重試,可以用戶自己重試,并發(fā)送到其他隊列
public SendResult send(Message msg, MessageQueueSelector selector, Object arg)

//發(fā)送嚴格有序消息,通過指定隊列,保證嚴格有序,異常默認不重試
public SendResult send(Message msg, MessageQueue mq)

所以RocketMQ客戶端的生產(chǎn)者默認重試機制,只對普通消息有作用。對于普通有序消息、嚴格有序消息是沒有作用。

(3)nameserver數(shù)據(jù)一致性問題

在通過修改啟動參數(shù)com.rocketmq.remoting.frameMaxLength進行臨時恢復的時候,發(fā)現(xiàn)一個問題:日志恢復了,但是控制臺上卻仍然沒有顯示broker-b。

排查了下發(fā)現(xiàn),由于nameserver有4臺,只重啟了一臺,而控制臺連接訪問的nameserver是另一臺,所以顯示不正確。

通過切換控制臺nameserver地址,就能看到broker-b了。

為什么不同nameserver允許數(shù)據(jù)不一致呢?

前面在排查的過程中也發(fā)現(xiàn)了,broker源碼中通過遍歷nameserverlist,在線程池中異步注冊topic信息到nameserver。

圖片

注冊邏輯

而這也體現(xiàn)了RocketM中對nameserver的設計思想。

nameserver是一個AP組件,而不是CP組件!

在 RocketMQ 中 Nameserver 集群中的節(jié)點相互之間不通信,各節(jié)點相互獨立,實現(xiàn)非常簡單。但同樣會帶來一個問題:

Topic 的路由信息在各個節(jié)點上會出現(xiàn)不一致。

那 Nameserver 如何解決這個問題呢?RocketMQ 的設計者采取的方案是不解決,即為了保證 Nameserver 的高性能,允許存在這些缺陷。

NameServer之間不通信,消息發(fā)送端通過PULL方式更新topic信息,無法及時感知路由信息的變化,因此引入了消息發(fā)送重試(只針對普通消息)與故障規(guī)避機制來保證消息的發(fā)送高可用。

事實上,在RocketMQ的早期版本,即MetaQ 1.x和MetaQ 2.x階段,也是依賴Zookeeper的(CP型組件)。但MetaQ 3.x(即RocketMQ)卻去掉了ZooKeeper依賴,轉(zhuǎn)而采用自己的NameServer。

NameServer數(shù)據(jù)不一致,比較大的影響就是topic的隊列會存在負載不均衡的問題,以及消費端的重復消費問題,這些問題對消息隊列來說都是可以忍受的,只要最終能保持一致,恢復平衡即可。

責任編輯:姜華 來源: 阿丸筆記
相關推薦

2024-04-22 00:00:00

RocketMQ優(yōu)化位點

2024-01-24 09:00:31

SSD訂閱關系內(nèi)存

2021-08-05 15:03:14

Windows 服務器系統(tǒng)

2022-08-12 10:02:24

數(shù)據(jù)中心谷歌

2024-08-19 04:00:00

2025-04-15 19:52:04

2021-04-16 07:04:53

SQLOracle故障

2021-10-08 08:09:13

Facebook算法DNS

2024-11-19 08:36:16

2025-07-28 02:55:00

虛擬列表JavaScript單線程

2021-03-18 10:33:26

智商本科HR

2021-01-22 09:56:50

微信微信8.0移動應用

2022-01-19 11:19:25

Java/接口/代碼

2021-09-13 08:38:42

阿里時間成本

2017-09-04 16:51:03

Java虛擬機GC

2021-02-02 09:13:11

索引SQL數(shù)據(jù)庫

2024-01-26 07:48:10

SpringKafka提升

2024-01-05 13:26:00

KafkaTopicSpring

2023-09-21 10:31:06

人工智能模型

2025-09-01 17:18:55

GoogleChatGPT模型
點贊
收藏

51CTO技術棧公眾號