稳定性 耗时 监控原因分析-- dubbo rpc 框架 的线程池,io 连接模型. 客户端,服务端

上次 提到的Nagle算法特性有可能是dubbo调用”网络耗时高“的始作俑者,后来又仔细看了下dubbo的代码,发现dubbo在consumer端已经将tcp设置成非延迟(即关闭Nagle特性)了,代码片段如下:

order模块中调用量最高的接口是查询未完成订单,调用量达到每10秒18000,如下:

但该接口在order这边的平均耗时特别低(尖刺是由发布引起的,这里忽略),才1毫秒:

该接口直接由kop来调用,我们看kop这边的平均耗时:

可以看出,在低峰期,kop这边的耗时和order的耗时是匹配的,1-2毫秒,但在高峰期,kop这边的平均耗时高达13毫秒!
是否因为单TCP吞吐达到瓶颈?
和@董磊讨论了下,在order这边将该接口的TCP连接数设置成3(这里需要注意,connections不能设置成1,设置成1还将继续共用1条tcp连接,至少需要2或2以上),如下:
<dubbo:service interface="PassService"
   ref="passService" connections="3"version="1.0.0" />
上线后的效果如下:

可以看出,在设置成3个单独tcp连接后,网络耗时再也不受高峰期影响,一直很平稳!!

