分享下最近遇到的5種網站變慢的案例

踩刀詩人發表於2022-04-22

 

 聊聊閒天:四月的西安陽光明媚,溫度舒適,本應該是個全家出去春遊的日子,奈何病毒再一次攻破了西安的嚴防死守,讓大家本就懸著的心又緊繃起來,為了安全還是在家貓著吧,另一方面專案組內4月12號開始要開啟一波996,意味著又要過一段加班狗的日子,估計顧不上寫點東西了,避免四月留下空檔,還是在家潤色一篇技術貼。

 

最近一年多在一家toB業務的公司,主營疑難雜症的解決、效能優化,和過往待過的公司相比,開發除了編碼之外還需要兼任一部分dba、一部分運維,實話講有點累,有時遇到一些奇怪問題一度讓人很暴躁

“為什麼沒個專業的dba呢?”

“啥時候能有個專業的運維呢?”

“這一天天弄啥呢,打雜的一樣”

 

躁歸躁,發洩完了還得接著幹啊,經過一年多的摸爬滾打也算是對常見問題有一些中規中矩的解決辦法,冷靜下來想想還是有些許收穫,待我娓娓道來。

排名第一 資料庫問題

這是發生頻率最高的,目前團隊的toB業務,融合了OLTP和OLAP兩種模式,然而底層只有RDS在負隅頑抗,經常會因為慢查導致資料庫cpu 100%,也許你會說OLAP用RDS本身就不合適,但是沒辦法,試圖去說服客戶接受大資料那一套複雜玩意實屬不易,畢竟系統是部署在客戶私有化機房的,不是你想加就能加的,再者說團隊之前沒有這方面的使用經驗。

 

主要從五個方面優化資料庫問題:

  • 升級資料庫配置,能用錢解決最好,見效快;                                       

  • 優化資料庫引數,最大限度利用硬體,比如我之前提到的innodb_buffer_pool_size的調整,參考終於做了一把MySQL調參boy,效果非常顯著;

  • 加索引,利用索引將查詢的效率提上去,這塊可以借用雲廠商的資料庫診斷工具,為你推薦合適的索引,最後結合自己的經驗進行適當的改造,索引加多了本身也會成為資料庫的負擔,簡單體驗下某雲的診斷功能

分享下最近遇到的5種網站變慢的案例

  • 優化SQL, 複雜SQL拆分、去除不必要的語句等,比如下面這個sql

select distinct A.* from A
union 
select distinct B.* from B

  union本身在做結果合併的時候就會去重,為什麼還要對結果集分別做distinct,徒增RDS的負擔。

  • 在架構上做一些優化,按照2/8原則來講,80%的請求都是讀操作,可以通過增加讀庫的方式來提升讀的吞吐量,也就是常說的讀寫分離,做了讀寫分離以後,報表查詢只會導致讀庫cpu 100%,讀庫一般可以掛多個,可以緩解原來RDS單庫的壓力,如何接入讀寫分離也是個需要重點考慮的點:  

           1.程式碼實現,常見方式是配置讀寫資料來源,程式碼中指定讀還是寫操作,由框架層做切換;

           2.通過資料庫代理,比如MyCAT、ShardingSphere、雲廠商的讀寫分離服務等,該方案的好處是對程式碼無侵入,開發無感知,只需要更換資料庫連結即可。

交代下我們的背景,系統執行多年,框架上並不支援讀寫分離,需要新開發,而且要驅動業務開發對程式碼進行改造,標識哪些走寫庫,哪些走讀庫,再加上充分的測試,戰線會比較長,似乎選擇資料庫代理方案更合適,但是代理類軟體有一個繞不過的問題就是協議相容性,比如我用了一個MySQL資料庫的私有函式,代理不認識就會解析報錯,不能等著代理軟體去相容吧,推動開發改成通用的就更費勁了,可能連方案都要重做了,考慮再三,還是回到了方案一,分階段處理,先處理查詢耗時特別嚴重的,每個迭代處理幾個,小步快跑。

 

做方案就是這樣,提出目標,設想方案,推翻自己,借鑑歷史,取得真經。

 

排名第二 cpu跑滿,fullgc頻繁

  • cpu被某個大任務佔滿,導致其他服務受到牽連,目前有兩種處理方式

      1.程式碼上優化:大任務拆分為小任務,小任務之間增加休眠期,比如每100條sleep 1秒,讓cpu做到雨露均沾;

      2.限制pod的資源佔用,limit cpu 等,降低pod相互影響,一次業務應用被一個基礎服務影響,一看監控該基礎服務幾乎跑滿宿主機的cpu

  • fullgc頻繁導致長時間STW,前端大量超時,看下某客戶環境猖狂的gc log

