日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
老板急壞了,線上又出“幺蛾子”了!

 很多人在面試時,會被問到這樣的問題:遇到過什么系統(tǒng)故障?怎么解決的?

圖片來自 Pexels

下面是筆者根據(jù)自己 15 年互聯(lián)網(wǎng)研發(fā)經(jīng)歷總結的多個線上故障真實案例。相信可以幫你從容應對面試官的提問!本文圖不多,但內(nèi)容很干!理解為主,面試為輔,學以致用!

故障一:JVM頻繁FULL GC快速排查

在分享此案例前,先聊聊哪些場景會導致頻繁 Full GC:

  • 內(nèi)存泄漏(代碼有問題,對象引用沒及時釋放,導致對象不能及時回收)
  • 死循環(huán)
  • 大對象

尤其是大對象,80% 以上的情況就是它,那么大對象從哪里來的呢?

  • 數(shù)據(jù)庫(包括 MySQL 和 MongoDB 等 NoSQL 數(shù)據(jù)庫),結果集太大
  • 第三方接口傳輸?shù)拇髮ο?/li>
  • 消息隊列,消息太大

根據(jù)多年一線互聯(lián)網(wǎng)經(jīng)驗,絕大部分情況是數(shù)據(jù)庫大結果集導致。

好,現(xiàn)在我們開始介紹這次線上故障:在沒有任何發(fā)布的情況下,POP 服務(接入第三方商家的服務)突然開始瘋狂 Full GC,觀察堆內(nèi)存監(jiān)控沒內(nèi)存泄漏,回滾到前一版本,問題仍然存在,尷尬了!!!

按照常規(guī)做法,一般先用 jmap 導出堆內(nèi)存快照(jmap -dump:format=b,file=文件名 [pid]),然后用 mat 等工具分析出什么對象占用了大量空間,再查看相關引用找到問題代碼。

這種方式定位問題周期會比較長,如果是關鍵服務,長時間不能定位解決問題,影響太大。

下面來看看我們的做法:先按照常規(guī)做法分析堆內(nèi)存快照,與此同時另外的同學去查看數(shù)據(jù)庫服務器網(wǎng)絡 IO 監(jiān)控。

如果數(shù)據(jù)庫服務器網(wǎng)絡 IO 有明顯上升,并且時間點吻合,基本可以確定是數(shù)據(jù)庫大結果集導致了 Full GC,趕緊找 DBA 快速定位大 SQL(對 DBA 來說很簡單,分分鐘搞定,如果 DBA 不知道怎么定位,那他要被開除了,哈哈),定位到 SQL 后再定位代碼就非常簡單了。

按照這種辦法,我們很快定位了問題。原來是一個接口必傳的參數(shù)沒傳進來,也沒加校驗,導致 SQL 語句 where 后面少了兩個條件,一次查幾萬條記錄出來,真坑啊!這種方法是不是要快很多,哈哈,5 分鐘搞定。

當時的 DAO 層是基于 Mybatis 實現(xiàn)的,出問題的 SQL 語句如下:

 
 
 
 
  1.  
  2.  
  3. select * from user where 1=1 
  4.  
  5. and order_id = #{orderID} 
  6.  
  7.  
  8.  
  9. and user_id=#{userID} 
  10.  
  11.  
  12.  
  13. and create_time >= #{createTime} 
  14.  
  15.  
  16.  
  17. and create_time <= #{userID} 
  18.  
  19.  
  20.  

上面 SQL 語句意思是根據(jù) orderID 查一個訂單,或者根據(jù) userID 查一個用戶所有的訂單,兩個參數(shù)至少要傳一個。

但是兩個參數(shù)都沒傳,只傳了 startTime 和 endTime。所以一次 Select 就查出了幾萬條記錄。

所以我們在使用 Mybatis 的時候一定要慎用 if test,一不小心就會帶來災難。后來我們將上面的 SQL 拆成了兩個。

根據(jù)訂單 ID 查詢訂單:

 
 
 
 
  1.  
  2.  
  3. select * from user where 
  4.  
  5. order_id = #{orderID} 
  6.  
  7.  
  8.  

根據(jù) userID 查詢訂單:

 
 
 
 
  1.  
  2.  
  3. select * from user where 
  4. user_id=#{userID} 
  5.  
  6.  
  7. and create_time >= #{createTime} 
  8.  
  9.  
  10.  
  11. and create_time <= #{userID} 
  12.  
  13.  
  14.  

故障二:內(nèi)存泄漏

介紹案例前,先了解一下內(nèi)存泄漏和內(nèi)存溢出的區(qū)別。

內(nèi)存溢出:程序沒有足夠的內(nèi)存使用時,就會發(fā)生內(nèi)存溢出。內(nèi)存溢出后程序基本上就無法正常運行了。

