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

线上_Dubbo项目线上案例解析

本文由编程笔记#小编为大家整理,主要介绍了Dubbo项目线上案例解析相关的知识,希望对你有一定的参考价值。
本文由编程笔记#小编为大家整理,主要介绍了Dubbo项目线上案例解析相关的知识,希望对你有一定的参考价值。







本节介绍笔者在工作和实践中遇到的两起事故案例,可通过这两个案例了解到解决问题的方法。对于更多的线上事故解决方法和步骤,可以参考《分布式服务架构:原理、设计与实战》第6章的内容。



线上问题的通用解决方案


1.发现问题


发现问题通常通过自动化的监控和报警系统来实现,线上游戏服搭建了一个完善、有效的日志中心、监控和报警系统,通常我们会从系统层面、应用层面和数据库层面进行监控。

对系统层面的监控包括对系统的CPU利用率、系统负载、内存使用情况、网络I/O负载、磁盘负载、I/O等待、交换区的使用、线程数及打开的文件句柄数等进行的监控,一旦超出阈值,就需要报警。

对应用层面的监控包括对服务接口的响应时间、吞吐量、调用频次、接口成功率及接口的波动率等进行的监控。

对资源层的监控包括对数据库、缓存和消息队列的监控。我们通常会对数据库的负载、慢SQL、连接数等进行监控;对缓存的连接数、占用内存、吞吐量、响应时间等进行监控;并对消息队列的响应时间、吞吐量、负载、积压情况等进行监控。




2.定位问题

定位问题时,首先要根据经验来分析,如果应急团队中有人对相应的问题有经验,并确定能够通过某种手段进行恢复,则应该第一时间恢复,同时保留现场,然后定位问题。

应急人员在定位过程中需要与业务负责人、技术负责人、核心技术开发人员、技术专家、架构师、运营人员和运维人员一起,对产生问题的原因进行快速分析。在分析的过程中要先考虑系统最近的变化,考虑如下问题。



  • 问题系统最近是否进行了上线?


  • 依赖的基础平台和资源是否进行了上线或者升级?


  • 依赖的系统最近是否进行了上线?


  • 运营人员是否在系统里做过运营变更?


  • 网络是否有波动?


  • 最近的业务是否上量?


  •  服务的使用方是否有促销活动?





3.解决问题

解决问题的阶段有时处于应急处理中,有时处于应急处理后。在理想情况下,每个系统都会对各种严重情况设计止损和降级开关,因此在发生严重问题时先使用止损策略,在恢复问题后再定位和解决问题。解决问题要以定位问题为基础,必须清晰地定位问题产生的根本原因,再提出解决问题的有效方案,切记在没有明确原因之前,不要使用各种可能的方法来尝试修复问题,这样可能导致还没有解决这个问题又引出另一个问题。



4.消除影响

在解决问题时,某个问题可能还没被解决就已恢复,在任何情况下都需要消除问题带来的影响。



  • 技术人员在应急过程中对系统做的临时性改变,若在后面证明是无效的,则要尝试恢复到原来的状态。


  • 技术人员在应急过程中对系统进行的降级开关操作,在事后需要恢复。


  • 运营人员在应急过程中对系统做的特殊设置如某些流量路由的开关,在事后需要恢复。


  • 对使用方或者用户造成的问题,尽量采取补偿的策略进行修复,在极端情况下需要一一核实。


  • l对外由专门的客服团队整理话术,统一对外宣布发生故障的原因并安抚用户,话术要贴近客观事实,并从用户的角度出发。



在详细了解如何发现问题、定位问题、解决问题和消除造成的影响后,接下来让我们看看在实际情况下如何应用。


首先,找运维看日志。如果在日志监控系统中有报错,则能很好地定位问题,我们只需根据日志报错的堆栈信息来解决问题即可。如果在日志监控系统中没有任何异常信息,就得保存现场了。


其次,保存现场并恢复服务。在日志系统中找不到任何线索的情况下,我们需要赶紧保存现场快照,并尽快恢复服务,以达到最大程度止损的目的。在JVM中保存现场快照通常包括保存当前运行线程的快照和保存JVM内存堆栈快照。如下所述。


(1)保存当前运行线程的快照,可以使用jstack [pid]命令实现,在通常情况下需要保存三份不同时刻的线程快照,时间间隔为1~2分钟。

(2)保存JVM内存堆栈快照,可以使用jmap –heap、jmap –histo、jmap -dump:format=b、file=xxx.hprof等命令实现。


快速恢复服务的常用方法如下:

(1)隔离出现问题的服务,使其退出线上服务,便于后续的分析处理。

(2)尝试快速重启服务,第一时间恢复系统,而不是彻底解决问题。

(3)对服务降级处理,只使用少量的请求来重现问题,以便我们全程跟踪观察,因为之前可能没太注意这个问题是如何发生的。

通过上面的一系列操作后,要分析日志并定位问题。这一步很关键,也需要有很多实战经验,需要先查看服务器的“当前症状”,才能进一步对症下药。下面提供从服务器的CPU、内存和I/O三方面查看症状的基本方法。


查看CPU或内存情况的命令如下:

l   top:查看服务器的负载状况。

l   top+1:在top视图中按键盘数字“1”查看每个逻辑CPU的使用情况。

l   jstat –gcutil pid:查看堆中各内存区域的变化及GC的工作状态。

