我的博客地址 studyidea.cn,点击查看更多原创文章html
那是个月黑风高的夜晚,小黑哥成功将新版本发布到了生产,当心翼翼检查了应用日志,后续测试小姐姐验收成功。java
恩,小黑哥我仍是一如既往的稳~apache
接着小黑哥就跑到楼下食堂吃个夜宵,谁知正吃到一半,线上运维同窗发来几条告警信息,服务器链接数过多警告,链接数已经飙升到上万。编程
天啦撸,赶忙放下正在啃的鸡腿,火速跑到工位上查看问题。数组
打开电脑,首先确认生产交易一切还正常。查看这段时间日志,发现并无什么异常状况,日志都是正常输出。没办法只好再次走查这次改动的代码,发现全是业务代码,并无任何与网络链接有关的代码改动。服务器
问题真的请奇怪,一时半会想不到解决方案,只好先实施重启大法。重启事后,链接数降低了,到达了正常阈值。可是不一会链接数持续升高,不一会仍是升到上万。网络
这下重启解决不了办法,只好从应用出发,找找到底什么问题。架构
这个应用是一个路由服务,会根据上游系统指定路由编码,将交易分发到下游子系统。架构图以下:并发
以前在这篇文章路由系统演化史讲过,路由系统使用 Dubbo API ,代码以下:框架
因为咱们还有另一套系统,也部署这个应用,可是该系统生产机器链接数却不多。交叉比对了两套系统应用的系统配置值,只有 connections 设置不同,当前有问题的系统设置为 1000,另一个系统为 10 。
大体找到缘由,也将 connections 设置为 10,重启应用,生产机器链接数恢复正常。
首先咱们来看下 connections 这个配置的做用,能够直接查看官方文档dubbo.apache.org/zh-cn/docs/…。
下面配置来源于:dubbo:reference
总共能够在三个地方配置 connections 参数,分别为:dubbo:reference,dubbo:consumer,dubbo:provider。
注意:图中标示地方实际上与源码存在出入。截止 Dubbo 2.7.3 版本,图中 ① 处,dubbo:consumer 文档上显示为 100,实际源码默认配置为 0,这点须要注意。另外 ② 处文字描述存在问题,目前 connections 参数主要对 dubbo 协议有用,http 短链接协议还未使用该配置
其中 reference.connections 为服务级别的配置,若未配置将会使用 consumer.connections 配置值。另外这个参数若在 provider.connections 配置,其对服务提供者无效,参数将经过注册中心传递给消费者成为其默认配置。三者实际做用顺序以下:
Debug 源码,connections 最终会在 DubboProtocol#getClients 被使用,方法源码以下:
Dubbo 协议默认将会使用 **Netty **与服务提供者创建长链接
首先将会获取 connections 配置,规则如上图,若其大于 0,创建 connections 数量的长链接。
若是一个提供者对外暴露 10 个接口,且其有两个节点。消费者端引入提供者全部服务,配置 connections=1000。当消费者启动以后,将会马上建立 1000x2x10=20000 链接。这就是生产机器链接数飙升的根本缘由。
路由服务使用 Dubbo API 编程,服务启动成功以后,只有上游系统调用路由服务时, Dubbo 才会与与下游服务提供者创建链接,因此现象看起来服务链接数是慢慢激增。
若是未设置 connections 参数,Dubbo 将会建立共享链接(shareconnections)。消费者调用的服务若为同一个服务提供者(IP+PORT 区分),这些服务接口将会共享这些链接。
shareconnections 能够在 dubbo:consumer 配置中配置,也能够在启动 JVM 参数加入以下配置:
-Dshareconnections=10
复制代码
若是消费者须要调用同个服务提供者应用的 10 个服务接口,服务提供者提供两个节点,shareconnections=1000,消费者服务启动以后,仅会建立 1000*2=2000 链接。
这么对比,shareconnections 与 connections 创建连不是一个量级。
消费者调用服务时,将会随机从链接数组中取一个链接使用,代码位于 DubboInvoker#doInvoke
。
首先咱们来看下单一长链接性能,文档地址:dubbo.apache.org/zh-cn/docs/…
对于只有少数消费者场景,咱们可使用默认配置,即不配置 connections 参数 。若调用同一个提供者服务过多,能够考虑适当多配增长 shareconnections。最后若某一服务接口调用量特别大,能够考虑为这个服务单独配置 connections。
Dubbo 还有不少配置项,下面着重介绍一些配置参数。
该参数用来控制每一个方法最大并行数。若是该值设置为 10 ,每一个服务方法若已有 10 个请求正在处理,第 11 个服务请求将会抛出异常,直到以前服务调用完成,正在请求数量小于 10 未知。
一旦设置 executes>0,Dubbo 将会经过 SPI 机制启用 ExecuteLimitFilter
,源码仍是比较简单。
这个参数将会控制消费者每一个服务每一个方法最大并发数。能够经过 dubbo:method.actives 单独为服务方法设置。若是该值为 10,一旦某个服务某个方法并发数超过 10,第 11 个服务将会等待,若在超时时间内其余请求执行结束,计数值减值小于阈值,第 11 个请求将会被执行,否者将会抛错。
dubbo.provider
上也能够配置这个值,其将会与 connections 同样,将会传递给消费者。
原理等同上面方法,将会启用 ActiveLimitFilter
,源码以下 :
这里须要注意 actives 引发超时与服务端超时区别。
服务提供者最大链接数,若是设置 accepts=10,一旦服务提供者链接数大于 10,其他新增链接将会被拒绝。
方法源码以下:
服务提供者断开链接,消费端将会打印链接断开日志。另外消费者会定时检查长链接可用性,若不可用,将会从新发起链接。因此在消费者端就会看到链接断开,重连,而后又被服务提供者断开的现象。
本文经过一次生产链接数过多的现象,详细剖析定位问题的缘由。做为一个合格的开发,对于开源框架,咱们不只要会熟练使用,也要了解其底层实现,相关参数设置。一旦参数设置不合理就可能引起生产事故。
另外对于生产系统,监控系统很是重要。好比上面的问题,若是没有监控发现,小黑哥可能一时半会都不知道有这个问题存在,毕竟平时也不会太关注链接数这个指标。
好快,已经在家呆了两周了。哎,出不去,又进不来。之后回想,2020 真是一个使人难忘的一年。。。好了,10 号要正视开工了。
欢迎关注个人公众号:程序通事,得到平常干货推送。若是您对个人专题内容感兴趣,也能够关注个人博客:studyidea.cn