在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

詳解zookeeper的session管理機制

馬哥Linux運維 ? 來源:稀土掘金技術社區 ? 2024-01-08 09:46 ? 次閱讀

使用過zookeeper的都知道,當我們使用zookeeper創建一個節點時,我們能選擇節點的類型是“臨時節點”還是“永久節點”。臨時節點和永久節點的區別是,臨時節點會在客戶端斷開連接時被刪除,而永久節點無論客戶端是否斷開連接,都會保留。

臨時節點非常重要,我們經常利用它來實現分布式鎖、選舉等等

而為了實現臨時節點的功能,zookeeper服務端就勢必要有一套高效的session管理機制,它能實現如下功能:當客戶端session失效后,服務端能感知到,隨后刪掉客戶端當前創建的臨時節點,并通知給其他的客戶端。這篇文章會深入探討zookeeper的session管理機制。

zookeeper的心跳機制

為什么要有心跳機制

zookeeper底層支持兩種網絡庫,一種是zookeeper基于NIO自己寫的,一種是Netty。那么zookeeper能不能直接通過感知TCP連接是否斷開來感知客戶端連接是否斷開呢?

答案是不能,原因有很多,個人覺得最重要的一點是,基于TCP連接來判斷客戶端是否存活是不靠譜的

這里舉兩個異常case 1、客戶端進程直接crash了,還沒來得及發送FIN報文,這種情況下,zookeeper在TCP這一側是沒辦法及時感知到TCP連接已經失效了。(也就是說,由于zookeeper沒收到client的FIN包,雖然client已經掛了,TCP側還認為客戶端還活著。只能等弱雞keepalive了)

168ceda2-ad48-11ee-8b88-92fbcf53809c.jpg

2、客戶端和服務端之間很久沒有報文交互,TCP連接其實已經失效了。(失效原因很多,比如路由器出問題了,網絡設備故障了等等)這時候,如果客戶端發送報文給服務端,linux會進行重試,默認差不多要重試15分鐘,才能感知到這個連接已經失效。

16acafb6-ad48-11ee-8b88-92fbcf53809c.jpg這里只是舉個例子。實際來說,client和zookeeper的報文交互可能不會那么少。也就是第二種情況,客戶端很久不給服務端發報文,要發了,才發現tcp連接已經有問題了,這種情況不太可能出現。(當然,選舉這種場景是有可能出現這種情況的,后面會單獨寫文章分析這個case) 但是從上面兩個例子,我們也不難得出結論,通過tcp連接的斷開與否來感知客戶端是否存活,似乎并不太靠譜

client發送心跳

因為tcp的“不靠譜”,zookeeper為了能夠實現可靠的連接管理(也為了保活),選擇自己實現心跳機制。

175356fe-ad48-11ee-8b88-92fbcf53809c.jpg

正如上圖所示,client隔一段時間就會發送一個心跳報文給服務端,告訴zookeeper自己還活著,別把我連接關了。

注意:這里亂入了一個create報文,因為正常報文也算是一種“心跳”。反正,zookeeper只要能收到報文,就能知道客戶端還活著。

服務端收到報文后,會更新session信息

這里帶大家看看代碼。很簡單,收到報文后,會調用SessionTracker.touchSession()來更新session信息

sessionId是zookeeper為每一個連接分配的唯一id

176b9476-ad48-11ee-8b88-92fbcf53809c.jpg

管理session的難點在哪

zookeeper 管理session的需求分析

這里我們思考下zookeeper對于session管理的需求是什么?

1、zookeeper需要有個地方存session

2、當客戶端一段時間沒發生心跳時,zookeeper要能感知到

第一個問題比較簡單,java提供了各式各樣的集合,無論是Map或者是List理論上都能存session。由于我們一般是通過sessionId來找到關聯的Session的,因此使用Map更合適點。Zookeeper也是這么做的protected final ConcurrentHashMap sessionsById這里sessionsById 就是zookeeper管理Session使用的容器

第二個問題看起來也很簡單,客戶端不是會發送心跳么?我給每一個session記錄一個上一個報文到達時間,一旦收到新的報文,我就更新這個時間。然后我再不斷地掃描每個session是否很久沒收到報文不就行了?

如何檢測Session失效?

