开工第一天,这个超时问题把我干趴下了!

简介: 开工第一天,这个超时问题把我干趴下了!

近日我司进行云服务商更换,恰逢由我负责新上线的三方调用 api 维护管理,在将服务由阿里云部署到腾讯云过程中,我们压测发现在腾讯云调用京东接口时 TP999 抖动十分剧烈,尽管业务层有重试操作但是超时依然较多,并不满足业务要求...... 接下来针对过程中发现的种种问题我们便踏上了优化之路。


开端



那还是普通的一夜,突然群里蹦出一些报警消息,多条业务线调用外部 api 超时,dubbo 线程池数量不足,还好很快服务恢复了正常,不过这也为我提了个大醒,我维护的服务作为业务调用的聚合出口,一旦服务发生异常将会导致很多业务方失败。尽管在压测过程中我们便知道了迁移云后的 api 调用可用性会有明显下降,但在 C 端业务还未迁移时便出了这么大影响确实是前期准备不足。


基于表面问题分析



出现问题先从最容易下手的地方开始解决,这种心理是好是坏?先分析问题,线程池飙高报警,结合日志、APM(skywalking) 工具进行排查,发现报警时刻线程数量和 cpu 均出现飙升情况,由于服务主要提供的功能就是三方调用,很多线程卡在调用三方 api 等待响应结果步骤上,并且有响应结果的调用消耗在 http 的时间也特别长,这就很容易理解了,是由于三方 api 抖动加之服务创建 http 连接过多先是导致应用响应缓慢,再之服务超时触发重试瞬间导致应用负载翻倍,进而加剧了服务缓慢问题。在不具备限流降级能力时服务一旦出现这种情况很容易导致雪崩,万幸没有太多业务损失,作为一个成熟的程序员总不能给自己留坑啊,赶紧来填坑!


多方位填坑



问题找到了,方案自然不缺了


  1. 修改 http 调用方式,引入 http 连接池

这个方案其实在之前压测过程中便考虑采用了,由于使用的三方 sdk 在 http 调用中均使用 java 原生的 HttpURLConnection ,这在接口高并发情况下不停创建连接,性能实在太差了。考虑团队内大家熟悉程度直接用 HttpClinet 覆盖三方 SDK 中的 HttpUtil 实现,稍加修改即可。修改好重新进行压测,TP999 指标、cpu 使用率均有明显下降,这波漂亮,投入产出 ++!


  1. 第一个方案就万事大吉了吗?支持请求超时分级,线程隔离

在第一个方案开发上线后我们又发现了新问题,业务侧超时情况依然明显!这个原因很容易想到,针对不同业务方我们只配置了一份超时配置,尽管部分业务方(主要是 C 端业务,对接口超时十分敏感)会提前超时然后触发重试,但是我的应用线程依然在阻塞请求,这是资源的浪费啊,仔细想想,之前的问题还是没有解决,在客户端不停重试下服务的 dubbo 线程岂不是还得爆了啊。再优化,这次我想到了请求分级,由于不同业务方对接口的响应时效要求不同,我们进行了连接池隔离,针对不同的业务方调用可以在调用时设置请求分级,我们大致分类下创建了三种分级 ‘FAST’,'STANDARD','SLOW',不同分级由服务提供者去配置使用不同超时方案。服务稳定性又进一步,问题再一次得到了解决。


这里还要提醒下大家 HttpClinet 使用过程中一般会配置连接池使用,切记搭配连接池使用时超时参数要配置三个,分别为


ConnectionRequestTimeout 获取连接池连接的超时时间(这个大家最容易忽略了)
ConnectTimeout 连接超时时间
SocketTimeout socket 读取超时时间
复制代码


  1. 合理应用重试(消费者重试)
    尽管在提供者服务上已进行代码优化,但是为了提升业务成功率,合理的使用重试也是很有必要的。此处要注意如果服务响应较慢千万避免消费者的多级重试,如果我们的整个业务调用链每一层都做了重试那么就会导致链路中响应慢的服务压力愈发增长,严重的引发重试风暴,直接压垮服务,所以合理设置重试也是很关键的一环,这里我们后续也要考虑引入熔断降级方案,避免意外发生。


在上述三招连环出击后,问题基本告一段落,2C4G 200 dubbo 线程,30 http 线程,吞吐量固定 1k,服务的 TP999 在压测过程中基本可以稳定在 500 毫秒以下,满足各方要求。


问题再起



