[实战干货]C10K场景下的线上Dubbo问题排查(1)

简介: [实战干货]C10K场景下的线上Dubbo问题排查



Dubbo 是一款轻量级的开源 Java 服务框架,是众多企业在建设分布式服务架构时的首选。中国工商银行自 2014 年开始探索分布式架构转型工作,基于开源 Dubbo 自主研发了分布式服务平台。

Dubbo 框架在提供方消费方数量较小的服务规模下,运行稳定、性能良好。随着银行业务线上化、多样化、智能化的需求越来越旺盛,在可预见的未来,会出现一个提供方为数千个、甚至上万个消费方提供服务的场景。

在如此高负载量下,若服务端程序设计不够良好,网络服务在处理数以万计的客户端连接时、可能会出现效率低下甚至完全瘫痪的情况,即为 C10K 问题。那么,基于 Dubbo 的分布式服务平台能否应对复杂的 C10K 场景?为此,我们搭建了大规模连接环境、模拟服务调用进行了一系列探索和验证。



C10K 场景下 Dubbo 服务调用出现大量交易失败

ALIWARE


1

准备环境


使用 Dubbo2.5.9(默认 netty 版本为 3.2.5.Final)版本编写服务提供方和对应的服务消费方。提供方服务方法中无实际业务逻辑、仅 sleep 100ms;消费方侧配置服务超时时间为 5s,每个消费方启动后每分钟调用1次服务。

准备 1 台 8C16G 服务器以容器化方式部署一个服务提供方,准备数百台 8C16G 服务器以容器化方式部署 7000 个服务消费方。

启动 Dubbo 监控中心,以监控服务调用情况。

2

定制验证场景,观察验证结果



操作步骤 观察内容 验证结果
场景 1 先启动服务提供方,后分批启动消费方 调用 1 小时观察交易情况 存在零星交易超时失败。消费方分散在多台服务器上。
场景 2 在服务正常调用一段时间后,重启提供方 观察提供方重启后的表现 在提供方重启后 1-2 分钟内存在大量交易超时失败,后逐渐恢复。消费方分散在多台服务器上。


验证情况不尽如人意。C10K 场景下 Dubbo 服务调用存在超时失败的情况。

如果分布式服务调用耗时长,从服务消费方到服务提供方全链路节点都会长时间占用线程池资源,增加了额外的性能损耗。而当服务调用并发突增时,很容易造成全链路节点堵塞,从而影响其他服务的调用,并进一步造成整个服务集群性能下降甚至整体不可用,导致发生雪崩。服务调用超时问题不可忽视。因此,针对该 C10K 场景下 Dubbo 服务调用超时失败情况我们进行了详细分析。



C10K场景问题分析

ALIWARE


根据服务调用交易链路,我们首先怀疑交易超时是因为提供方或消费方自身进程卡顿或网络存在延迟导致的。



因此,我们在存在交易失败的提供方、消费方服务器上开启进程 gc 日志,多次打印进程 jstack,并在宿主机进行网络抓包。

1

观察 gc 日志、jstack


提供方、消费方进程 gc 时长、gc 间隔、内存使用情况、线程堆栈等无明显异常,暂时排除 gc 触发 stop the world 导致超时、或线程设计不当导致阻塞而超时等猜想。

2

针对以上两种场景下的失败交易,分别观察网络抓包,对应有以下两种不同的现象


针对场景 1:提供方稳定运行过程中交易超时

跟踪网络抓包及提供方、消费方交易日志。消费方发起服务调用请求发起后,在提供方端迅速抓到消费方请求报文,但提供方从收到请求报文到开始处理交易耗时 2s+。


同时,观察交易请求响应的数据流。提供方业务方法处理完毕后到向消费方发送回包之间也耗时 2s+,此后消费方端迅速收到交易返回报文。但此时交易总耗时已超过 5s、超过服务调用超时时间,导致抛出超时异常。


由此,判断导致交易超时的原因不在消费方侧,而在提供方侧。

针对场景 2:提供方重启后大量交易超时

服务调用请求发起后,提供方迅速收到消费方的请求报文,但提供方未正常将交易报文递交给应用层,而是回复了 RST 报文,该笔交易超时失败。


观察在提供方重启后 1-2 分钟内出现大量的 RST 报文。通过部署脚本,在提供方重启后每隔 10ms 打印 established 状态的连接数,发现提供方重启后连接数未能迅速恢复到 7000,而是经过 1-2 分钟后连接数才恢复至正常数值。而在此过程中,逐台消费方上查询与提供方的连接状态,均为 established,怀疑提供方存在单边连接情况。

我们继续分别分析这两种异常场景。

场景 1:提供方实际交易前后均耗时长、导致交易超时