內(nèi)存泄漏:當程序不能及時釋放內(nèi)存,導致占用內(nèi)存逐漸增加,就是內(nèi)存泄漏。

內(nèi)存泄漏一般不會導致程序無法運行。不過持續(xù)的內(nèi)存泄漏,累積到內(nèi)存上限時,就會發(fā)生內(nèi)存溢出。

在 Java 中,如果發(fā)生內(nèi)存泄漏,會導致 GC 回收不徹底,每次 GC 后,堆內(nèi)存使用率逐漸增高。

下圖是 JVM 發(fā)生內(nèi)存泄漏的監(jiān)控圖,我們可以看到每次 GC 后堆內(nèi)存使用率都比以前提高了。

圖片來源于網(wǎng)絡

當時內(nèi)存泄漏的場景是,用本地緩存(公司基礎架構組自己研發(fā)的框架)存放了商品數(shù)據(jù),商品數(shù)量不算太多,幾十萬的樣子。

如果只存熱點商品,內(nèi)存占用不會太大,但是如果存放全量商品,內(nèi)存就不夠了。

初期我們給每個緩存記錄都加了 7 天的過期時間,這樣就可以保證緩存中絕大部分都是熱點商品。

不過后來本地緩存框架經(jīng)過一次重構,過期時間被去掉了。沒有了過期時間,日積月累本地緩存越來越大,很多冷數(shù)據(jù)也被加載到了緩存。直到有一天接到告警短信,提示堆內(nèi)存過高。

趕緊通過 jmap(jmap -dump:format=b,file=文件名 [pid] )下載了堆內(nèi)存快照,然后用 eclipse 的 mat 工具分析快照,發(fā)現(xiàn)了本地緩存中有大量的商品記錄。定位問題后趕緊讓架構組加上了過期時間,然后逐個節(jié)點重啟了服務。

虧了我們加了服務器內(nèi)存和 JVM 堆內(nèi)存監(jiān)控,及時發(fā)現(xiàn)了內(nèi)存泄漏的問題。否則隨著泄漏問題日積月累,如果哪天真的 OOM 就慘了。

所以技術團隊除了做好 CPU,內(nèi)存等運維監(jiān)控,JVM 監(jiān)控也非常重要。

故障三:冪等問題

很多年前,筆者在一家大型電商公司做 Java 程序員,當時開發(fā)了積分服務。當時的業(yè)務邏輯是,用戶訂單完結后,訂單系統(tǒng)發(fā)送消息到消息隊列,積分服務接到消息后給用戶積分,在用戶現(xiàn)有的積分上加上新產(chǎn)生的積分。

由于網(wǎng)絡等原因會有消息重復發(fā)送的情況,這樣也就導致了消息的重復消費。當時筆者還是個初入職場的小菜鳥,并沒有考慮到這種情況。

所以上線后偶爾會出現(xiàn)重復積分的情況,也就是一個訂單完結后會給用戶加兩次或多次積分。

后來我們加了一個積分記錄表,每次消費消息給用戶增加積分前,先根據(jù)訂單號查一遍積分記錄表,如果沒有積分記錄才給用戶增加積分。

這也就是所謂的“冪等性”,即多次重復操作不影響最終的結果。實際開發(fā)中很多需要重試或重復消費的場景都要實現(xiàn)冪等,以保證結果的正確性。例如,為了避免重復支付,支付接口也要實現(xiàn)冪等。

故障四:緩存雪崩

我們經(jīng)常會遇到需要初始化緩存的情況。比如,我們曾經(jīng)經(jīng)歷過用戶系統(tǒng)重構,用戶系統(tǒng)表結構發(fā)生了變化,緩存信息也要變。

重構完成后上線前,需要初始化緩存,將用戶信息批量存入 Reids。每條用戶信息緩存記錄過期時間是 1 天,記錄過期后再從數(shù)據(jù)庫查詢最新的數(shù)據(jù)并拉取到 Redis 中。

灰度上線時一切正常,所以很快就全量發(fā)布了。整個上線過程非常順利,碼農(nóng)們也很開心。

不過,第二天,災難發(fā)生了!到某一個時間點,各種報警紛至沓來。用戶系統(tǒng)響應突然變得非常慢,甚至一度沒有任何響應。

查看監(jiān)控,用戶服務 CPU 突然飆高(IO wait 很高),MySQL 訪問量激增,MySQL 服務器壓力也隨之暴增,Reids 緩存命中率也跌到了極點。

依賴于我們強大的監(jiān)控系統(tǒng)(運維監(jiān)控,數(shù)據(jù)庫監(jiān)控,APM 全鏈路性能監(jiān)控),很快定位了問題。

原因就是 Reids 中大量用戶記錄集中失效,獲取用戶信息的請求在 Redis 中查不到用戶記錄,導致大量的請求穿透到數(shù)據(jù)庫,瞬間給數(shù)據(jù)庫帶來巨大壓力。同時用戶服務和相關聯(lián)的其他服務也都受到了影響。