伴随着应用接入量越来越大,我们的 C 端业务方又给提出了一个新问题,服务的超时情况怎么和阿里的服务差那么大啊(此处仅是指京东接口),由于是新业务直接上线到腾讯云,怀疑可能是我们服务的性能问题,这个在之前只有一些 B 端业务我确实没有过多注意,必须把这个问题好好查一查,还是从 APM 工具侧查看,果然,接口的 TP999 抖动十分剧烈,很多达到超时阈值,而 C 端业务十分重视这些指标,这也值得我们去学习,往往这些指标上线很容易暴露出根本问题,在高并发下看 TP90、TP99 时指标看起来还是挺正常的,那是因为超高请求量将响应时间给平均下去了。


纠结求解



这次的问题不再简单,面对这些 TP999 的超时响应,我们在观测了应用的整体流量、JVM 情况等等,愣是没有找到瓶颈,有之前阿里云的应用对比我们坚信问题是存在的,可能是在网络请求层面。接下来我们一步步出击。


0、查看 APM 工具发现部分 HTTP 请求确实超时,还有一部分是 HTTP 请求耗时不算长,但是从 APM 统计的调用链路来看耗费在提供者服务的时间比较长导致超时了。上述为两个问题,分别来看,请求可以确定是超时的我怀疑是不是由于使用了 http 连接池,池中的链接是不是超时了,从 httpclient 的日志中我分析了一下并没有这个问题,因为三方响应的 header 只返回了 keepalived,并没有返回其有超时时间。第二个问题我反复查找当时并没有找到原因,服务压力不大,也没有发生长耗时的 GC,实在不好解释这个问题,但是后来问题找到了,继续看结果在下文。


1、为了观察应用的请求响应信息,我们对 http 出口进行了抓包,通过对大量请求的抓包分析,我们找到了在响应比较高的时候抓包的 ip 中竟然有香港的 ip,为了验证这个问题,我们去百度了 dns 解析,发现该 ip 确实为该域名所有。


网络异常,图片无法展示
|


2、我们的服务器和出口 ip 都是北京的为什么 dns 解析出来的 ip 会返回香港的呢?带着问题我们求助了腾讯云官方,在官方问题排查过程中,我们又做了其他测试,在服务器上写了一个 python 小脚本定时进行指定域名的 dns 域名解析,果然在跑了一段时间后出现了几次解析结果为香港的 ip,狂喜。此时腾讯云官方也有了回应,由于京东自己搭建的 DNS 解析服务器,但是无法准确识别腾讯云的 ip 地域,导致偶尔会解析到香港,解决方案是他们推动京东去识别腾讯云的 ip。


网络异常,图片无法展示
|


3、等官方解决进度迟缓啊,我们能有什么临时的解决办法吗?纠结之时我们也接入了架构组为我们搭建的 kong 出口网关,有专门的 net 出口,更高的带宽,完善的 granfa 监控,结合监控请求抖时展现更明显了,于是我们想到了固定 host,更改 dns 方案,由于固定 host 风险太大了,我们采用了更改 dns 的方案尝试。原来机器上默认是腾讯云的 dns,我们分别更换为阿里的 dns 和 114 的 dns 进行了测试,测试结果是差距不大最终我们采用了阿里的 dns,在更换阿里的 dns 后效果明显,原来 TP999 的尖刺明显减少,观察 kong 日志也不存在香港的 ip 了,这里就有点诧异腾讯不是说和 dns 没关系吗,为什么换了别人家的 dns 情况就好了很多(这个问题的结果是明确的,但是原因目前还是停留在猜测阶段,猜测是 114 和阿里 dns 对此有优化,所以在该场景下优于腾讯 dns,若大家有方案可以验证此问题欢迎提出来哦)。


网络异常,图片无法展示
|


小插曲,kong 网关的 dns 解析器是写在 kong.conf 配置文件中的,如果未配置该项则会读取系统的 /etc/resolv.conf 文件,每次 kong 启动后会读取配置并缓存到内存中,如果启动 kong 后再修改系统的 nameserver 对 kong 是不管用的!还好我们之前有在专门的机器中测试 dns 更换效果,所以才敢肯定是 kong 配置问题,但是来回也折腾了不少时间才找到问题。

在这里我也想告诉大家,和别人协作,如果可以请一定准备好对比数据,避免他人因质疑而不配合,或者合作结果并不如预期时可以有个对照。


4、记得最开始有一个问题当时没找到原因吗,‘一部分 HTTP 请求耗时不算长,但是从 APM 统计的调用链路来看耗费在提供者服务的时间比较长导致超时了。’ 这个的问题最后还是 http 请求超时的原因,我对照了 kong 的日志和服务的 httpClient 日志,发现出现这种问题的请求有个共同点就是请求头很快接收到了,但是 body 迟迟未读取到然后触发超时了。skyWaling 中展示的 HTTP 耗时很短的原因是因为只要开始有响应就算请求结束了,然后为什么会有只返回 header 的情况呢?我 ping 了一下出现问题的 ip 是香港的,响应时间明显要比北京的慢,而且偶尔会丢包。这个问题解释通了。


