0x00. 翻车现场

那是个月黑风高的夜晚,小黑哥成功将新版本发布到了生产,小心翼翼检查了应用日志,后续测试小姐姐验收成功。

恩,小黑哥我还是一如既往的稳~

接着小黑哥就跑到楼下食堂吃个夜宵,谁知正吃到一半,线上运维同学发来几条告警信息,服务器连接数过多警告,连接数已经飙升到上万。

天啦撸,赶紧放下正在啃的鸡腿,火速跑到工位上查看问题。

0x01. 历尽艰辛,深入排查

打开电脑,首先确认生产交易一切还正常。查看这段时间日志,发现并没有什么异常情况,日志都是正常输出。没办法只好再次走查此次改动的代码,发现全是业务代码,并没有任何与网络连接有关的代码改动。

问题真的请奇怪,一时半会想不到解决方案,只好先实施重启大法。重启过后,连接数下降了,到达了正常阈值。但是不一会连接数持续升高,不一会还是升到上万。

这下重启解决不了办法,只好从应用出发,找找到底什么问题。

这个应用是一个路由服务,会根据上游系统指定路由编码,将交易分发到下游子系统。架构图如下:

之前在这篇文章路由系统演化史讲过,路由系统使用 Dubbo API ,代码如下:

由于我们还有另外一套系统,也部署这个应用,但是该系统生产机器连接数却很少。交叉比对了两套系统应用的系统配置值,只有 connections 设置不一样,当前有问题的系统设置为 1000,另外一个系统为 10

大致找到原因,也将 connections 设置为 10,重启应用,生产机器连接数恢复正常。

0x02. 抽丝剥茧,还原经过

首先我们来看下 connections 这个配置的作用,可以直接查看官方文档http://dubbo.apache.org/zh-cn/docs/user/references/xml/dubbo-reference.html。

下面配置来源于:dubbo:reference

总共可以在三个地方配置 connections 参数,分别为:dubbo:referencedubbo:consumerdubbo: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 参数加入如下配置:

1-Dshareconnections=10

如果消费者需要调用同个服务提供者应用的 10 个服务接口,服务提供者提供两个节点,shareconnections=1000,消费者服务启动之后,仅会创建 1000*2=2000 连接。

这么对比,shareconnectionsconnections建立连接不是一个量级。

2.1 使用连接

消费者调用服务时,将会随机从连接数组中取一个连接使用,代码位于 DubboInvoker#doInvoke

2.2 如何正确配置连接数

首先我们来看下单一长连接性能,文档地址:http://dubbo.apache.org/zh-cn/docs/user/references/protocol/dubbo.html

对于只有少数消费者场景,我们可以使用默认配置,即不配置 connections 参数 。若调用同一个提供者服务过多,可以考虑适当多配增加 shareconnections。最后若某一服务接口调用量特别大,可以考虑为这个服务单独配置 connections

0x03. 举一反三,聊聊其他配置

Dubbo 还有很多配置项,下面着重介绍一些配置参数。

3.1 dubbo.provider.executes

该参数用来控制每个方法最大并行数。如果该值设置为 10 ,每个服务方法若已有 10 个请求正在处理,第 11 个服务请求将会抛出异常,直到之前服务调用完成,正在请求数量小于 10 未知。

一旦设置 executes>0,Dubbo 将会通过 SPI 机制启用 ExecuteLimitFilter,源码还是比较简单。

3.2 dubbo.reference.actives

这个参数将会控制消费者每个服务每个方法最大并发数。可以通过 dubbo:method.actives 单独为服务方法设置。如果该值为 10,一旦某个服务某个方法并发数超过 10,第 11 个服务将会等待,若在超时时间内其他请求执行结束,计数值减值小于阈值,第 11 个请求将会被执行,否者将会抛错。

dubbo.provider 上也可以配置这个值,其将会与 connections 一样,将会传递给消费者。

原理等同上面方法,将会启用 ActiveLimitFilter,源码如下 :

这里需要注意 actives 引起超时与服务端超时区别。

3.3 dubbo.protocol.accepts

服务提供者最大连接数,如果设置 accepts=10,一旦服务提供者连接数大于 10,其余新增连接将会被拒绝。

方法源码如下:

服务提供者断开连接,消费端将会打印连接断开日志。另外消费者会定时检查长连接可用性,若不可用,将会重新发起连接。所以在消费者端就会看到连接断开,重连,然后又被服务提供者断开的现象。

0x04. 总结

本文通过一次生产连接数过多的现象,详细剖析定位问题的原因。作为一个合格的开发,对于开源框架,我们不仅要会熟练使用,也要了解其底层实现,相关参数设置。一旦参数设置不合理就可能引发生产事故。

另外对于生产系统,监控系统非常重要。比如上面的问题,如果没有监控发现,小黑哥可能一时半会都不知道有这个问题存在,毕竟平时也不会太关注连接数这个指标。

特别推荐一个分享架构+算法的优质内容,还没关注的小伙伴,可以长按关注一下:

长按订阅更多精彩▼如有收获,点个在看,诚挚感谢

天啦噜!生产机器连接数飙升到上万,背后发生了什么?相关推荐

  1. InetAddress.getByName背后发生了什么

    [背景] 在一次问题排查过程中,发现偶现调用"InetAddress.getByName()"无法通过域名解析到IP(实际在容器中都能正确解析到),因此怀疑和容器的DNS解析有问题 ...

  2. [C# 基础知识系列]专题五:当点击按钮时触发Click事件背后发生的事情

    引言: 当我们在点击窗口中的Button控件VS会帮我们自动生成一些代码,我们只需要在Click方法中写一些自己的代码就可以实现触发Click事件后我们Click方法中代码就会执行,然而我一直有一个疑 ...

  3. 理解go func背后发生了什么?

    参考:理解go func背后发生了什么 - Go语言中文网 - Golang中文社区 先看下下面这段代码? (1)A与B分布在不同的goroutine队列 package mainimport (&q ...

  4. 生活当中调整时钟时间背后发生的事情

    生活当中调整时钟时间背后发生的事情 我们在生活当中想要设定时钟.手表的时间的事情,我们通过会和大多数人一样,会按照手机上的时间来设定.但是,这背后发生了什么事情,我想大部分人应该是不知道的,其实我们自 ...

  5. 科普丨让机器看见世界,这背后的技术是什么?

    IDF大会上,英特尔终于向外界推出了Realsense技术的SDK和机器人开发工具包以及无人机平台.搭载Realsense 的3D摄像头能够帮助机器实现查看环境物体"深度"信息,通 ...

  6. 上帝就在机器里:复杂算法背后隐藏的可怕现实

    上帝就是黑箱. 编者按:本文节选自Carl Miller的<诸神之死:新的全球权力攫取>(The Death of the Gods: The new global power grab) ...

  7. BTC交易费激增,LTC活跃地址数飙升! BRC-20爆火背后,区块链网络经历了什么?

    BRC-20 代币和 Ordinals 协议的日益普及推动了对比特币区块空间的需求,比特币区块链的费用已飙升至两年来的高点. BRC-20代币标准在 Ordinals 协议上运行.Ordinals 允 ...

  8. 威纶通宏开机后使用初始化宏指令_【操作系统】我们按下电脑开机键的背后发生了什么?...

    作者:CVNot 链接:https://juejin.im/post/5e8844996fb9a03c6675b9d6 操作系统是什么? 操作系统是用来管理计算机硬件的软件,狭义上实现该定义的为操作系 ...

  9. ping 命令_命令PING背后发生了什么,记得Windows XP拒绝利用PING命令通信吗

    首先了解PING命令,PING是Windows.Unix和Linux系统下的一个命令,当小伙伴们检查网络情况的时候,先使用的命令肯定是PING命令.PING也属于一个通信协议,是TCP/IP协议的一部 ...

最新文章

  1. oracle 快速备份表数据
  2. 累加器配上委托也可以很吊
  3. FFmpeg编写一个简单播放器 -1
  4. gevent queue应用1
  5. java keytool 导入证书_java - Keytool无法导入证书 - SO中文参考 - www.soinside.com
  6. android 动态修改菜单,如何在Android的“选项”菜单上更改MenuItem?
  7. Java Map 怎样实现Key 的唯一性?
  8. Spring Data JPA 从入门到精通~Auditing及其事件详解
  9. PTA--Reversing Linked List
  10. 「专题训练」Collecting Bugs(POJ-2096)
  11. (笔记)涉及到的WinAPI函数
  12. 40岁开始学python_37 岁了,想学习 Linux 和 Python ,不知道晚不晚。
  13. 牛客练习赛50 F tokitsukaze and Another Protoss and Zerg(分治NTT)
  14. VPS云主机是什么?有什么优势?
  15. 5.1.7—二叉树的遍历—Recover Binary Sear Tree
  16. 利用Python脚本给图片批量添加文字水印
  17. macbook linux 双系统,MacBook Air (13-inch, 2017)(8+128G)安装Ubuntu18.04双系统
  18. 《尚硅谷大数据Hadoop》教程
  19. 计算思维导论-为什么要学习计算思维
  20. oracle字体加粗函数_html把字体加粗

热门文章

  1. 【MySQL】数据库1 (数据库+基本操作介绍)
  2. 【Java】 链表的回文结构
  3. 关于学习Python的一点学习总结(46->属性访问)
  4. 练习5-3 数字金字塔 (15 分)
  5. 电脑c盘满了怎么办_电脑用久了C盘空间不够用怎么办?教你如何无损扩展C盘空间大小...
  6. 【位运算】解题报告:luoguP4310 绝世好题(位运算优化DP)
  7. 7 12次c语言上机作业,第十二次C语言上机实验参考答案
  8. 文件系统_文件系统基础总结
  9. 打开完成查看的CAD图纸如何一键进行打印?
  10. playbook核心元素之 -- 角色role(9)