成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Zookeeper恢復了,線上微服務卻全部掉線了,怎么回事?

開發 架構
除了優化對異常的捕獲處理外,RPC框架對注冊中心的空地址推送也應該做特殊判斷,用業界的專業名詞來說,就是「推空保護」。所謂「推空保護」,就是在服務發現監聽獲取空節點列表時,維持本地服務發現列表緩存,而不是清空處理。

注冊中心zookeeper重啟恢復后,線上微服務卻全部掉線了,怎么回事?!

最近因為一次錯誤的運維操作,導致線上注冊中心zk被重啟。而zk重啟后發現所有線上微服務開始不斷掉線,造成了持續30分鐘的P0?故障。

整體排查過程深入學習了 zookeeper的session機制,以及在這種異常情況下,RPC框架應該如何處理。

好了,一起來回顧下這次線上故障吧,最佳實踐總結放在最后,千萬不要錯過。

1、現象描述

某天晚上19:43分左右,誤操作將線上zk集群下線(stop),總共7臺節點,下線了6臺,導致zk停止工作。

在發現節點下掉后,于19:51分左右將所有zk節點進行重啟(start),期間服務正常運行,沒有收到批量業務調用的報錯和客訴。

直到19:56分,開始收到大面積調用失敗的警報和客訴,我們嘗試著依賴自研RPC框架與zk間重連后的「自動恢復」機制,希望能夠在短時間內批量恢復。

但是很不幸,過了接近8分鐘,沒有任何大面積恢復的跡象。

結合zk znode節點數上升非常緩慢的情況,于是我們采取了應急措施,將所有微服務的pod原地重啟,執行重啟后效果顯著,大面積服務在短時間內逐步恢復。

2、初步分析

我們自研的RPC框架采用典型的 注冊中心+provider+consumer 的模式,通過zk臨時節點的方式做服務的注冊發現,如下圖所示。

圖片

結合故障期間發生的現象,我們初步分析:

  • 階段1:zk集群停服(stop)期間,業務能夠正常調用。原因是consumer無法訪問zk,暫時失去服務發現能力,所以在這個期間只要服務沒有重啟,就不會刷新本地的服務發現provider緩存列表provider-list,調用無異常。
  • 階段2:zk集群啟動完畢后,服務間立刻出現調用問題。原因是consumer連接上zk后,立刻進行服務發現操作,然而provider服務這時還沒重新注冊到zk,讀取到的是空地址列表,造成了業務的批量報錯。
  • 階段3:zk恢復后續一段時間,provider服務仍然沒「自動重連」到zk,導致consumer持續報錯。在所有服務全量重啟后,provider服務重新注冊成功,consumer恢復。

這里存在一個問題:

為什么zk集群恢復后,provider客戶端「自動重連」注冊中心的機制沒有生效?導致consumer被推送了空地址列表后,沒有再收到重新的provider注冊節點信息了。

3、深入排查

(1問題復現

根據大量測試,我們找到了穩定復現本次問題的方法:

zk session過期包括 「服務端過期」 和 「客戶端過期」,在「客戶端過期」情況下恢復zk集群,會導致「臨時節點」丟失,且無法自動恢復的情況。

(2原因分析

1)?在集群重啟恢復后,RPC框架客戶端立刻就與zk集群取得重連,將保存在本地內存待注冊的providers節點 + 待訂閱的consumers節點 進行重建。

2)但是zk集群此時根據snapshot恢復的「臨時節點」(包括provider和consumer) 都還在,因此重建操作返回NodeExist異常,重建失敗了。(問題1:為什么沒有重試?)

3)在集群重啟恢復40s后,將過期Session相關的 臨時節點全都移除了。(問題2:為什么要移除?)

4)consumer監聽到 節點移除 的空列表,清空了本地provider列表。故障發生了。?

基于這個分析,我們需要進一步圍繞2個問題進行源碼的定位:

  • 問題1:zk集群恢復后,前40s,為什么RPC框架的客戶端在創建臨時節點失敗后沒有重試?
  • 問題2:zk集群恢復后,40s后,為什么zk會刪除之前所有已經恢復的臨時節點?

(3)問題1:為什么臨時節點創建失敗沒有重試?

通過源碼分析,我們看到,RPC框架客戶端與服務端取得重連后,會將內存里老的臨時節點進行重新創建。

這段邏輯看來沒有什么問題,doRegister成功之后才會將該節點從失敗列表中移除,否則將繼續定時去重試創建。

圖片

繼續往下走,關鍵點來了:

圖片

這里我們可以看到,在創建臨時節點時,吞掉了服務端返回的NodeExistsException,使整個外層的doRegister和doSubscribe(訂閱)方法在這種情況下都被認為是重新創建成功,所以只創建了一次。

正如上面分析的,其實正常情況下,這里對NodeExistsException不做處理是沒有問題的,就是節點已經存在不用再添加了,也不需要再重試了,但是伴隨服務端后續踢出老sessionId同時刪除了相關臨時節點,就引起了故障。

(4)問題2:zk為什么刪除已經恢復的臨時節點?

1)從zk的session機制說起

眾所周知,zk session管理在客戶端、服務端都有實現,并且兩者通過心跳進行交互。

在發送心跳包時,客戶端會攜帶自己的sessionId,服務端收到請求,檢查sessionId確認存活后再發送返回結果給客戶端。

如果客戶端發送了一個服務端并不知道的sessionId,那么服務端會生成一個新的sessionId頒布給客戶端,客戶端收到后本地進行sessionid的刷新。

2)zk客戶端(curator)session過期機制

當客戶端(curator)本地sessionTimeout超時時,會進行本地zk對象的重建(reset),我們從源碼可以看到默認將本地的sessionId重置為0了。

圖片

圖片