终是踏平



经过又一轮的问题解决,测试加验证效果耗费了近两周时间,服务的可用性也提升了一个层次,算是一个小坑,不过这也让我们对 http 的整个请求流程做了很多梳理和二次认知,以上便是我在解决这个超时问题的整个解决路径和心路历程,感谢看我的叨叨叨,希望我们可以一起共同进步。

相关实践学习
通过轻量消息队列(原MNS)主题HTTP订阅+ARMS实现自定义数据多渠道告警
本场景将自定义告警信息同时分发至多个通知渠道的需求,例如短信、电子邮件及钉钉群组等。通过采用轻量消息队列(原 MNS)的主题模型的HTTP订阅方式,并结合应用实时监控服务提供的自定义集成能力,使得您能够以简便的配置方式实现上述多渠道同步通知的功能。
相关文章
|
Java Python Spring
spring + groovy 实现动态代码注入执行
spring + groovy 实现动态代码注入执行
5701 0
|
机器人 数据安全/隐私保护 Python
企业微信自动回复软件,企业微信自动回复机器人,python框架分享
企业微信机器人包含完整的消息处理流程,支持文本消息自动回复、事件处理、消息加密解密等功能
|
7月前
|
人工智能 边缘计算 自然语言处理
2025年中国数字人企业介绍与数字人技术新标准及选择指南
数字人技术正从辅助迈向核心生产力。2025年,行业聚焦提效、降本与多场景适配。五类平台覆盖创作、教育、IP打造等需求,助力内容生态进入务实新阶段。
|
云安全 安全 API
“安全体检”测评:安全自动化背后的隐忧与突破
本文围绕阿里云安全检查服务展开,从技术深度、场景适配和安全边界三个维度分析其价值与短板。该服务定位为自动化风险治理工具,涵盖漏洞扫描、合规基线和配置修复。体验中发现,其优势在于云原生体系耦合、资源拓扑感知及成本效益;不足则体现在量化指标缺失和攻击面覆盖有限。改进建议包括优化风险排序、引入AI分析及提供场景化助手。文章总结,该产品在基础风险治理和合规提效上表现良好,但需强化自动化修复与业务场景适配能力,以实现从工具到平台的跃迁。
614 65
|
人工智能 自然语言处理 搜索推荐
AI赋能教育与阿里云通义千问的结合
本简介介绍了AI技术如何赋能教育行业,结合阿里云“通义千问”大模型,助力海豚大数据及人工智能实验平台实现个性化教学、智能答疑与资源优化,推动高校与企业人才培养模式革新,构建终身学习生态体系。
844 1
|
数据采集 编解码 数据可视化
空间单细胞|10x Visium数据分析、可视化与整合(1)
空间单细胞|10x Visium数据分析、可视化与整合(1)
|
存储 人工智能 自然语言处理
拥抱Data+AI|B站引入阿里云DMS+X,利用AI赋能运营效率10倍提升
本篇文章针对B站在运营场景中的痛点,深入探讨如何利用阿里云Data+AI解决方案实现智能问数服务,赋能平台用户和运营人员提升自助取数和分析能力,提高价值交付效率的同时为数据平台减负。
拥抱Data+AI|B站引入阿里云DMS+X,利用AI赋能运营效率10倍提升
|
存储 JavaScript 算法
JS垃圾回收机制有哪些?
本文介绍了JavaScript中的垃圾回收(GC)机制,包括其概念、产生原因及重要性。文章详细讲解了几种常见的垃圾回收算法,如引用计数、标记清除、标记整理和分代回收,并分析了它们的优缺点。最后总结了垃圾回收对JS开发的重要作用,强调了其在自动内存管理和性能优化中的关键地位。
802 2
JS垃圾回收机制有哪些?
|
存储 数据可视化 Python
使用Python实现个人财务管理工具
本文介绍如何使用Python实现一个简单的个人财务管理工具,包括记录支出和收入、生成财务报告和数据可视化等功能。通过命令行界面输入数据,计算总支出、总收入和净收入,并使用Matplotlib库进行数据可视化。
1251 2
|
存储 数据采集 Java
Spring Boot 3 实现GZIP压缩优化:显著减少接口流量消耗!
在Web开发过程中,随着应用规模的扩大和用户量的增长,接口流量的消耗成为了一个不容忽视的问题。为了提升应用的性能和用户体验,减少带宽占用,数据压缩成为了一个重要的优化手段。在Spring Boot 3中,通过集成GZIP压缩技术,我们可以显著减少接口流量的消耗,从而优化应用的性能。本文将详细介绍如何在Spring Boot 3中实现GZIP压缩优化。
2266 6