一、問題描述
2022年7月2x日,窗外夕陽將落不落,余暉灑落在街道上,遠(yuǎn)處的熱浪仿佛在說:嘿,歡迎來到烤箱中的瑞士卷—成都!
“嘿!”,我回過神來看到一只潔白纖細(xì)的手落在我的肩膀上,眼光從窗外收回順著手臂快速扭跟過去,然后看到臉色暗淡夾雜著些許痘痘的測(cè)試妹紙一臉的嚴(yán)肅!“昨天晚上上線后,這個(gè)后臺(tái)執(zhí)行更新信息非常緩慢,這里肯定有問題!”
基于 Spring Boot + MyBatis Plus + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能
- 項(xiàng)目地址:https://github.com/YunaiV/ruoyi-vue-pro
- 視頻教程:https://doc.iocoder.cn/video/
二、問題分析
“好的,我排查一下”。三步并作兩步回到工位,掀開MacBook Pro的蓋子、打開顯示器的電源、輸入鏈路日志跟蹤系統(tǒng)地址、復(fù)制traceId、查看日志…… 這一套操作熟悉得令人心疼。
排查日志初步發(fā)現(xiàn)實(shí)際調(diào)用了兩次,第一次執(zhí)行時(shí)間接近10s,調(diào)用超時(shí),第二次執(zhí)行時(shí)間接近5s。你肯定也想到了,RPC調(diào)用retry設(shè)置了值。對(duì)RPC配置檢查之后確實(shí)設(shè)置的是retry=1,實(shí)際項(xiàng)目中,增、刪、改等操作不應(yīng)設(shè)置retry。
通過調(diào)用鏈排查發(fā)現(xiàn)update執(zhí)行非常耗時(shí)。聰明的你一定也第一時(shí)間懷疑update語句有性能問題。把update語句拿出來:
updatetableseta=#{1},b=#{2},...whereid=#{0}(id主鍵)
這下傻眼了,根據(jù)主鍵id更新怎么可能要執(zhí)行10s?
masaga??。?/strong>
為了驗(yàn)證我的猜想,command + 空格、鍵入idea并回車、打開對(duì)應(yīng)的工程、定位到對(duì)應(yīng)的方法處、迅速瀏覽一遍并思索片刻之后,真相大白!

服務(wù)B執(zhí)行完update語句之后,事務(wù)commit之前,還有兩個(gè)異步通知任務(wù),使用的是spring的@Async注解,自定義的線程池,跟蹤日志中的線程標(biāo)志,排查過程中發(fā)現(xiàn)有的異步任務(wù)居然由原線程執(zhí)行!進(jìn)一步分析日志發(fā)現(xiàn)這種現(xiàn)象并不是一直發(fā)生,有時(shí)又是由異步線程執(zhí)行。開始排查線程池,線程池果然設(shè)置了callRunner的失敗策略。
所以,由原線程執(zhí)行時(shí),事務(wù)的范圍如下:

定位到原因之后,修改線程池參數(shù)為常見策略,初始和最大線程數(shù)相同,隊(duì)列數(shù)9999,保證線程池的線程充足性。
修復(fù)
灰度
招呼測(cè)試妹紙測(cè)試
自信滿滿,悠閑喝水
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能
三、梅開二度
“在高并發(fā)場(chǎng)景下,復(fù)現(xiàn)了這個(gè)問題,你快看一下”!測(cè)試妹紙對(duì)我投來鄙視的眼光犀利的說道:“修復(fù)好了,再喊我回歸哈,拜拜~”。
奇怪,為什么這么平常的一個(gè)update語句,怎么會(huì)執(zhí)行這么長(zhǎng)時(shí)間呢?難道出發(fā)了框架的bug導(dǎo)致事務(wù)提交延遲?不對(duì)不對(duì),這個(gè)方向想偏了~也沒有其他地方在更新這個(gè)表了呀?不可能有表鎖,更不可能有行鎖呀……
masaga?!!
根據(jù)表鎖以及行鎖的思路,為了驗(yàn)證我的內(nèi)心OS猜想,立即使用 show processlist 進(jìn)行了連接查詢,果然有重大發(fā)現(xiàn),除了服務(wù)B有連接之外,還有服務(wù)A的連接。而服務(wù)A又是服務(wù)B的上游系統(tǒng)!系統(tǒng)架構(gòu)如下:

