记一次最近生产环境项目中发生的两个事故及处理方法


前言

  年前放假的几个月内,公司项目发生了两次事故,虽然与我无关,但事故发生后整个团队都受到影响,主管需要给客户写事故报告,客户甚至打电话给公司领导严肃批评,我想经历过这种事的朋友不在少数,但很多刚入行的朋友可能不太清楚其中利害,这里我分享出来希望对大家有所帮助。


事故经过

  三个月内一共发生两次生产环境事故,一个是接口超时导致服务雪崩,一个是锁表导致核心功能停滞一小时。


1、接口超时事故

1)、现象

  2021年12月某周一上午,负责管理网络的同事(俗称网管)一大早巡检过程中发现有一个服务挂掉了,他当时没在意,直接重启就好了,但到了10点左右,忽然三四个服务:挂号服务、门诊服务、检查报告服务等一起挂掉了,而且重启十几分钟后又会挂掉,瞬间公司就炸锅了,网管、开发人员、技术主管集体冒汗,在紧急处理过程中,还不断有院方电话打给主管、总经理直到大老板,领导就站在我们背后着急的等待我们处理,我想很多人应该有画面了。

2)、原因

  大概到中午都没解决,因为没有日志平台的情况下,定位问题是一件不容易的事情,后来在中午休息时间技术主管和我们终于发现了门诊服务中调用某软his接口出现超时,而周一上午的流量又很大,平常偶尔超时也没问题没人在意,这次一个小小的接口超时竟然直接把服务全部堵塞,调用该接口的挂号和门诊服务全部挂掉,而和门诊服务有一点耦合的检查报告服务也在疯狂的超时等待又超时又等待中挂掉了。

  最终,紧急联系院方找厂商服务团队查找该接口问题,同时我们临时把几个服务全部重启,总算在所有人惶惶不安的努力下3点之前恢复了正常。

3)、总结及处理

  事后,老板大发雷霆,并召开批斗大会点出了团队没有危机处理预案等等种种问题,据说是被院方碉堡了。我们怀着谦虚忐忑的心情在小本上疯狂做笔记(做样子),算是挺过去了,唯独主管比较难受,要亲自写好几个事故报告给甲方,懂的都懂。

  接口超时时间之后发现设置为60秒,真特么离谱啊,之前竟没一个人关注(包括我),没问题的情况下自然万事大吉,但凡出了问题,60秒的超时时间这是人干的事么,有什么接口若需要60秒,那本身就是一枚定时炸弹,必须一开始就拆掉。

  很多公司的项目其实都存在这个问题,碍于调用第三方接口难以预估超时时间,所以就设置的比较长,可实际上,这会给项目带来莫大的隐患,处理方式很简单:

  i)、一定要和对接的厂商确定接口的大概超时时间,有个基本的范围,因为你很难要求其他公司给你做好接口的完善,很多是不会搭理你的,你也看不见人家接口怎么写的,那么就要知道个大概,然后自己这边才好设置;

  ii)、在预估项目上线后流量会成倍增长的情况下,一定要对项目主要接口做压测,这是公司的测试团队必须要做的事情,我们公司这次就是测试人员不会压测,也没人重视,所以功能没问题就上线了,事后所有测试人员都被要求参加压测培训;

  iii)、只要是微服务,请一定引入熔断机制 ,这次事故过后,团队深刻反思,明明用了SpringCloud,但调用第三方接口的位置都没有做熔断处理,如果一开始做了,那么这次事故至少我们可以抽身,服务熔断降级后,既不会出现雪崩影响到其他服务,主要责任也在某软,给自己公司更多弹性处理的空间,而不是现在反而担负了主要责任。


2、锁表事故

1)、现象

  这个事故和前面的相比算是小事故了,但依然令人心惊胆战,毕竟快过年了,谁也不想出问题。墨菲定律讲过,越是你害怕的事情越是会到来,果不其然,年前大概就是前一两周的样子,某天下午一家三甲医院的挂号服务未响应,在前端的效果就是,你打开了小程序,点击了挂号服务,然后某个功能一直加载中,最后页面未响应或假死。

2)、原因

  锁表,因为负责维护该医院的同事,在下午四点中的时候给挂号表新增了一个可以为空的字段,而挂号表是百万数据的大表,直接执行SQL新增字段还附带部分条件,直接导致整个表都锁掉了,前端发来的请求就一直无法对该表执行其他操作,最终未响应及假死。

  既然锁了就要解,操作很简单,但集成同事刚好一时联系不上,开发人员又不熟悉内网环境,前后花了一个小时时间才解锁恢复正常,在一堆病患使用过程中,一个小时时间内都无法挂号,这背后的凶残你可想而知。

3)、总结及处理

  给该表迅速解锁,有条件的话最好让本公司专业DBA或集成同事来操作,他们更熟悉数据库服务及项目部署,操作更安全,如果公司没有这样的同事,只能百度一下咯。



MySQL解锁方式:

# 1. 查看当前数据库锁表的情况 
SELECT * FROM information_schema.INNODB_TRX; 
# 2. 杀掉查询结果中锁表的trx_mysql_thread_id 
kill trx_mysql_thread_id

Oracle解锁方式:

# 查看被锁的表ct
select b.owner, b.object_name, a.session_id, a.locked_mode
from v$locked_object a, dba_objects b where b.OBJECT_ID = a.OBJECT_ID

# 查看连接的进程
select sid, serial#, username, osuser from v$session;

# 杀掉进程 sid, serial#
alter system kill session '678,983';

切记,给大表新增字段以及其他操作,一定要选择流量最小的时间段,比如凌晨以后,这样可以避免造成生产环境事故。


总结

1)、首先,接口超时时间的设置不是小问题,希望大家引以为戒,一是要充分和对接厂商沟通,对接口情况有底,一个接口的响应时间理论上是毫秒级的,大厂甚至对接口超时时间都有明确规范,小厂因为身不由己,只能曲线救国,设置一个合理的范围;

    其次,一定要在测试阶段进行核心接口的压测,某种程度上可以提前暴露问题;

    最后,微服务一定要引入熔断机制,并且重视使用;

2)、大表操作要谨慎,要么选择合适的工具来实时操作大表(可以百度非常多),要么就选择流量最少的时间去操作,无非也就是凌晨,因为没啥人用,而且执行SQL操作大表时最好不要附带条件比如设置默认值之类的,这样会明显提升速度,把复杂的语句分段执行效果更佳,大家可以试试。



  本人文章从来都是纯手打,且都来自实际工作中的经验及分享,如果觉得有一滴滴帮助,就点个推荐吧!(o..o)~


其他文章推荐
Springboot+Redisson自定义注解一次解决重复提交问题(含源码):https://www.cnblogs.com/fulongyuanjushi/p/15883067.html


posted @ 2022-02-06 18:30  程序员济癫  阅读(7339)  评论(65编辑  收藏  举报