热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Qunar大讲堂:深入解析问题排查与解决方案

近日,技术学院负责人委托我负责维护包括大讲堂和积分管理系统在内的几个平台。尽管这些系统的功能已经相当成熟且不再进行新功能的开发,但大讲堂系统自上线以来,每隔一段时间就会出现故障,影响了学员的学习体验。为了解决这一问题,我们将从多个角度深入分析其原因,并探讨有效的解决方案。

1. 问题背景

前不久技术学院负责人让我帮助维护下⼤讲堂、积分管理等⼏个系统。这些系统功能都已经很稳定,也不会再有新的功能开发,但是⼤讲堂系统自上线后,每过⼀段时间就会出错,导致学员⽆法报名课程,希望我帮助解决下。这种累积下来的问题解决起来⽐较难,但是对能⼒提升帮助很大,我欣然接受了,所以就有了这次“艰苦”的问题排查和解决之旅。

2. 解决思路

本人未参加过大讲堂和积分系统的开发,解决问题⾸先要最⼤化的了解系统背景、问题发⽣时的系统表现等信息。技术学院的同事和我说,负责系统的开发⼈员已经换过⼏波了,现在基本已经找不到了解系统的开发⼈员了,但是也反馈了以下信息:

1、系统是16年公司应届⽣培训时做的项⽬。2、其他系统运⾏良好,就是⼤讲堂系统偶尔会报错,导致学员⽆法报名,重启下就好了,果然是“重启⼤法”好啊。3、系统出错的频率不⾼,但是貌似很有规律,⼤半个⽉左右出现⼀次。根据以上描述,特别是出错后“重启⼤法”特别有效,出错频率基本固定,通过这两点基本上可以断定是资源泄露导致的问题。既然确定是资源泄露问题,对于 Java 应⽤来说排查⽅向也就确定为以下2个⽅向:1、对象泄露2、线程泄露

3. 处理过程

前文提过本人并未参与项目开发,所以整个排查大部分是通过 linux 和 jvm 的⼀些命令行辅助功能来进行的,下面是整个排查过程:1、 首先通过 jps 确定 Java 应用的进程 idsudo -u tomcat jps -lv | grep qtscore

2、 排查内存泄露

通过持续观察 GC 日志文件 /home/q/www/qtscore/log/gc.log 文件,发现 GC 执行频率正常,特别是 Full GC 执行也并不频繁,虽然内存使用量在持续增长,但是并不明显。

为了确认业务代码是否存在泄漏,通过 jmap 查看了堆内对象分布情况,切记此命令会导致进程暂停,如果是 qps 高或者响应时间要求高的应用慎用:sudo -u tomcat jmap –F -histo 11035

这里只截取了⼀部分,内存占用量和数量靠前的并无业务代码。到这⼀步,基本初步排除内存泄露的可能性。

3、 排查线程泄露

top -H -p 11035

通过结果可以看出线程已经高达4038,应用中dubbo线程池默认配置是200个线程,tomcat线程池配置也是200个线程,所以这个线程数明显不合理。参照另外一个同等应用,其线程数未超过500,所以可以初步判断系统存在线程泄露,下⼀步只能查看线程栈信息了:

sudo -u tomcat jstack -l 11035 > /tmp/qtscore_stack.log

系统中存在100多个“New I/O boss"线程,这个应该是 netty 线程池的 boss 线程,到这里基本上可以确认是线程池泄露引起的问题了,但是究竟是哪段代码引起的,线程栈中并无业务相关代码,只是 netty 线程池的代码,所以无法判断出引起问题的代码源头,只能先看看系统日志中是否有价值的信息了,发现系统日志中频繁报以下错误:

图片