2021-11-01T01:41:28.604+0000: 1460.617: [Full GC (Allocation Failure) 2021-11-01T01:41:28.604+0000: 1460.617: [Tenured: 2097151K->2097151K(2097152K), 2.3259098 secs] 3040895K->2417455K(3040896K), [Metaspace: 122544K->122544K(1163264K)], 2.3260359 secs] [Times: user=2.32 sys=0.01, real=2.32 secs] 
2021-11-01T01:41:31.429+0000: 1463.442: [Full GC (Allocation Failure) 2021-11-01T01:41:31.429+0000: 1463.442: [Tenured: 2097151K->2097151K(2097152K), 3.0093385 secs] 3040246K->2392920K(3040896K), [Metaspace: 122575K->122575K(1163264K)], 3.0094839 secs] [Times: user=3.02 sys=0.02, real=3.01 secs] 
2021-11-01T01:41:34.861+0000: 1466.874: [Full GC (Allocation Failure) 2021-11-01T01:41:34.861+0000: 1466.874: [Tenured: 2097151K->2097151K(2097152K), 2.4219892 secs] 3040364K->2397366K(3040896K), [Metaspace: 122590K->122590K(1163264K)], 2.4221382 secs] [Times: user=2.42 sys=0.00, real=2.42 secs]

  每次持續時間2.5s左右,每次的開始幾乎緊跟著上一次的結束,jvm基本幹不了別的,全用來處理gc了,再看看arthas dashboard的監控,cpu幾乎全讓vm thread給佔了

優化思路是設定合理的jvm記憶體,降低fullgc頻率,具體設定方式如下:

 

圖片內容來源於https://tech.meituan.com/2017/12/29/jvm-optimize.html

 我在之前的一篇文章中做了一點分析,有興趣的可以移步記一次k8s pod頻繁重啟的優化之旅

 

排名第三 外部依賴故障、超時帶來的連鎖反應 

客戶為了打通內部資訊化流程,會要求我們和其他系統做整合,比如待辦同步到OA,業務資料同步到資料中臺等,互動方式也是多種多樣,http、webservice、直接寫庫等,因為這塊相對於業務來講比較獨立,所以和外部的互動這塊是外包出去的,負責人界限模糊,人員流動大等導致了“屎山堆積“,第一版的程式碼可能還會按照規範來寫,到了第N版的時候就是怎麼方便怎麼來了,本應該非同步的做了同步,本應該配置超時的就是不配置,正常的時候比誰都正常,出事的時候牽一髮動全身,怎麼辦呢,這種就只能指望重構了,非同步化、檢查超時等是否缺失,不能非同步化的引入熔斷降級等策略,貼一張比較經典的圖腦補一下。

 

 

 

排名第四 內網丟包

這個確實之前沒有遇到過,也許沒留意過(想到前領導說過一句話,有些問題你沒發現說明能力不夠),一個簡單的請求,耗時居然十幾秒,內部只有查詢資料庫的操作,太不應該了,機器負載很低,資料庫負載可以忽略不計,抱著碰運氣的心態,我ping資料庫,居然有丟包,丟包率最高有8%,懷疑是不是走外網了,跟客戶一反饋,客戶說這都是內網有線連線的機器,萬分之一的丟包都不正常,他們立馬排查。

 

 

 

 

 

 

排名第五 受WAF影響

WAF是什麼,看下阿里雲官網的介紹:

Web應用防火牆(Web Application Firewall,簡稱 WAF)為您的網站或App業務提供一站式安全防護。WAF可以有效識別Web業務流量的惡意特徵,在對流量進行清洗和過濾後,將正常、安全的流量返回給伺服器,避免網站伺服器被惡意入侵導致伺服器效能異常等問題,保障網站的業務安全和資料安全。

主要功能

  • 提供Web應用攻擊防護。

  • 緩解惡意CC攻擊,過濾惡意的Bot流量,保障伺服器效能正常。

  • 提供業務風控方案,解決業務介面被惡意濫刷等業務安全風險。

  • 提供網站一鍵HTTPS和HTTP回源,降低源站負載壓力。

  • 支援對HTTP和HTTPS流量進行精準的訪問控制。

  • 支援超長時長的全量日誌實時儲存、分析和自定義報表服務,支援日誌線上同步第三方平臺,助力滿足等保合規要求。

看下接了WAF以後請求鏈路發生了什麼變化,最直觀的就是使用者到真實伺服器之間多了一層WAF,如下圖所示:

引入新事物的同時勢必會帶來新問題,通過WAF解決了安全問題,同時就會帶來一些效能損耗。

 

假設WAF慢了,使用者到源站的訪問時間勢必會變長,而使用者一定會投訴是源站出了問題,WAF於ta們而言是透明的,作為源站負責人的我們怎麼甩鍋呢?

 1.ping

 

 

 最開始是想用ping測試一下延遲的,但是發現顯示的ip和運維提供的ip不一致,第一反應是不是網站被黑了,跟客戶說了我們的疑惑後得知,應資訊部門的要求,所有外網域名必須接入某政務雲防禦平臺(WAF),所以現在域名解析的ip是WAF的ip,這樣請求就會先進入到WAF進行防護,防護完成以後回源到真實的伺服器,可以將WAF簡單理解為反向代理的角色。

2.繞過WAF測試響應速度

既然請求鏈路上多了一個節點,那我們想辦法將這個節點摘除以後再測試,兩者對比就可以評估出這個節點帶來的效能損耗,具體怎麼摘除呢,其實很簡單,本地修改hosts檔案將域名直接指向源站ip即可,最終測試發現,WAF在高峰期帶來的效能損耗有數秒。

 

將這些證據發給客戶以後,客戶“已讀未回。”

 

一個小時以後,客戶拉了個群,裡面有WAF的開發,至此,甩鍋成功。

 

 

 

結語

本想著上週末就完成,寫的過程中發現有些東西自己不熟,又順帶學習了一下,好在拖了一週終於結束了,希望能讓來到的同學不虛此行,最後送上一張自己拍的趣圖,名為“打工人的卑微。”

 

 

 

相關文章