1787d78a-ad48-11ee-8b88-92fbcf53809c.jpg按照上面的說法,收到一個報文,我就更新Session的“上次報文”字段。假設session失效時間是4秒,我就每隔4秒掃描一次session的集合,找出那個超過4秒沒有新的報文的session不就行了?像上圖一樣,假設sessionTimeout是4秒,現在已經11點50分05秒了,理論上每個session上一個報文時間應該大于11點50分01秒。很明顯,session1失效了。

定時任務的選型

既然要定時掃描,我們就需要跑一個定時任務。jdk本身也提供了很多的定時任務方案。不知道定時任務的同學可以參考這篇文章Java中定時任務的6種實現方式,你知道幾種?- 掘金既然如此,我們完全可以使用jdk自帶的定時任務,定時去掃描這個集合啊,這樣不就能很輕易的找到失效的session了么?

這里有兩個問題:1、每一個客戶端和服務端的連接,sessionTimeout都是可配的。我們例子是4秒沒收到報文,就認為連接失效。實際超時時間可能有1秒、2秒、3秒.... 所以如果用定時任務來實現,我們可能需要啟動不止一個定時任務。2、jdk提供的定時任務不夠靈活,什么意思呢。比如我設置的sessionTimeout是4秒,現在是11點。然后我在11點00分02秒就收到了一個心跳,那么下次檢測時間應該變成11點00分06秒。而jdk的定時任務限定了,只能每隔4秒檢測一次。比如:11點、11點00分04秒、11點00分08秒、這樣檢測下去。而如果用jdk的定時任務,我們只能簡單的隔一段時間,檢測一次。這里可以仔細體會下兩者的差異。

想一想這些問題,是不是發現想實現一個高效的session管理機制是不是沒那么簡單。接下來我們看看,zookeeper是如何巧妙地實現session的管理。

zookeeper session管理機制

接下來就要介紹zookeeper的session管理機制了。

1、通過expiryMap存儲過期時間與session集合的對應關系

首先,zookeeper內部有一個expiryMap

17a02a24-ad48-11ee-8b88-92fbcf53809c.jpg

非常簡單,Key是過期時間,value是一個Set,里面放了一個個的Session。

舉個例子:S1在11點50分02秒的key下面,表示如果11點50分02秒前沒收到新的報文,就認為S1過期了。

2、當收到某條連接的報文時,更新expiryMap

拿上圖的S1為例,它的sessionTimeout是4秒,在11點50分01秒收到報文。那么理論上下個session檢測時間會是 11點50分05秒。

這里要說下expiryMap的第一個特征,它的key并不是隨意一個時間。它會間隔一個固定的時間叫做expirationInterval,數值上它等于zookeeper的配置tickTime(默認配的2秒)

所以說,這里計算出11點50分05秒后,它會round下,round到11點50分06秒

如圖所示:

17b94a0e-ad48-11ee-8b88-92fbcf53809c.jpg

S1在截止時間前更新了session,我們就要把它從舊的桶里移除,挪到新的桶里。

3、循環檢測ExpiryMap

有個SessionTracker線程會循環檢測這個expiryMap,找到最近的那個key對應的session集合,把他們全部都過期掉。

17dc0b98-ad48-11ee-8b88-92fbcf53809c.jpg就像上面的例子,一旦時間到了11點50分02秒,就把對應的session全部過期掉。

小結下

1、如果收到報文,會把session放到下一個過期桶里。2、SessionTracker會按次序,不斷地取出過期的桶,把桶里的session全部過期掉(過期會刪除臨時節點,當然還有其他一系列操作) 3、zookeeper底層使用了非常簡單的Map就實現了非常高效的Session管理機制。

session管理機制源碼分析

接下來我們來看看源碼

1、server端的心跳續約


