前言
年前放假的幾個月內,公司專案發生了兩次事故,雖然與我無關,但事故發生後整個團隊都受到影響,主管需要給客戶寫事故報告,客戶甚至打電話給公司領導嚴肅批評,我想經歷過這種事的朋友不在少數,但很多剛入行的朋友可能不太清楚其中利害,這裡我分享出來希望對大家有所幫助。
事故經過
三個月內一共發生兩次生產環境事故,一個是介面超時導致服務雪崩,一個是鎖表導致核心功能停滯一小時。
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)~