如果不是Nagle算法导致的问题,那么还有可能是其他什么原因呢?
为了达到当前网络条件下的最大吞吐量,TCP协议设计成自适应的(可以参看:https://segmentfault.com/a/1190000008803687),就是说如果网络质量高的情况下,理论上单条TCP连接都能“占满”整个带宽。但tcp是基于可靠到达+顺序保证的,所以每个发生着在发送tcp数据段后都需要收到接收者的ack后才认为数据已经发送成功,否则将定时重发一定次数。而为了增加吞吐量,tcp这边提出了窗口的概念,窗口内的tcp数据段会一次性发送,而不需要等前一个段ack再发送另一个段,而tcp会根据网络质量来逐渐增大窗口。

所以tcp发送数据的吞吐量可能如下几个因素都有关(这里只是分析,欢迎大伙一起纠正和补充):
网络带宽。在我们线上机器是万兆网卡,而且我们用dubbo做rpc都是小数据高频传输,所以不存在带宽被打满的情况。
mss大小。每个分段中能发送的最大TCP数据量。
平均窗口大小。一旦网络质量高,tcp的窗口将变得很大,否则窗口将缩小,直至达到当前网络的合理值,当然窗口一直在不断变化。
TCP缓冲区大小。缓冲区满了发送将一定程度的阻塞。
平均重发次数。这也直接和网络质量有关系。
不论是什么原因,可以知道的是带宽不是瓶颈,网络质量也是靠谱的,所以瓶颈应该和TCP本身的设计相关,既然多条TCP连接能解决问题,现在所要做的就是如何发现业务中网络耗时高的调用了。

于是我们对taxi-rpc和taxi-dubbo进行了升级(后面会单独发邮件推广),用来统计网络耗时,计算公式:网络耗时 = consumer处理耗时 – provider处理耗时,这里先忽略服务器时间同步的影响。order和cos已经进行了升级,所以cos调用order的网络耗时如下:

后期如果发现某些接口网络耗时特别高,就很有可能是单个公共的tcp连接不够用了,届时可以对tcp连接的数量进行优化!

时间: 2024-11-07 19:15:47

稳定性 耗时 监控原因分析-- dubbo rpc 框架 的线程池,io 连接模型. 客户端,服务端的相关文章

简单RPC框架-业务线程池

*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* BLOCKS =============================================================================*/ p, blockquote, ul, ol, dl, table, pre { margin: 15px 0; } /* HEAD

从零开始手写 dubbo rpc 框架

rpc rpc 是基于 netty 实现的 java rpc 框架,类似于 dubbo. 主要用于个人学习,由渐入深,理解 rpc 的底层实现原理. 前言 工作至今,接触 rpc 框架已经有很长时间. 但是对于其原理一直只是知道个大概,从来没有深入学习过. 以前一直想写,但由于各种原因被耽搁. 技术准备 Java 并发实战学习 TCP/IP 协议学习笔记 Netty 权威指南学习 这些技术的准备阶段,花费了比较长的时间. 也建议想写 rpc 框架的有相关的知识储备. 其他 rpc 框架使用的经验

Netty自娱自乐之类Dubbo RPC 框架设计构想 【上篇】

之前在前一篇的<Netty自娱自乐之协议栈设计>,菜鸟我已经自娱自乐了设计协议栈,gitHub地址为https://github.com/vOoT/ncustomer-protocal.先这一篇中,准备接着自娱去实现一个RPC框架,现在公司共的是Dubbo,那么先不看其代码,先自行实现一下吧. dubbo 包括 注册和服务调用,细节我们先不管,然后,我先先实现一个如下的简单模型 哈哈哈,第一个版本就是这么简单,粗暴.说到自定义配置,首先想到的是Spring 自定义标签,利用标签进行配置服务.而

一个简单RPC框架是如何炼成的(VI)——引入服务注册机制

开局篇我们说了,RPC框架的四个核心内容 RPC数据的传输. RPC消息 协议 RPC服务注册 RPC消息处理 接下来处理RPC服务的注册机制.所谓注册机制,就是Server需要声明支持哪些rpc方法,然后当客户端发送调用某个声明的rpc方法之后,服务端能自动找到执行该请求的具体方法.以实际的例子为例,这是现在server端处理RPC请求的代码 def procRequest(self): # 循环读取并处理收到的客户端请求 while True: req = self.conn.recv()

一个简单RPC框架是怎样炼成的(VI)——引入服务注冊机制

开局篇我们说了.RPC框架的四个核心内容 RPC数据的传输. RPC消息 协议 RPC服务注冊 RPC消息处理 接下来处理RPC服务的注冊机制.所谓注冊机制,就是Server须要声明支持哪些rpc方法.然后当client发送调用某个声明的rpc方法之后,服务端能自己主动找到运行该请求的详细方法.以实际的样例为例.这是如今server端处理RPC请求的代码 def procRequest(self): # 循环读取并处理收到的client请求 while True: req = self.conn

java.net.SocketException:Software caused connection abort: recv failed 异常分析 +socket客户端&amp;服务端代码

java.net.SocketException:Software caused connection abort: recv failed 异常分析 分类: 很多的技术 2012-01-04 12:54 8004人阅读 评论(6) 收藏 举报 socket服务器bufferstring网络java 第 1个异常是java.net.BindException:Address already in use: JVM_Bind.该异常发生在服务器端进行new ServerSocket(port)(p

Java并发(基础知识)—— Executor框架及线程池

在Java并发(基础知识)—— 创建.运行以及停止一个线程中讲解了两种创建线程的方式:直接继承Thread类以及实现Runnable接口并赋给Thread,这两种创建线程的方式在线程比较少的时候是没有问题的,但是当需要创建大量线程时就会出现问题,因为这种使用方法把线程创建语句随意地散落在代码中,无法统一管理线程,我们将无法管理创建线程的数量,而过量的线程创建将直接使系统崩溃. 从高内聚角度讲,我们应该创建一个统一的创建以及运行接口,为我们管理这些线程,这个统一的创建与运行接口就是JDK 5的Ex

转:【Java并发编程】之十九:并发新特性—Executor框架与线程池(含代码)

  Executor框架简介 在Java5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.cocurrent 包下,通过该框架来控制线程的启动.执行和关闭,可以简化并发编程的操作.因此,在Java 5之后,通过Executor来启动线程比使用Thread的start方法更好,除了更易管理,效率更好(用线程池实现,节约开销)外,还有关键的一点:有助于避免this逃逸问题--如果我们在构造器中启动

Java的Executor框架和线程池实现原理

一,Java的Executor框架 1,Executor接口 public interface Executor { void execute(Runnable command); } Executor接口是Executor框架中最基础的部分,定义了一个用于执行Runnable的execute方法,它没有实现类只有另一个重要的子接口ExecutorService 2,ExecutorService接口 //继承自Executor接口 public interface ExecutorServic