记一次故障的处理的心得

背景

三个时间点:

  • 中午1点多收到拨测告警邮件和短信
  • 下午5点多收到拨测告警邮件和短信
  • 第二天早上5点多收到拨测告警邮件和短信

追查故障原因

排查方向

应用日志

查询应用日志的报错信息,抓到可疑点的信息 ,多关注重复打印的报错日志,例如NPE异常或者ERROR日志。

ps -ef|grep keyword
less -i file
cat file |grep --color=auto

应用堆栈信息

关注waiting和blacking状态的线程,线程和内存都被谁占用着。

1.top查找出哪个进程消耗的cpu高。执行top命令,默认是进程视图,其中PID是进程号
21125 co_ad2    18   0 1817m 776m 9712 S  3.3  4.9  12:03.24 java                                                                                           
5284 co_ad     21   0 3028m 2.5g 9432 S  1.0 16.3   6629:44 ja
这里我们分析21125这个java进程
2.top中shift+h 或“H”查找出哪个线程消耗的cpu高 
先输入top,然后再按shift+h 或“H”,此时打开的是线程视图,pid为线程号
21233 co_ad2    15   0 1807m 630m 9492 S  1.3  4.0   0:05.12 java                                                                                           
20503 co_ad2_s  15   0 1360m 560m 9176 S  0.3  3.6   0:46.72 java                                                                                           

这里我们分析21233这个线程,并且注意的是,这个线程是属于21125这个进程的。 

3.使用jstack命令输出这一时刻的线程栈,保存到文件,命名为jstack.log。注意:输出线程栈和保存top命令快照尽量同时进行。  由于jstack.log文件记录的线程ID是16进制,需要将top命令展示的线程号转换为16进制。4. jstack查找这个线程的信息 
jstack [进程]|grep -A 10 [线程的16进制] 
即: jstack 21125|grep -A 10 52f1  

-A 10表示查找到所在行的后10行。21233用计算器转换为16进制52f1,注意字母是小写。 
结果: 
 
"http-8081-11" daemon prio=10 tid=0x00002aab049a1800 nid=0x52bb in Object.wait() [0x0000000042c75000]  
   java.lang.Thread.State: WAITING (on object monitor)  
     at java.lang.Object.wait(Native Method)  
     at java.lang.Object.wait(Object.java:485)  
     at org.apache.tomcat.util.net.JIoEndpoint$Worker.await(JIoEndpoint.java:416)  
在结果中查找52f1,可看到当前线程在做什么。

数据库排查

  • 查看数据库服务的负载情况
  • 进入数据库查询当前链接正在惊醒的sql语句,关注执行时间
  • 排查数据库锁的情况和回滚的情况
--根据threadid查询详细信息
select * from information_schema.innodb_TRX where trx_mysql_thread_id= 26986562;
select * from information_schema.processlist where Info like '%biz_device_message%';
--查询长时间sql
select * from information_schema.processlist where COMMAND <> 'sleep' and time > 100;
select * from information_schema.processlist where COMMAND <> 'sleep' and time > 100 and info like 'alter%';
--查询从库状态
show slave status;
start slave;
stop slave;
--mysql数据导出/导入
mysqldump -u 用户名 -p 数据库名 表名> 导出的文件名
mysqldump -u root -p -q -e -t  intelligent-family biz_device_message > biz_device_message20201231.sql  
source dn_location2.sql  

解决方案

解决思路

从业务上考虑是否可以简单粗暴,先让服务恢复正常,咨询产品后确认只保留一个月的消息记录信息即可

临时方案

新建临时表,将老表数据最新的1个月的数据导入到新表中,修改代码逻辑,批量替换成新表进行查询业务。

永久方案

存到es中
建立从库,主从分离
API网关加入自定义路由规则,增加限流配置方案

结论

工欲善必先利其器

命令行
kafka工具配置

kafkaTools

平时多积累,关键时刻可以用上

系统学习多线程知识
数据库
架构、解耦合的知识、设计模式

常用框架源码

扩展、改造成适合自己的

定位问题原因* 根据原因思考问题解决方案* 实践验证方案有效性* 提交验证结果
原文地址:https://www.cnblogs.com/jimoliunian/p/14230897.html