l   top+H:查看线程的使用情况。

l   ps -mp pid -o THREAD,tid,time | sort -rn:查看指定进程中各个线程占用CPU的状态,选出耗时最多、最繁忙的线程id。

l   jstack pid:打印进程中的线程堆栈信息。

判断内存溢出(OOM)方法如下。

l   堆外内存溢出:由JNI的调用或NIO中的DirectByteBuffer等使用不当造成。

l   堆内内存溢出:容易由程序中创建的大对象、全局集合、缓存、ClassLoader加载的类或大量的线程消耗等造成。

l   使用jmap –heap命令、jmap –histo命令或者jmap-dump:format=b,file=xxx.hprof等命令查看JVM内存的使用情况。


分析I/O读写问题的方法如下。

l   文件I/O:使用命令vmstat、lsof –c -ppid等。

l   网络I/O:使用命令netstat –anp、tcpdump -i eth0 ‘dst host 239.33.24.212’ -w raw.pcap和wireshark工具等。

l   mysql数据库:查看慢查询日志、数据库的磁盘空间、排查索引是否缺失,或使用show processlist检查具体的SQL语句情况。

最后,在Hotfix后继续观察情况。在测试环境或预生产环境修改测试后,如果问题不能再复现了,就可以根据公司的Hotfix流程进行线上的Bug更新,并继续观察。如果一切都正常,就需要消除之前可能造成的影响。




耗时服务耗尽了线程池的案例

有一次,我们线上的某个Web服务访问报HTTP 500错误,在查看log日志时报异常,异常的关键信息如下:

Caused by:java.util.concurrent.RejectedExecutionException: Thread pool is EXHAUSTED!Thread Name: DubboServerHandler-172.31.24.215:20880, Pool Size: 200 (active:200, core: 200, max: 200, largest: 200), Task: 3622292 (completed: 3622092),Executor status:(isShutdown:false, isTerminated:false, isTerminating:false), indubbo://172.31.24.215:20880!

我们并没有手动设置过服务端线程池的大小,默认使用200,从报错日志来看,明显是服务端的线程池被用光了。

接下来使用jstack pid打印进程中的线程堆栈信息,确实有200个Dubbo线程在不断地执行,Dubbo线程的命名格式为:DubboServerHandler-192.168.168.101:20880-thread-num。


为什么突然有这么多线程不断执行呢?是用户量突然增大了,还是有爬虫攻击?带着这些问题,笔者查看了网络流量监控,并未发现有明显的流量突增。

我们通过日志和监控暂时没有发现问题的成因,就添加了些日志,添加了请求时长打印,也增加了服务端的线程数。问题依然存在,不过可以排除服务端的线程数设置的问题了。

最后,通过新添加的日志打印发现,服务的请求时间普遍很长,这引起了我们的注意,顺着该线索找下去,才发现是服务调用数据库的时间太长,所以最后定位为数据库的问题。

在定位为是数据库执行慢导致很多线程占用不释放后,我们开始查看MySQL慢查询日志。由于之前慢查询的阀值时间被设置为1秒,所以在慢查询日志中没有任何记录;然后使用show processlist查看SQL的执行情况,发现有一条SQL语句占用的时间较长;最后,修改慢查询的时间为500毫秒,并记录下相关的慢查询SQL语句。

我们采取的解决方法为:为慢查询语句添加索引并修改逻辑代码,恢复之前的修改。通过查看codereview相关的代码,我们发现有部分业务逻辑在for循环中多次查询数据库,便将其修改为一次查询多条数据,然后在for循环中使用。


-----------------------------------------------------------------------------------












Dubbo项目线上案例解析







如对分布式缓存有进一步阅读欲望,推荐本号作者总策划和合著的新书。

《深入分布式缓存》



购书请点击查看原文。


推广活动:评论区点赞多的前三名可获得《可伸缩服务架构:框架与中间件》,如果文章阅读量超过5000,还有神秘奖项--挑选评论最走心者送出作者签名版《深入分布式缓存》。


声明:

封面图片由张逸大师提供,公子张子瞻拍摄于动物园。


推荐阅读
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Oracle Database 10g许可授予信息及高级功能详解
    本文介绍了Oracle Database 10g许可授予信息及其中的高级功能,包括数据库优化数据包、SQL访问指导、SQL优化指导、SQL优化集和重组对象。同时提供了详细说明,指导用户在Oracle Database 10g中如何使用这些功能。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 本文详细介绍了MysqlDump和mysqldump进行全库备份的相关知识,包括备份命令的使用方法、my.cnf配置文件的设置、binlog日志的位置指定、增量恢复的方式以及适用于innodb引擎和myisam引擎的备份方法。对于需要进行数据库备份的用户来说,本文提供了一些有价值的参考内容。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 解决VS写C#项目导入MySQL数据源报错“You have a usable connection already”问题的正确方法
    本文介绍了在VS写C#项目导入MySQL数据源时出现报错“You have a usable connection already”的问题,并给出了正确的解决方法。详细描述了问题的出现情况和报错信息,并提供了解决该问题的步骤和注意事项。 ... [详细]
  • 本文详细介绍了MySQL表分区的创建、增加和删除方法,包括查看分区数据量和全库数据量的方法。欢迎大家阅读并给予点评。 ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
author-avatar
那一年2502931247
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有