一、問題描述
2022年7月2x日,窗外夕陽將落不落,余暉灑落在街道上,遠處的熱浪仿佛在說:嘿,歡迎來到烤箱中的瑞士卷—成都!
“嘿!”,我回過神來看到一只潔白纖細的手落在我的肩膀上,眼光從窗外收回順著手臂快速扭跟過去,然后看到臉色暗淡夾雜著些許痘痘的測試妹紙一臉的嚴肅!“昨天晚上上線后,這個后臺執行更新信息非常緩慢,這里肯定有問題!”
基于 Spring Boot + MyBatis Plus + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能
- 項目地址:https://github.com/YunaiV/ruoyi-vue-pro
- 視頻教程:https://doc.iocoder.cn/video/
二、問題分析
“好的,我排查一下”。三步并作兩步回到工位,掀開MacBook Pro的蓋子、打開顯示器的電源、輸入鏈路日志跟蹤系統地址、復制traceId、查看日志…… 這一套操作熟悉得令人心疼。
排查日志初步發現實際調用了兩次,第一次執行時間接近10s,調用超時,第二次執行時間接近5s。你肯定也想到了,RPC調用retry設置了值。對RPC配置檢查之后確實設置的是retry=1,實際項目中,增、刪、改等操作不應設置retry。
通過調用鏈排查發現update執行非常耗時。聰明的你一定也第一時間懷疑update語句有性能問題。把update語句拿出來:
updatetableseta=#{1},b=#{2},...whereid=#{0}(id主鍵)
這下傻眼了,根據主鍵id更新怎么可能要執行10s?
masaga?!!
為了驗證我的猜想,command + 空格、鍵入idea并回車、打開對應的工程、定位到對應的方法處、迅速瀏覽一遍并思索片刻之后,真相大白!
服務B執行完update語句之后,事務commit之前,還有兩個異步通知任務,使用的是spring的@Async注解,自定義的線程池,跟蹤日志中的線程標志,排查過程中發現有的異步任務居然由原線程執行!進一步分析日志發現這種現象并不是一直發生,有時又是由異步線程執行。開始排查線程池,線程池果然設置了callRunner的失敗策略。
所以,由原線程執行時,事務的范圍如下:
定位到原因之后,修改線程池參數為常見策略,初始和最大線程數相同,隊列數9999,保證線程池的線程充足性。
修復
灰度
招呼測試妹紙測試
自信滿滿,悠閑喝水
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能
三、梅開二度
“在高并發場景下,復現了這個問題,你快看一下”!測試妹紙對我投來鄙視的眼光犀利的說道:“修復好了,再喊我回歸哈,拜拜~”。
奇怪,為什么這么平常的一個update語句,怎么會執行這么長時間呢?難道出發了框架的bug導致事務提交延遲?不對不對,這個方向想偏了~也沒有其他地方在更新這個表了呀?不可能有表鎖,更不可能有行鎖呀……
masaga?!!
根據表鎖以及行鎖的思路,為了驗證我的內心OS猜想,立即使用 show processlist 進行了連接查詢,果然有重大發現,除了服務B有連接之外,還有服務A的連接。而服務A又是服務B的上游系統!系統架構如下:
執行順序如下:
順序 | 服務 | 執行動作 | 關鍵點 |
---|---|---|---|
1 | 服務A | 執行update語句 | 數據庫 行鎖 lock |
2 | 服務A | 調用服務B | RPC 調用 |
3 | 服務B | 執行update語句 | 數據庫 行鎖 waiting |
4 | 服務A | 調用服務B超時 | RPC timeout |
5 | 服務A | 再次調用服務B | RPC retry |
6 | 服務A | 調用調用服務B再次超時 | RPC timeout |
7 | 服務A | PRC調用超時異常 | 數據庫 事務回滾 行鎖 unlock |
8 | 服務B | 執行 | 數據庫 行鎖 競爭 |
不被人信任的滋味很難受!為了重新贏回測試妹紙對我的信任,這次的bug修復只需成功不許失??!
四、解決方案
知道病根之后,問題就很簡單了。
最理想的方案
對微服務架構進行重構,但這樣做帶來的收益不高,現在手上還有優先級更高的事情要做。
最實際的方案
是將服務A對服務B的調用和服務A的事務分離出來。這樣就不存在鎖競爭的問題了。
五、總結
看到了這里,你心里是不是已經在想:我靠,大廠的系統架構真的很垃圾,我都是關著燈的~(走錯片場~)
其實這個系統變成這樣是有歷史原因的,如果當初的開發者能夠采用DDD的思想或者能夠明白微服務的對象高內聚思想,或許今天就不會發生在我身上這場研發與測試之間的信任危機。
夕陽落下,夜晚籠罩著大地。路旁的小貓咪悠然站了起來,張大嘴巴打個哈欠的同時伸了個懶腰,然后走向3號門口,等待著心地善良的加班兒投食貓糧?!膀炞C通過,早點下班”。不遠處傳來測試妹紙的聲音,夾雜著中央空調吹出的風聲。
審核編輯 :李倩
-
macbook
+關注
關注
0文章
496瀏覽量
41684 -
線程
+關注
關注
0文章
504瀏覽量
19675 -
系統架構
+關注
關注
1文章
69瀏覽量
23528
原文標題:一個update語句執行要10s,大廠的架構真垃圾!
文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論