找到对应的源代码进行查看,发现这是⼀个 dubbo 服务接口,而 dubbo 底层用的就是 netty,种种迹象表明问题应该就出在这里。仔细分析代码后,发现这个 dubbo 接口抛出的异常 QtalkQueryException,居然没有通过 api 暴露给调用方,也就是说调用方是无法正确反序列化这个异常的。初步推测可能就是这个原因导致 dubbo 未能正确处理线程池,导致线程池泄露了。将 QtalkQueryException 改为抛出 IllegalStateException 异常,发布上线,满怀期待地等着问题被完美解决。过了一个星期后,通过 top 命令查看进程的线程数,发现线程数又飙升到1千1百多了,看来问题还是没有解决,只能再排查了,但是基本上可以确定是线程泄露问题,而且是 netty 引起的,可是线程栈中 netty 的 worker 线程栈中没有任何业务相关的代码,应该是代码间接用到了 netty 线程池,但是一时没有了头绪。只有找同事咨询一下了,和几个同事讨论后,大家都认为最有可能用到线程池的就是异步请求,特别是一些HTTP客户端,根据这个思路对代码进行排查后,发现系统中有如下代码:

图片

这个 com.ning.http.client.AsyncHttpClient 底层用到了 netty 线程池,这个用法存在明显错误,AsyncHttpClient 实例应该重用,而不应该每次使用时都创建一个。修改代码后重新发布上线,一周后再统计应用线程数,发现线程数稳定在350个左右,确认问题得到了解决。但是故事还没有结束,个人觉得既然应用报错,日志应该有所体现才对,难道是被其他异常淹没了?所以重新排查了出错日期的日志,果然发现了以下错误信息:

图片

通过系统命令  ulimit –a 发现系统最大用户线程数是4096,所以问题是创建的线程超过了系统最大用户线程数限制。

图片

4. 经验总结

回顾这次问题排查经历,其实这个问题排查起来并不难,最初的排查方向也是对的,但是整个过程还是花费了很长时间。回顾整个过程,总结出以下经验和教训:

  1. 大规模使用的基础组件(例如:Dubbo)不容易有问题,即使有问题也会被及时修复,所以还是要多分析自己编写的代码。

  2. 排查问题首先要仔细分析系统日志,报错的地方⼀般也就是引起问题的源头,遵循和重视这个原则,通常可以大大提高排查问题的效率。



