Q1# 问题整理20210529
业务要发展,功能要增强,基础设施要完善,变更就无法避免,带来新功能的同时也带来了风险。整理下近期碰到的和被问的几个问题。
问题一
Zookeeper几乎每年都能听到有公司踩到坑,故事往往是这样:@1 多个业务线共用zk集群,某个新上的功能把zk当缓存用,大量创建zk路径,造成zk不堪重负瘫痪;@2 某个新上的功能往zk集群中写入过大消息,单条消息好几兆,造成zk集群性能下降,甚至带宽、磁盘被打满。
知道可能的坑咱肯定不能再去踩了,重要中间件的独立zk集群彻底隔离,上面的问题基本可以避免。今天的故事却发生在watch的数量上。
现象
从4月中旬左右发现zk的watch水位在翻倍增长,从200多万到400多万一直翻到800多万,一直到五一之后的12000万。watch水位的升高会影响与zk通信的延迟。
原因
SDK中有使用一个公共主题用于客户端行为收集,该主题下会被注册临时节点,临时节点会被watch用于一个特定功能。在卡点升级过程中随着服务应用的接入,注册的节点越来越多。例如:3000个临时节点每个节点都会有3000个watch数量,就会有3000的平方个watch数量,就是900万个watch数量
解决
止血方案:删除公共主题下的临时节点,watch数量水位恢复正常
根除方案:剔除SDK中对注册节点的watch,例如:curator中用NodeCacheListener替代TreeCacheListener,同时移除关联节点的wath功能,或者对公共主题进行过滤,不再注册节点
问题二
问: Sentinel的集群限流有预热功能吗?
答: 预热适用于单机限流。
源码
这个问题先从源码角度看看:
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 单机限流逻辑
return passLocalCheck(rule, context, node, acquireCount, prioritized);
}
备注:集群限流逻辑:会向token server请求token,如果获取token则放行否则拒绝,没有预热相关逻辑。
下面接着看单机限流:单机限流会有不同类型限流效果的选择,因此预热只有单机限流才存在。
问题三
问: RocketMQ默认消费重试多少次?可以自定义设置吗?
答: 默认消费16次,可以自定义设置消费次数,通过DefaultMQPullConsumer#setMaxReconsumeTimes设置
源码
private int maxReconsumeTimes = 16;
// 注解@1 DefaultMQPullConsumer#setMaxReconsumeTimes
public void setMaxReconsumeTimes(final int maxReconsumeTimes) {
this.maxReconsumeTimes = maxReconsumeTimes;
}
问题四
问: RocketMQ发送重试次数可以设置吗?
答: 可以的,默认2次重试算上第1次共3次。可以自定义设置重试次数。
// 默认次数
private int retryTimesWhenSendFailed = 2;
// 同步发送重试次数
producer.setRetryTimesWhenSendFailed();
// 异步发送重试次数
producer.setRetryTimesWhenSendAsyncFailed();