崩潰的一天,西安一碼通崩潰背後的技術問題。

1.崩潰的一天

12月20號,算得上西安崩潰的一天。

12月19號新增病例21個,20號新增病例42個,並且有部分病例已經在社區內傳播...

西安防疫壓力巨大,各單位公司要求,需48小時核酸檢測報告上班。

在這樣嚴峻的情況下,作爲防控最核心的系統:西安一碼通竟然崩潰了,並且崩潰得是那麼的徹底。

足足癱瘓超過 15+ 個小時!

整整一天的時間呀,多少上班族被堵在地鐵口,多少旅客被凍在半路上,進退不能...

到了下午,新聞甚至提示:

爲了減輕系統壓力,建議廣大市民非必要不展碼、亮碼,在出現系統卡頓時,請耐心等待,儘量避免反覆刷新,也感謝廣大市民朋友們的理解配合。

這是解決問題的方法嗎?

如果真的需要限流來防止系統崩潰,用技術手段來限流是不是會更簡單一些,甚至前面加一個 nginx 就能解決的問題。

今天,我們就試着分析一下這個業務、以及對應的技術問題。

2.產品分析

西安一碼通其它業務我們暫且不分析,那並不是重點,並且當天也沒有完全崩潰,崩潰的僅有掃碼功能。

其實這是一個非常典型的大量查詢、少數更新的業務,閉着眼睛分析一下,可以說, 90% 以上的流量都是查詢。

我們先來看看第一版的產品形態,掃碼之後展示個人部分姓名和身份證信息,同時下面展示綠、黃、紅碼。

這是西安一碼通最開始的樣子,業務流程僅僅只需要一個請求,甚至一個查詢的 SQL 就可以搞定。

到了後來,這個界面做了2次比較大的改版。

第一次改版新增了疫苗接種信息,加了一個邊框;第二次改版新增了核酸檢測信息,在最下方展示核酸檢測時間、結果。

整個頁面增加了2個查詢業務,如果系統背後使用的是關係數據庫,可能會多增加至少2個查詢SQL。

基本上就是這樣的一個需求,據統計西安有1300萬人口,按照最大10%的市民同時掃碼(我懷疑不會有這麼多),也就是百萬的併發量。

這樣一個併發量的業務,在互聯網公司很常見,甚至比這個複雜的場景也多了去了。

那怎麼就崩了呢?

3.技術分析

在當天晚上的官方回覆中,我們看到有這樣一句話:

12月20日早7:40分左右,西安“一碼通”用戶訪問量激增,每秒訪問量達到以往峯值的10倍以上,造成網絡擁塞,致使包括“一碼通”在內的部分應用系統無法正常使用。“

一碼通”後臺監控第一時間報警,各24小時駐場通信、網絡、政務雲、安全和運維團隊立即開展排查,平臺應用系統和數據庫運行正常,判斷問題出現在網絡接口側。

根據上面的信息,數據庫和平臺系統都正常,是網絡出現了問題。

我之前在文章《一次dns緩存引發的慘案》畫過一張訪問示意圖,用這個圖來和大家分析一下,網絡出現問題的情況。

一般用戶的請求,會先從域名開始,經過DNS服務器解析後拿到外網IP地址,經過外網IP訪問防火牆和負載之後打到服務器,最後服務器響應後將結果返回到瀏覽器。

如果真的是網絡出現問題,一般最常見的問題就是 DNS 解析錯誤,或者外網的寬帶被打滿了。

DNS解析錯誤一定不是本次的問題,不然可能不只是這一個功能出錯了;外網的寬帶被打滿,直接增加帶寬就行,不至於一天都沒搞定。

如果真的是網絡側出現問題,一般也不需要改動業務,但實際上系統恢復的時候,大家都發現界面回到文章開頭提到了第一個版本了。

也就是說系統“回滾”了。

界面少了接種信息和核酸檢測信息的內容,並且在一碼通的首頁位置,新增加了一個核酸查詢的頁面。

