转载

高并发dubbo服务,每次重启后都大量超时,我懵圈了

前言

今天群里小伙伴 黄晓峰 咨询一个问题:"dubbo接口怎么做预热呢,每次上线,都会有一小部分超时?"。熟悉JVM都知道,JVM重启后有一段预热过程,要运行一段时间,它的性能才能达到最佳状态。阿里JVM团队就针对原生JVM这个缺陷进行了优化,其特性名曰: jwarmup ,可以戳链接了解更多:  Alibaba JVM创新提效 获国际社区认可登台JVM圈顶会 (http://tech.gmw.cn/2017-08/26/content_25844099.htm);

另外,在 JVM大神你假笨 那里了解到jwarmup的大概原理: 针对上次JIT对应用的优化,主动去触发JIT编译优化,而不是等jvm运行一段时间自己去感知

阿里大厂可以这么做,我们小厂肿么办?事实上dubbo作者 梁飞大神 考虑到了这种情况,在dubbo中也引入了"warmup"特性(注意,虽然都叫warnup, 但是dubbo的warmup和阿里JVM的jwarmup原理还是完全不一样的 ),核心源码在 "com.alibaba.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance.java" 中:

protected int getWeight(Invoker<?> invoker, Invocation invocation) {
// 先得到Provider的权重
int weight = invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT);
if (weight > 0) {
// 得到provider的启动时间戳
long timestamp = invoker.getUrl().getParameter(Constants.REMOTE_TIMESTAMP_KEY, 0L);
if (timestamp > 0L) {
// provider已经运行时间
int uptime = (int) (System.currentTimeMillis() - timestamp);
// 得到warmup的值,默认为10分钟
int warmup = invoker.getUrl().getParameter(Constants.WARMUP_KEY, Constants.DEFAULT_WARMUP);
// provider运行时间少于预热时间,那么需要重新计算权重weight(即需要降权)
if (uptime > 0 && uptime < warmup) {
weight = calculateWarmupWeight(uptime, warmup, weight);
}
}
}
return weight;
}

static int calculateWarmupWeight(int uptime, int warmup, int weight) {
// 随着provider的启动时间越来越长,慢慢提升权重直到weight
int ww = (int) ( (float) uptime / ( (float) warmup / (float) weight ) );
return ww < 1 ? 1 : (ww > weight ? weight : ww);
}

warnup权重计算过程:

根据calculateWarmupWeight()方法实现可知,随着provider的启动时间越来越长,慢慢提升权重直到weight,且权重最小值为1,所以:
如果provider运行了1分钟,那么weight为10,即只有最终需要承担的10%流量;
如果provider运行了2分钟,那么weight为20,即只有最终需要承担的20%流量;
如果provider运行了5分钟,那么weight为50,即只有最终需要承担的50%流量;
... ...

这里需要注意的是,dubbo默认有3种负载均衡实现方式:随机,轮询,一致性哈希;其中一致性哈希是不受权重影响的,也就是说,如果选择一致性哈希负载均衡,就不支持dubbo的预热特性了。

问题

既然,dubbo有预热功能,为什么每次重启,还会有那么多的超时呢?后来咨询小伙伴 黄晓峰VIVO ,他们的dubbo是基于dubbox的自建分支,dubbox2.8.4和dubbo原生分支的代码是有一点出入的:

高并发dubbo服务,每次重启后都大量超时,我懵圈了
dubbox&dubbo AbstractLoadBalance.java差异性

笔者查找Github上dubbo更新,从 AbstractLoadBalance.java 的提交记录发现有过一次fix,记录如下:

高并发dubbo服务,每次重启后都大量超时,我懵圈了
Fix warmup timestamp bug

修改记录为如下所示:

高并发dubbo服务,每次重启后都大量超时,我懵圈了
the commit
fix来源:
https://github.com/apache/incubator-dubbo/commit/ed66afd9a38d80f839f0381fbd1dc1d3c068bc1c#diff-c5cb2df641f0a7d0553343c757425d2b

真相

真相原来如此,由于dubbox基于dubbo比较老的分支,而这个bug fix是 committed on 10 Oct 2017 ,所以dubbox分支的bug依然存在。我相信很多使用老版本dubbo或者dubbox的公司,都存在这个问题!

既然提到dubbo预热问题,另外一个优化点也可以参考一下(和warmup没有关系),dubbo官方称之为 延迟暴露

# 这个申明的含义是等spring容器启动后过5s再暴露dubbo服务:
<dubbo:provider delay="5000"/>
或者延迟暴露某个接口:
<dubbo:service delay="5000" interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" version="1.0.0"/>

验证日志如下--可以看到"Dubbo service server started"即dubbo服务启动后,过了5s才暴露服务:

[28/04/18 05:40:59:059 CST] main  INFO support.DefaultListableBeanFactory: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6b927fb: defining beans [dubbo-test,com.alibaba.dubbo.config.RegistryConfig,com.alibaba.dubbo.config.ProviderConfig,demoService,testService,com.alibaba.dubbo.demo.DemoService,com.alibaba.dubbo.demo.TestService]; root of factory hierarchy
[28/04/18 05:40:59:059 CST] main INFO container.Main: [DUBBO] Dubbo SpringContainer started!, dubbo version: 2.0.0, current host: 127.0.0.1
[2018-04-28 17:40:59] Dubbo service server started!
[28/04/18 05:41:04:004 CST] DelayExportServiceThread INFO config.AbstractConfig: [DUBBO] Export dubbo service com.alibaba.dubbo.demo.DemoService to local registry, dubbo version: 2.0.0, current host: 127.0.0.1
[28/04/18 05:41:04:004 CST] DelayExportServiceThread INFO config.AbstractConfig: [DUBBO] Export dubbo service com.alibaba.dubbo.demo.TestService to local registry, dubbo version: 2.0.0, current host: 127.0.0.1

总结

无论是dubbo的warmup特性还是延迟暴露服务,对生产环境都有很大的帮助,所以,赶紧做如下的优化吧:

  1. 如果是dubbox分支,或者旧的dubbo分支,请升级dubbo版本,或者merge这个PR修复warmup特性时间戳的问题;

  2. 配置 dubbo:provider delay="5000" 延迟暴露所有dubbo服务;

注意 按照dubbo参数等价转换特性,可以用-Ddubbo.provider.deplay代替,但是笔者跟踪源码发现这里有个bug并已经提交了issue,请戳【System property dubbo.service.delay invalid】,链接地址为: https://github.com/apache/incubator-dubbo/issues/1728 ,如果你的dubbo也存在这个问题,就老老实实用dubbo:provider delay="5000" 这种xml配置方式吧。

原文  http://mp.weixin.qq.com/s?__biz=Mzg3MjA4MTExMw==&mid=2247486582&idx=2&sn=8fcd587a12f84d7c066d2c4fa7743445
正文到此结束
Loading...