//org.apache.zookeeper.server.ExpiryQueue#update
public Long update(E elem, int timeout) {
  //1、除了上面我們介紹的ExpiryMap,zookeeper內部還有一個elemMap,用于存放 Session -> 過期時間
  Long prevExpiryTime = elemMap.get(elem);
  long now = Time.currentElapsedTime();
  //2、收到心跳后,我們會計算session應該更新到哪個桶里
  Long newExpiryTime = roundToNextInterval(now + timeout);


  //桶不變,就不用更新expiryMap了
  if (newExpiryTime.equals(prevExpiryTime)) {
    // No change, so nothing to update
    return null;
  }


  // First add the elem to the new expiry time bucket in expiryMap.
  //3. 找到新的桶,插入進去
  Set set = expiryMap.get(newExpiryTime);
  if (set == null) {
    // Construct a ConcurrentHashSet using a ConcurrentHashMap
    set = Collections.newSetFromMap(new ConcurrentHashMap());
    // Put the new set in the map, but only if another thread
    // hasn't beaten us to it
    Set existingSet = expiryMap.putIfAbsent(newExpiryTime, set);
    if (existingSet != null) {
      set = existingSet;
    }
  }
  set.add(elem);


  // Map the elem to the new expiry time. If a different previous
  // mapping was present, clean up the previous expiry bucket.
  prevExpiryTime = elemMap.put(elem, newExpiryTime);
  //4. 從舊的桶里移除
  if (prevExpiryTime != null && !newExpiryTime.equals(prevExpiryTime)) {
    Set prevSet = expiryMap.get(prevExpiryTime);
    if (prevSet != null) {
      prevSet.remove(elem);
    }
  }
  return newExpiryTime;
}


其實就是這幅圖 1、放入一個:Session -> 過期時間 的Map中 2、收到心跳后,我們會計算session應該更新到哪個桶里 3、找到新的桶,插入進去 4、把session從舊的桶里移除

2、SessionTracker不斷地輪訓,找到過期的Session集合,然后都過期掉

//org.apache.zookeeper.server.SessionTrackerImpl#run
@Override
public void run() {
  try {
    while (running) {
      //1. 這個其實就是不斷地輪訓下一個要檢測的key
      // 比如按我們的例子,應該是11點50分02秒檢測一次、11點50分04秒檢測一次、11點50分06秒檢測一次...
      // 這里的waitTime就是找到下次檢測需要等待多久,比如現在是11點50分01秒了,這個waitTime就是1秒
      // 如果是11點50分02秒了,waitTime就是0,我們要開始把過期的session都失效掉了
      long waitTime = sessionExpiryQueue.getWaitTime();
      if (waitTime > 0) {
        Thread.sleep(waitTime);
        continue;
      }


      //2. 取出過期的Session集合,全部都expire掉,如果session都及時發送了心跳了,這里就會拿到一個空的集合
      for (SessionImpl s : sessionExpiryQueue.poll()) {
        ServerMetrics.getMetrics().STALE_SESSIONS_EXPIRED.add(1);
        setSessionClosing(s.sessionId);
        expirer.expire(s);
      }
    }
  } catch (InterruptedException e) {
    handleException(this.getName(), e);
  }
  LOG.info("SessionTrackerImpl exited loop!");
}


17dc0b98-ad48-11ee-8b88-92fbcf53809c.jpg其實就是這個圖

審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 路由器
    +關注

    關注

    22

    文章

    3745

    瀏覽量

    114480
  • TCP
    TCP
    +關注

    關注

    8

    文章

    1378

    瀏覽量

    79303
  • 客戶端
    +關注

    關注

    1

    文章

    290

    瀏覽量

    16766
  • zookeeper
    +關注

    關注

    0

    文章

    34

    瀏覽量

    3712