细化收集提供方的运行状态及性能指标:

1、在提供方服务器上每隔 3s 收集服务提供方 jstack,观察到 netty worker 线程每 60s 左右频繁处理心跳。

2、同时打印 top -H,观察到占用 CPU 时间片较多的线程排名前 10 中包含 9 个 netty worker 线程。因提供方服务器为 8C,Dubbo 默认 netty worker 线程数为 9 个,即所有 9 个 netty worker 线程均较忙碌。


3、部署服务器系统性能采集工具 nmon,观察到 CPU 每隔 60 秒左右产生毛刺;相同时间网络报文数也有毛刺。


4、部署 ss -ntp 连续打印网络接收队列、发送队列中的数据积压情况。观察到在耗时长的交易时间点附近队列堆积较多。


5、Dubbo 服务框架中提供方和消费方发送心跳报文(报文长度为 17)的周期为 60s,与以上间隔接近。结合网络抓包,耗时长的交易时间点附近心跳包较多。


根据 Dubbo 框架的心跳机制,当消费方数量较大时,提供方发送心跳报文、需应答的消费方心跳报文将会很密集。因此,怀疑是心跳密集导致 netty 线程忙碌,从而影响交易请求的处理,继而导致交易耗时增加。


进一步分析 netty worker 线程的运行机制,记录每个 netty worker 线程在处理连接请求、处理写队列、处理 selectKeys 这三个关键环节的处理耗时。观察到每间隔 60s 左右(与心跳间隔一致)处理读取数据包较多、耗时较大,期间存在交易耗时增加的情况。同一时间观察网络抓包,提供方收到较多的心跳报文。


因此,确认以上怀疑。心跳密集导致 netty worker 线程忙碌,从而导致交易耗时增长。



相关文章
|
4天前
|
Dubbo Java 应用服务中间件
实战指南:如何在Spring Boot中无缝整合Dubbo【四】
实战指南:如何在Spring Boot中无缝整合Dubbo【四】
48 0
|
4天前
|
Cloud Native Dubbo 应用服务中间件
【Dubbo3高级特性】「微服务云原生架构」带你从零基础认识搭建公司内部服务用户中心体系(实战指南-序章)
【Dubbo3高级特性】「微服务云原生架构」带你从零基础认识搭建公司内部服务用户中心体系(实战指南-序章)
66 0
|
4天前
|
Java fastjson 数据安全/隐私保护
【Dubbo3技术专题】「云原生微服务开发实战」 一同探索和分析研究RPC服务的底层原理和实现
【Dubbo3技术专题】「云原生微服务开发实战」 一同探索和分析研究RPC服务的底层原理和实现
49 0
|
4天前
|
XML Dubbo Java
【Dubbo3高级特性】「提升系统安全性」手把手教你如何通过令牌进行Dubbo3服务验证及服务鉴权控制实战指南(二)
【Dubbo3高级特性】「提升系统安全性」手把手教你如何通过令牌进行Dubbo3服务验证及服务鉴权控制实战指南
59 0
|
4天前
|
XML Cloud Native Dubbo
【Dubbo3高级特性】「提升系统安全性」手把手教你如何通过令牌进行Dubbo3服务验证及服务鉴权控制实战指南(一)
【Dubbo3高级特性】「提升系统安全性」手把手教你如何通过令牌进行Dubbo3服务验证及服务鉴权控制实战指南
56 1
|
4天前
|
Dubbo Cloud Native 应用服务中间件
【Dubbo3 终极特性】「云原生三中心架构」带你探索 Dubbo3 体系下的配置中心和元数据中心、注册中心的原理及开发实战(中)
【Dubbo3 终极特性】「云原生三中心架构」带你探索 Dubbo3 体系下的配置中心和元数据中心、注册中心的原理及开发实战(中)
32 1
|
4天前
|
存储 Dubbo 应用服务中间件
SpringCloud | Dubbo 微服务实战——注册中心详解
SpringCloud | Dubbo 微服务实战——注册中心详解
|
4天前
|
Dubbo Java 应用服务中间件
微服务学习 | Springboot整合Dubbo+Nacos实现RPC调用
微服务学习 | Springboot整合Dubbo+Nacos实现RPC调用
|
6月前
|
负载均衡 Dubbo 应用服务中间件
微服务技术系列教程(31) - Dubbo-原理及负载均衡分析
微服务技术系列教程(31) - Dubbo-原理及负载均衡分析
57 0
|
6月前
|
Dubbo Java 应用服务中间件
微服务技术系列教程(30) - Dubbo-SpringCloud与Dubbo区别
微服务技术系列教程(30) - Dubbo-SpringCloud与Dubbo区别
48 0