這種緩存集中失效,導致大量請求同時穿透到數(shù)據(jù)庫的情況,就是所謂的“緩存雪崩”。

如果沒到緩存失效時間點,性能測試也測不出問題。所以一定要引起大家注意。所以,需要初始化緩存數(shù)據(jù)時,一定要保證每個緩存記錄過期時間的離散性。

例如,我們給這些用戶信息設置過期時間,可以采用一個較大的固定值加上一個較小的隨機值。比如過期時間可以是:24 小時+0 到 3600 秒的隨機值。

故障五:磁盤 IO 導致線程阻塞

問題發(fā)生在 2017 年下半年,有一段時間地理網(wǎng)格服務時不常的會響應變慢,每次持續(xù)幾秒鐘到幾十秒鐘就自動恢復。

如果響應變慢是持續(xù)的還好辦,直接用 jstack 抓線程堆棧,基本可以很快定位問題。

關鍵持續(xù)時間只有最多幾十秒鐘,而且是偶發(fā)的,一天只發(fā)生一兩次,有時幾天才發(fā)生一次,發(fā)生時間點也不確定,人盯著然后用 jstack 手工抓線程堆棧顯然不現(xiàn)實。

好吧,既然手工的辦法不現(xiàn)實,咱們就來自動的,寫一個shell腳本自動定時執(zhí)行 jstack,5 秒執(zhí)行一次 jstack,每次執(zhí)行結果放到不同日志文件中,只保存 20000 個日志文件。

Shell 腳本如下:

 
 
 
 
  1. #!/bin/bash 
  2. num=0 
  3. log="/tmp/jstack_thread_log/thread_info" 
  4.  
  5. cd /tmp 
  6. if [ ! -d "jstack_thread_log" ]; then 
  7.    mkdir jstack_thread_log 
  8. fi 
  9.  
  10. while ((num <= 10000)); 
  11.  
  12.   do 
  13.  
  14.     ID=`ps -ef | grep java | grep gaea | grep -v "grep" | awk '{print $2}'` 
  15.  
  16.     if [ -n "$ID" ]; then 
  17.   jstack $ID >> ${log}   
  18.     fi 
  19.  
  20.     num=$(( $num + 1 )) 
  21.  
  22.     mod=$(( $num%100 )) 
  23.  
  24.     if [ $mod -eq 0 ]; then 
  25.   back=$log$num 
  26.   mv $log $back 
  27.     fi 
  28.  
  29.     sleep 5 
  30.  
  31. done 

下一次響應變慢的時候,我們找到對應時間點的 jstack 日志文件,發(fā)現(xiàn)里面有很多線程阻塞在 logback 輸出日志的過程。

后來我們精簡了 log,并且把 log 輸出改成異步,問題解決了,這個腳本果真好用!建議大家保留,以后遇到類似問題時,可以拿來用!

故障六:數(shù)據(jù)庫死鎖問題

在分析案例之前,我們先了解一下 MySQL INNODB。在 MySQL INNODB 引擎中主鍵是采用聚簇索引的形式,即在 B 樹的葉子節(jié)點中既存儲了索引值也存儲了數(shù)據(jù)記錄,即數(shù)據(jù)記錄和主鍵索引是存在一起的。

而普通索引的葉子節(jié)點存儲的只是主鍵索引的值,一次查詢找到普通索引的葉子節(jié)點后,還要根據(jù)葉子節(jié)點中的主鍵索引去找到聚簇索引葉子節(jié)點并拿到其中的具體數(shù)據(jù)記錄,這個過程也叫“回表”。

故障發(fā)生的場景是關于我們商城的訂單系統(tǒng)。有一個定時任務,每一小時跑一次,每次把所有一小時前未支付訂單取消掉。而客服后臺也可以批量取消訂單。

訂單表 t_order 結構大至如下:

id 是表的主鍵,created_time 字段上是普通索引。

聚簇索引(主鍵 id):

普通索引(created_time字段 ):

定時任務每一小時跑一次,每次把所有一小時前兩小時內(nèi)的未支付訂單取消掉,比如上午 11 點會取消 8 點到 10 點的未支付訂單。

SQL 語句如下:

 
 
 
 
  1. update t_order set status = 'CANCELLED' where created_time > '2020-01-01 08:00:00' and created_time < '2020-01-01 10:00:00' and status = 'UNPAID' 

客服批量取消訂單 SQL 如下:

 
 
 
 
  1. update t_order set status = 'CANCELLED' where id in (2, 3, 5) and status = 'UNPAID' 

上面的兩條語句同時執(zhí)行就可能發(fā)生死鎖,我們來分析一下原因。

第一條定時任務的 SQL,會先找到 created_time 普通索引并加鎖,然后再在找到主鍵索引并加鎖。