原文標題:深入詳解zookeeper的session管理機制

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    控制器中如何設計MMU--虛擬內存管理機制

    控制器中如何設計MMU--虛擬內存管理機制
    發表于 12-15 09:53

    安卓應用商店和APP市場管理機制

    “工信部正在搭建移動應用軟件認證和管理服務,以加強對智能終端的安全管理。”工信部相關負責人昨日表示,目前為了解決智能終端的安全問題,內部確實已經明確了需要一套對安卓應用商店和APP市場管理機制,包括上線前的審核和上線后的監測和抽
    發表于 07-15 07:41

    Keil C動態內存管理機制分析及改進,不看肯定后悔

    Keil C動態內存管理機制分析及改進,不看肯定后悔
    發表于 04-25 08:48

    怎么給RTOS動態分區內存管理機制進行優化?

    怎么給RTOS動態分區內存管理機制進行優化?
    發表于 04-28 06:17

    嵌入式系統所用到的內存管理機制主要有哪幾種

    嵌入式系統所用到的內存管理機制主要有以下兩種: 1、虛擬內存管理機制: 有一些嵌入式處理器提供了MMU,在MMU具備內存地址映射和尋址功能,它使操作系統的內存管理更加方便。如果存在MMU ,操作系統
    發表于 12-17 06:34

    命令終端的常用操作有哪些?軟件包管理機制是什么

    一.命令終端(terminal)常用操作:ctrl+shift +t,在終端上打開多個標簽ctrl+alt+t,在終端上打開另外一個終端二.deb軟件包管理1.Debian 軟件包的管理機制 Deb
    發表于 12-21 06:38

    VxWorks內存管理機制的分析與研究

    實時性、可靠性是嵌入式開發對內存管理的基本要求,本文探討了操作系統內存管理的主要問題,對嵌入式操作系統Vxworks 的內存管理機制進行分析,給出了Vxworks 高效內存管理
    發表于 01-07 12:35 ?23次下載

    linux內存管理機制淺析

    本內容介紹了arm linux內存管理機制,詳細說明了linux內核內存管理,linux虛擬內存管理,arm linux內存管理等方面的知識
    發表于 12-19 14:09 ?73次下載
    linux內存<b class='flag-5'>管理機制</b>淺析

    TMS320F28x 事件管理機制參考

    DSP之TMS320F28x事件管理機制參考,很好的DSP自學資料,快來學習吧。
    發表于 04-15 14:48 ?15次下載

    最全SPARK內存管理機制

    最全SPARK內存管理機制
    發表于 09-08 14:17 ?5次下載
    最全SPARK內存<b class='flag-5'>管理機制</b>

    嵌入式系統內存管理機制詳解

    操作系統的內存管理功能用于向操作系統提供一致的地址映射功能和內存頁面的申請、釋放操作。在嵌入式實時系統中,內存管理根據不同的系統,有不同的策略,對于有些系統支持的虛擬內存管理機制,對于另外一些系統,可能只有flat式的簡單內存
    發表于 11-18 09:41 ?4566次閱讀

    淺析物理內存與虛擬內存的關系及其管理機制

    本文主要介紹內存管理機制:物理內存與虛擬內存的關系,Linux內存管理機制,Python內存管理機制,Nginx內存管理機制,環形緩沖區機制
    的頭像 發表于 04-12 09:55 ?5555次閱讀
    淺析物理內存與虛擬內存的關系及其<b class='flag-5'>管理機制</b>

    xenomai系統中的xnheap管理機制

    本文分析的enomai系統中的內存池(xnheap)管理機制
    的頭像 發表于 05-25 10:15 ?1797次閱讀

    zookeeper引入什么機制

    Zookeeper是一個開源的分布式協調服務,被廣泛應用于構建分布式系統和大規模集群的管理。作為一個分布式協調服務,Zookeeper引入了一系列機制來提供可靠的協調和一致性服務。在這
    的頭像 發表于 12-03 16:38 ?916次閱讀

    zookeeper的選舉機制

    ZooKeeper是一個分布式協調服務,主要用于管理分布式系統中的配置信息、命名服務、分布式鎖和分布式隊列等。在ZooKeeper集群中,為了保證高可用性,需要選舉出一個主節點(Leader),其他
    的頭像 發表于 12-04 10:39 ?1078次閱讀
    主站蜘蛛池模板: 久久免费精品 | 亚洲网站免费观看 | 欧美色图俺去了 | 轻点灬大ji巴太大太深了 | 91久操| 欧美性hd | 精品四虎免费观看国产高清 | 国产精品igao在线观看樱花日本 | 性毛片| 男人的午夜影院 | 91三级在线 | 看片在线 | 亚洲一在线 | 久久网站免费观看 | 337p欧洲亚洲大胆艺术 | 成色视频| 都市激情综合网 | 午夜私人影院 | 日本一区二区三区不卡在线看 | aa级毛片| 一级片免费在线观看 | 网女色| 手机在线观看毛片 | 1000又爽又黄禁片在线久 | 久久这里只有精品任你色 | 亚洲三级电影在线播放 | 奇米影视四色7777久久精品 | 高清视频黄色录像免费 | 狠狠干天天色 | 欧美成人免费夜夜黄啪啪 | 四虎精品免费永久在线 | a级男女性高爱潮高清试 | 亚洲美女视频在线观看 | 俺来也俺去啦久久综合网 | 国产精品嫩草影院人体模特 | 国模论坛 | 久久精品美女久久 | 四虎永久在线观看视频精品 | 99久久免费精品高清特色大片 | 九九热视频免费在线观看 | 五月婷婷色 |