所以,僅僅是網絡接口側出現問題嗎?我這裏有一點點的疑問。

4.個人分析

根據我以往的經驗,這是一個很典型的系統過載現象,也就是說短期內請求量超過服務器響應。

說人話就是,外部請求量超過了系統的最大處理能力。

當然了,系統最大處理能力和系統架構息息相關,同樣的服務器不同的架構,系統負載量差異極大。

應對這樣的問題,解決起來無非有兩個方案,一個是限流,另外一個就是擴容了。

限流就是把用戶擋在外面,先處理能處理的請求;擴容就是加服務器、增加數據庫承載能力。

上面提到官方讓大家沒事別刷一碼通,也算是人工限流的一種方式;不過在技術體系上基本上不會這樣做。

技術上的限流方案有很多,但最簡單的就是前面掛一個 Nginx 配置一下就能用;複雜一點就是接入層自己寫算法。

當然了限流不能真正的解決問題,只是負責把一部分請求擋在外面;真正解決問題還是需要擴容,滿足所有用戶。

但實際上,根據解決問題的處理和產品回滾的情況來看,一碼通並沒有第一時間做擴容,而是選擇了回滾。

這說明,在系統架構設計上,沒有充分考慮擴容的情況,所以並不能支持第一時間選擇這個方案。

5.理想的方案?

上面說那麼多也僅僅是個人推測,實際上可能他們會面臨更多現實問題,比如工期緊張、老闆控制預算等等...

話說回來,如果你是負責一碼通公司的架構師,你會怎麼設計整個技術方案呢?歡迎大家留言,這裏說說我的想法。

第一步,讀寫分離、緩存。

至少把系統分爲2大塊,滿足日常使用的讀業務單獨抽取出來,用於承接外部的最大流量。

單獨抽出一個子系統負責業務的更新,比如接種信息的更新、核酸信息的變化、或者根據業務定時變更碼的顏色。

同時針對用戶大量的單查詢,上緩存系統,優先讀取緩存系統的信息,防止壓垮後面的數據庫。

第二步,分庫分表、服務拆分。

其實用戶和用戶之間的單個查詢是沒有關係的,完全可以根據用戶的屬性做分庫分表。

比如就用用戶ID取模分64個表,甚至可以分成64個子系統來查詢,在接口最前端將流量分發掉,減輕單個表或者服務壓力。

上面分析沒有及時擴容,可能就是沒有做服務拆分,如果都是單個的業務子服務的話,遇到過載的問題很容易做擴容。

當然,如果條件合適的話,上微服務架構就更好了,有一套解決方案來處理類似的問題。

第三步,大數據系統、容災。

如果在一個頁面中展示很多信息,還有一個技術方案,就是通過異步的數據清洗,整合到 nosql 的一張大表中。

用戶掃描查詢等相關業務,直接走 nosql 數據庫即可。

這樣處理的好處是,哪怕更新業務完全掛了,也不會影響用戶掃碼查詢,因爲兩套系統、數據庫都是完全分開的。

使用異地雙機房等形式部署服務,同時做好整體的容災、備災方案,避免出現極端情況,比如機房光纜挖斷等。

還有很多細節上的優化,這裏就不一一說明了,這裏也只是我的一些想法,歡迎大家留言補充。

6.最後

不管怎麼分析,這肯定是人禍而不是天災。

系統在沒有經過嚴格測試之下,就直接投入到生產,在強度稍微大一點的環境中就崩潰了。

比西安大的城市很多,比西安現在疫情還要嚴重的情況,其它城市也遇到過,怎麼沒有出現類似的問題?

西安做爲一個科技大省,出現這樣的問題真的不應該,特別是我看了這個小程序背後使用的域名地址之後。

有一種無力吐槽的感覺,雖然說這和程序使用沒有關係,但是從細節真的可以看出一個技術團隊的實力。

希望這次能夠吸取教訓,避免再次出現類似的問題!

推薦閱讀:《西安健康一碼通崩了!程序員搶修竟然被……》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章