第一步,created_time 普通索引加鎖:

第二步,主鍵索引加鎖:

第二條客服批量取消訂單 SQL,直接走主鍵索引,直接在主鍵索引上加鎖。

我們可以看到,定時任務 SQL 對主鍵加鎖順序是 5,4,3,2??头咳∠唵?SQL 對主鍵加鎖順序是 2,3,5。

當?shù)谝粋€ SQL 對 3 加鎖后,正準備對 2 加鎖時,發(fā)現(xiàn) 2 已經(jīng)被第二個 SQL 加鎖了,所以第一個 SQL 要等待 2 的鎖釋放。

而此時第二個 SQL 準備對 3 加鎖,卻發(fā)現(xiàn) 3 已經(jīng)被第一個 SQL 加鎖了,就要等待 3 的鎖釋放。兩個 SQL 互相等待對方的鎖,也就發(fā)生了“死鎖”。

解決辦法就是從 SQL 語句上保證加鎖順序一致?;蛘甙芽头咳∠唵?SQL 改成每次 SQL 操作只能取消一個訂單,然后在程序里多次循環(huán)執(zhí)行 SQL,如果批量操作的訂單數(shù)量不多,這種笨辦法也是可行的。

故障七:域名劫持

先看看 DNS 解析是怎么回事,當我們訪問 www.baidu.com 時,首先會根據(jù) www.baidu.com 到 DNS 域名解析服務器去查詢百度服務器對應的 IP 地址,然后再通過 HTTP 協(xié)議訪問該 IP 地址對應的網(wǎng)站。

而 DNS 劫持是互聯(lián)網(wǎng)攻擊的一種方式,通過攻擊域名解析服務器(DNS)或者偽造域名解析服務器,把目標網(wǎng)站域名解析到其他的 IP。從而導致請求無法訪問目標網(wǎng)站或者跳轉到其他網(wǎng)站。

如下圖:

下面這張圖是我們曾經(jīng)經(jīng)歷過的 DNS 劫持的案例。

看圖中的紅框部分,本來上方的圖片應該是商品圖片,但是卻顯示成了廣告圖片。是不是圖片配錯了?不是,是域名(DNS)被劫持了。

原本應該顯示存儲在 CDN 上的商品圖片,但是被劫持之后卻顯示了其他網(wǎng)站的廣告鏈接圖片。

由于當時的 CDN 圖片鏈接采用了不安全的 HTTP 協(xié)議,所以很容易被劫持。后來改成了 HTTPS,問題就解決了。

當然域名劫持有很多方式,HTTPS 也不能規(guī)避所有問題。所以,除了一些安全防護措施,很多公司都有自己的備用域名,一旦發(fā)生域名劫持可以隨時切換到備用域名。

故障八:帶寬資源耗盡

帶寬資源耗盡導致系統(tǒng)無法訪問的情況,雖然不多見,但是也應該引起大家的注意。來看看,之前遇到的一起事故。

場景是這樣的:社交電商每個分享出去的商品圖片都有一個唯一的二維碼,用來區(qū)分商品和分享者。

所以二維碼要用程序生成,最初我們在服務端用 Java 生成二維碼。前期由于系統(tǒng)訪問量不大,系統(tǒng)一直沒什么問題。

但是有一天運營突然搞了一次優(yōu)惠力度空前的大促,系統(tǒng)瞬時訪問量翻了幾十倍。

問題也就隨之而來了,網(wǎng)絡帶寬直接被打滿,由于帶寬資源被耗盡,導致很多頁面請求響應很慢甚至沒任何響應。

原因就是二維碼生成數(shù)量瞬間也翻了幾十倍,每個二維碼都是一張圖片,對帶寬帶來了巨大壓力。

怎么解決呢?如果服務端處理不了,就考慮一下客戶端。把生成二維碼放到客戶端 APP 處理,充分利用用戶終端手機,目前 Andriod,iOS 或者 React 都有相關生成二維碼的 SDK。

這樣不但解決了帶寬問題,而且也釋放了服務端生成二維碼時消耗的 CPU 資源(生成二維碼過程需要一定的計算量,CPU 消耗比較明顯)。

外網(wǎng)帶寬非常昂貴,我們還是要省著點用啊!本文分享的案例都是筆者的親身經(jīng)歷,希望對各位讀者有所幫助。

作者:二馬讀書

簡介:曾任職于阿里巴巴,每日優(yōu)鮮等互聯(lián)網(wǎng)公司,任技術總監(jiān),15年電商互聯(lián)網(wǎng)經(jīng)歷。

編輯:陶家龍

出處:轉載自微信公眾號架構師進階之路


本文名稱:老板急壞了,線上又出“幺蛾子”了!
文章轉載:http://m.5511xx.com/article/cocpoog.html