執(zhí)行順序如下:
順序 | 服務(wù) | 執(zhí)行動(dòng)作 | 關(guān)鍵點(diǎn) |
---|---|---|---|
1 | 服務(wù)A | 執(zhí)行update語句 | 數(shù)據(jù)庫(kù) 行鎖 lock |
2 | 服務(wù)A | 調(diào)用服務(wù)B | RPC 調(diào)用 |
3 | 服務(wù)B | 執(zhí)行update語句 | 數(shù)據(jù)庫(kù) 行鎖 waiting |
4 | 服務(wù)A | 調(diào)用服務(wù)B超時(shí) | RPC timeout |
5 | 服務(wù)A | 再次調(diào)用服務(wù)B | RPC retry |
6 | 服務(wù)A | 調(diào)用調(diào)用服務(wù)B再次超時(shí) | RPC timeout |
7 | 服務(wù)A | PRC調(diào)用超時(shí)異常 | 數(shù)據(jù)庫(kù) 事務(wù)回滾 行鎖 unlock |
8 | 服務(wù)B | 執(zhí)行 | 數(shù)據(jù)庫(kù) 行鎖 競(jìng)爭(zhēng) |
不被人信任的滋味很難受!為了重新贏回測(cè)試妹紙對(duì)我的信任,這次的bug修復(fù)只需成功不許失??!
四、解決方案
知道病根之后,問題就很簡(jiǎn)單了。
最理想的方案
對(duì)微服務(wù)架構(gòu)進(jìn)行重構(gòu),但這樣做帶來的收益不高,現(xiàn)在手上還有優(yōu)先級(jí)更高的事情要做。

最實(shí)際的方案
是將服務(wù)A對(duì)服務(wù)B的調(diào)用和服務(wù)A的事務(wù)分離出來。這樣就不存在鎖競(jìng)爭(zhēng)的問題了。

五、總結(jié)
看到了這里,你心里是不是已經(jīng)在想:我靠,大廠的系統(tǒng)架構(gòu)真的很垃圾,我都是關(guān)著燈的~(走錯(cuò)片場(chǎng)~)
其實(shí)這個(gè)系統(tǒng)變成這樣是有歷史原因的,如果當(dāng)初的開發(fā)者能夠采用DDD的思想或者能夠明白微服務(wù)的對(duì)象高內(nèi)聚思想,或許今天就不會(huì)發(fā)生在我身上這場(chǎng)研發(fā)與測(cè)試之間的信任危機(jī)。
夕陽落下,夜晚籠罩著大地。路旁的小貓咪悠然站了起來,張大嘴巴打個(gè)哈欠的同時(shí)伸了個(gè)懶腰,然后走向3號(hào)門口,等待著心地善良的加班兒投食貓糧?!膀?yàn)證通過,早點(diǎn)下班”。不遠(yuǎn)處傳來測(cè)試妹紙的聲音,夾雜著中央空調(diào)吹出的風(fēng)聲。
審核編輯 :李倩
-
macbook
+關(guān)注
關(guān)注
0文章
500瀏覽量
42619 -
線程
+關(guān)注
關(guān)注
0文章
508瀏覽量
20651 -
系統(tǒng)架構(gòu)
+關(guān)注
關(guān)注
1文章
72瀏覽量
24066
原文標(biāo)題:一個(gè)update語句執(zhí)行要10s,大廠的架構(gòu)真垃圾!
文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
使用evn工具執(zhí)行pkgs --update時(shí)出現(xiàn)如下報(bào)錯(cuò),怎么解決?
ubuntu 22.04 執(zhí)行pkgs--update 失敗的原因?
紅魔10S Pro+體驗(yàn)報(bào)告
在使用EZ-USB? FX3? 設(shè)備時(shí),上電后相機(jī)開始正常工作,但延時(shí)10s左右播放器才能夠顯示圖像數(shù)據(jù)?為什么?
驅(qū)動(dòng)下一代E/E架構(gòu)的神經(jīng)脈絡(luò)進(jìn)化—10BASE-T1S

基礎(chǔ)篇3:掌握Python中的條件語句與循環(huán)
淺談wsl --update` 命令行選項(xiàng)無效的解決方案
《ESP32S3 Arduino開發(fā)指南》第三章 C/C++語言基礎(chǔ)
詳解TIA Portal SCL編程語言中的IF語句

CPU的各種指令和執(zhí)行流程
ADC128S022的驅(qū)動(dòng)架構(gòu)參考 ti-adc128s052.c,要如何做移位生成12bit結(jié)果呢?
深入理解C語言:循環(huán)語句的應(yīng)用與優(yōu)化技巧

評(píng)論