Q1# 問(wèn)題整理20210529
業(yè)務(wù)要發(fā)展,功能要增強(qiáng),基礎(chǔ)設(shè)施要完善,變更就無(wú)法避免,帶來(lái)新功能的同時(shí)也帶來(lái)了風(fēng)險(xiǎn)。整理下近期碰到的和被問(wèn)的幾個(gè)問(wèn)題。
問(wèn)題一
Zookeeper幾乎每年都能聽(tīng)到有公司踩到坑,故事往往是這樣:@1 多個(gè)業(yè)務(wù)線共用zk集群,某個(gè)新上的功能把zk當(dāng)緩存用,大量創(chuàng)建zk路徑,造成zk不堪重負(fù)癱瘓;@2 某個(gè)新上的功能往zk集群中寫(xiě)入過(guò)大消息,單條消息好幾兆,造成zk集群性能下降,甚至帶寬、磁盤(pán)被打滿。
知道可能的坑咱肯定不能再去踩了,重要中間件的獨(dú)立zk集群徹底隔離,上面的問(wèn)題基本可以避免。今天的故事卻發(fā)生在watch的數(shù)量上。
現(xiàn)象
從4月中旬左右發(fā)現(xiàn)zk的watch水位在翻倍增長(zhǎng),從200多萬(wàn)到400多萬(wàn)一直翻到800多萬(wàn),一直到五一之后的12000萬(wàn)。watch水位的升高會(huì)影響與zk通信的延遲。

原因
SDK中有使用一個(gè)公共主題用于客戶(hù)端行為收集,該主題下會(huì)被注冊(cè)臨時(shí)節(jié)點(diǎn),臨時(shí)節(jié)點(diǎn)會(huì)被watch用于一個(gè)特定功能。在卡點(diǎn)升級(jí)過(guò)程中隨著服務(wù)應(yīng)用的接入,注冊(cè)的節(jié)點(diǎn)越來(lái)越多。例如:3000個(gè)臨時(shí)節(jié)點(diǎn)每個(gè)節(jié)點(diǎn)都會(huì)有3000個(gè)watch數(shù)量,就會(huì)有3000的平方個(gè)watch數(shù)量,就是900萬(wàn)個(gè)watch數(shù)量
解決
止血方案:刪除公共主題下的臨時(shí)節(jié)點(diǎn),watch數(shù)量水位恢復(fù)正常
根除方案:剔除SDK中對(duì)注冊(cè)節(jié)點(diǎn)的watch,例如:curator中用NodeCacheListener替代TreeCacheListener,同時(shí)移除關(guān)聯(lián)節(jié)點(diǎn)的wath功能,或者對(duì)公共主題進(jìn)行過(guò)濾,不再注冊(cè)節(jié)點(diǎn)
問(wèn)題二
問(wèn): Sentinel的集群限流有預(yù)熱功能嗎?
答: 預(yù)熱適用于單機(jī)限流。
源碼
這個(gè)問(wèn)題先從源碼角度看看:
public boolean canPassCheck(/*@NonNull*/ FlowRule rule, Context context, DefaultNode node, int acquireCount,
boolean prioritized) {
String limitApp = rule.getLimitApp();
if (limitApp == null) {
return true;
}
if (rule.isClusterMode()) { // 注解@1 集群限流邏輯
return passClusterCheck(rule, context, node, acquireCount, prioritized);
}
// 注解@2 單機(jī)限流邏輯
return passLocalCheck(rule, context, node, acquireCount, prioritized);
}
備注:集群限流邏輯:會(huì)向token server請(qǐng)求token,如果獲取token則放行否則拒絕,沒(méi)有預(yù)熱相關(guān)邏輯。
下面接著看單機(jī)限流:?jiǎn)螜C(jī)限流會(huì)有不同類(lèi)型限流效果的選擇,因此預(yù)熱只有單機(jī)限流才存在。

問(wèn)題三
問(wèn): RocketMQ默認(rèn)消費(fèi)重試多少次?可以自定義設(shè)置嗎?
答: 默認(rèn)消費(fèi)16次,可以自定義設(shè)置消費(fèi)次數(shù),通過(guò)DefaultMQPullConsumer#setMaxReconsumeTimes設(shè)置
源碼
private int maxReconsumeTimes = 16;
// 注解@1 DefaultMQPullConsumer#setMaxReconsumeTimes
public void setMaxReconsumeTimes(final int maxReconsumeTimes) {
this.maxReconsumeTimes = maxReconsumeTimes;
}
問(wèn)題四
問(wèn): RocketMQ發(fā)送重試次數(shù)可以設(shè)置嗎?
答: 可以的,默認(rèn)2次重試算上第1次共3次。可以自定義設(shè)置重試次數(shù)。
// 默認(rèn)次數(shù)
private int retryTimesWhenSendFailed = 2;
// 同步發(fā)送重試次數(shù)
producer.setRetryTimesWhenSendFailed();
// 異步發(fā)送重試次數(shù)
producer.setRetryTimesWhenSendAsyncFailed();