zk服務端后續收到這個為“0”sessionId,認為是一個未知的session需要創建,接著就為客戶端創建了一個新的sessionId。

3) 服務端(zookeeper)session過期處理機制

服務端(zookeeper) sessionTimeout的管理,是在zk會話管理器中看到一個線程任務,不斷判斷管理的session是否有超時(獲取下一個過期時間點nextExpirationTime已經超時的會話),并進行會話的清理。

圖片

我們繼續往下走,關鍵點來了,在清理session的過程中,除了將sessionId從本地expiryMap中清除外,還進行了臨時節點的清理

圖片

?原來zkserver端是將sessionId和它所創建的臨時節點進行了綁定。伴隨著服務端sessionId的過期,綁定的所有臨時節點也會隨之刪除。

因此,zk集群恢復后40s,zk服務端session超時,刪除了過期session的所有相關臨時節點。?

4、故障根本原因總結

1)zk集群恢復的第一時間,對zk的snapshot文件進行了讀取并初始化zk數據,取到了老session,進行了create session的操作,完成了一次老session的續約(重置40s)。

集群恢復關鍵入口-重新加載snapshot:

圖片


進行session恢復(創建)操作,默認session timeout 40s:?

圖片

?2)而此時客戶端session早已經過期,帶著空sessionid 0x0進行重連,獲得新sessionId。但是此時RPC框架在臨時節點注冊失敗后吞掉了服務端返回的NodeExistsException,被認為是重新創建成功,所以只創建了一次。

3)zk集群恢復后經過40s最終因為服務端session過期,將過期sessionId和及其綁定的臨時節點進行了清除。

4)consumer監聽到 節點移除 的空列表,清空了本地provider列表。故障發生了。?

5、解決方案

經過上面的源碼分析,解決方案有兩種:

  • 方案1:客戶端(curator)設置session過期時間更長或者不過期,那么集群恢復后的前40s,客戶端帶著原本的sessionid跟服務端做一次請求,就自動續約了,不再過期。
  • 案2:客戶端session過期后,帶著空sessionid 0x0進行重連的時候,對NodeExsitException做處理,進行 刪除-重添加 操作,保證重連成功。

于是我們調研了一下業界使用zk的開源微服務框架是否支持自愈,以及如何實現的:

dubbo采用了方案2。

圖片

注釋也寫得非常清楚:?

“ZNode路徑已經存在,因為我們只會在會話過期時嘗試重新創建節點,所以這種重復可能是由zk服務器的刪除延遲引起的,這意味著舊的過期會話可能仍然保存著這個ZNode,而服務器只是沒有時間進行刪除。在這種情況下,我們可以嘗試刪除并再次創建?!?/span>

看來dubbo確實后續也考慮到這個邊界場景,防止踩坑。

所以最后我們的解決方案也是借鑒dubbo fix的邏輯,進行節點的替換:先deletePath再createPath,這么做的原因是將zk服務端內存維護的過期sessionId替換新的sessionId,避免后續zk清理老sessionId時將所有綁定的節點刪除。

6、最佳實踐

回顧整個故障,我們其實還忽略了一點最佳實踐。

除了優化對異常的捕獲處理外,RPC框架對注冊中心的空地址推送也應該做特殊判斷,用業界的專業名詞來說,就是「推空保護」。

所謂「推空保護」,就是在服務發現監聽獲取空節點列表時,維持本地服務發現列表緩存,而不是清空處理。

這樣可以完全避免類似問題。

責任編輯:姜華 來源: 阿丸筆記
相關推薦

2018-11-08 10:53:43

sshscp服務器

2022-10-10 08:05:34

線程池OOM問題

2020-02-04 17:42:17

寬帶運營商攜號轉網

2020-04-14 10:06:20

微服務Netflix語言

2023-02-27 16:24:17

架構開發數字化

2023-03-29 08:24:30

2023-02-27 08:10:16

2023-03-02 12:32:36

2021-01-11 11:14:35

微服務架構調用

2020-02-18 11:19:36

物聯網病毒物聯網IOT

2021-10-17 20:38:30

微服務內存組件

2023-03-10 08:24:27

OOMdump線程

2009-11-13 13:42:38

ADO.NET數據服務

2022-10-31 09:30:32

kafkaconsumer服務端

2020-09-29 12:15:13

生死鎖MySQL

2021-06-04 11:10:04

JavaScript開發代碼

2021-04-18 18:14:44

Windows 10Windows微軟

2010-04-20 09:55:37

2013-04-18 09:56:05

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲女人天堂成人av在线 | 日韩国产精品一区二区三区 | 日韩精品在线看 | 免费看一区二区三区 | 午夜视频在线免费观看 | 欧美成人影院 | 日本精品视频 | 天天色官网 | 看羞羞视频 | 亚洲一区二区三区在线 | 成人在线一区二区 | 日本网站在线看 | 亚洲欧美一区在线 | 国产1区2区在线观看 | 亚洲不卡在线观看 | 精品国产一区久久 | av在线播放国产 | 日本a在线| 夜夜爽99久久国产综合精品女不卡 | 日韩a| 精品一二三区视频 | 国产传媒视频在线观看 | 在线中文字幕亚洲 | 国产精品国产精品国产专区不卡 | 高清久久久 | 亚洲欧洲中文 | 日日操夜夜操天天操 | 九九综合| av在线三级 | 午夜av电影| av激情影院| 成人在线中文字幕 | 久热精品视频 | 国产人成在线观看 | 亚洲欧美一区二区三区在线 | 超碰成人在线观看 | 欧美成人免费在线 | 久久精品毛片 | 狠狠做六月爱婷婷综合aⅴ 国产精品视频网 | 国产精品免费一区二区 | 国产一区 在线视频 |