推荐阅读
  • 成都服务器租赁适用于哪些网站业务部署——Vecloud专业解析
    成都,作为四川省的省会,不仅是西南地区唯一的副省级城市,也是国家重要的高新技术产业基地和商贸物流中心。Vecloud专业解析指出,成都服务器租赁服务特别适合各类网站业务的部署,尤其是需要高效、稳定和安全的在线应用。无论是电子商务平台、内容管理系统还是大数据分析,成都的服务器租赁都能提供强大的支持,满足不同企业的需求。 ... [详细]
  • 《村夜》译文与原文赏析:宋代诗人陆游的乡村夜景诗作解析 ... [详细]
  • CSS伪类详解:定义与应用
    本文将深入解析CSS伪类的定义及其应用场景。CSS伪类通过为已存在的元素在特定状态下添加特殊样式,能够动态响应用户的交互行为,从而提升网页的视觉效果和用户体验。 ... [详细]
  • 在数字图像处理中,Photoshop 的直方图是一个重要的工具,它能够精确地反映图像中不同亮度级别的分布情况。通过分析直方图,用户可以深入了解图像的曝光、对比度和色调范围,从而进行更精细的调整。直方图不仅模拟了物体表面反射光线的原理,还能帮助摄影师和设计师更好地掌握图像的明暗细节,优化视觉效果。 ... [详细]
  • 深入浅出:PHP 中的 unset() 函数解析与应用
    本文深入解析了 PHP 中的 `unset()` 函数,详细介绍了其功能和应用场景。`unset()` 函数用于释放指定的变量,语法格式为 `void unset(mixed $var[, mixed $var[, ...]])`。通过具体示例,文章展示了如何在实际开发中有效使用 `unset()` 来管理内存和变量状态,帮助开发者提高代码效率和程序性能。 ... [详细]
  • 如何在您的计算机上配置Python和PyCharm开发环境
    本文详细介绍了在Windows 10系统上配置Python和PyCharm开发环境的步骤。内容包括Python的安装与卸载、PyCharm的安装与卸载,以及如何在Windows 10中通过双击安装文件“python-3.7.2-amd64.exe”来完成Python的安装。此外,还提供了关于环境变量配置和基本设置的实用建议,帮助用户快速搭建高效的开发环境。 ... [详细]
  • 2020年美国流感病例显著下降,创历史新低水平
    在2020年10月至2021年5月期间,美国的流感感染率降至自1997年以来的历史最低点。全球范围内报告的流感病例也极为罕见,专家们普遍认为,这一现象主要归因于为防控COVID-19而广泛采取的公共卫生措施,如佩戴口罩、保持社交距离和加强个人卫生等,这些措施有效抑制了流感病毒的传播。 ... [详细]
  • Java排序算法详解:选择排序、插入排序、冒泡排序与递归实现
    本文详细解析了Java中的几种基础排序算法,包括选择排序、插入排序和冒泡排序,并探讨了递归在这些算法中的应用。选择排序通过每次找到未排序部分的最小值并将其置于已排序部分的末尾来实现;插入排序则通过逐步将每个元素插入到已排序序列的正确位置;而冒泡排序则是通过多次遍历数组,两两比较并交换相邻的元素,最终使较大的元素逐渐“冒”到数组末尾。文章还提供了具体的代码示例,帮助读者更好地理解和掌握这些算法的实现细节。 ... [详细]
  • 本文深入探讨了Java多线程环境下的同步机制及其应用,重点介绍了`synchronized`关键字的使用方法和原理。`synchronized`关键字主要用于确保多个线程在访问共享资源时的互斥性和原子性。通过具体示例,如在一个类中使用`synchronized`修饰方法,展示了如何实现线程安全的代码块。此外,文章还讨论了`ReentrantLock`等其他同步工具的优缺点,并提供了实际应用场景中的最佳实践。 ... [详细]
  • 斯坦福大学公开课:利用神经网络技术实现自动驾驶的案例分析
    斯坦福大学的公开课深入探讨了如何利用神经网络技术实现自动驾驶。课程中通过实例展示了汽车如何通过学习算法自主驾驶。具体而言,课程展示了一幅图解,其中左下角显示了汽车前方的实时路况图像,而左上角则呈现了一个水平的菜单栏,用于展示系统处理和决策的过程。这一案例详细解析了神经网络在自动驾驶中的应用,为学生提供了宝贵的实践参考。 ... [详细]
  • 如何在Windows 10中彻底禁用用户账户控制弹窗
    如何在Windows 10中彻底禁用用户账户控制弹窗 ... [详细]
  • 《唐姚合诗作〈买太湖石〉的翻译与原文赏析》 ... [详细]
  • 这是一道涉及数学计算的问题。假设步行速度为 \(a\),车速为 \(b\),总距离为 \(c\)。Teddy 的步行时间为 \(T_1\),WhereIsHeroFrom 的步行时间为 \(T_2\),总时间为 \(T\)。通过分析不同时间段内的速度变化,可以得出最优的车辆使用策略,以最小化总的旅行时间。具体来说,需要计算在不同情况下步行和乘车的时间分配,以确保整体效率最大化。 ... [详细]
  • 在安装并配置了Elasticsearch后,我在尝试通过GET /_nodes请求获取节点信息时遇到了问题,收到了错误消息。为了确保请求的正确性和安全性,我需要进一步排查配置和网络设置,以确保Elasticsearch集群能够正常响应。此外,还需要检查安全设置,如防火墙规则和认证机制,以防止未经授权的访问。 ... [详细]
  • 《唐耿湋〈晚秋东游寄猗氏与解县二位明府〉译文及原文赏析》 ... [详细]
author-avatar
hareleemu_699
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有