非正式全面解析 NebulaGraph 中 Session 管理

image

NebulaGraph 論壇最近有些討論帖,各種姿勢(shì)來問 NebulaGraph Session 管理相關(guān)的事情,我尋思這也不是一個(gè)法子,還是來寫一篇文章來講述下 NebulaGraph 中的 Session 管理。由于本文設(shè)定為非正式的 Session 講解,所以本文主要分為理論和實(shí)操部分,在實(shí)操部分主要摘錄了論壇用戶的一些關(guān)于 Session 的理解,以及本人對(duì) Session 相關(guān)問題的解答。

客戶端交互流程

在之前的源碼解讀系列的客戶端部分,我們講過 Session 相關(guān)的知識(shí)點(diǎn),這里來回顧下。

通過下圖你能了解客戶端和服務(wù)端連接時(shí),背后的工作原理:

image

簡單來說,整個(gè) workflow 由 ConnectionPool、Session、Connection 構(gòu)成,用戶通過 Session 和計(jì)算引擎進(jìn)行交互,但真正和計(jì)算引擎 graphd 發(fā)生數(shù)據(jù)處理關(guān)系的是連接池當(dāng)中的 Connection。

Connection Pool

在連接池初始化階段,用戶使用 Session 之前需要先創(chuàng)建并初始化一個(gè)連接池 ConnectionPool,連接池會(huì)在初始化時(shí)會(huì)對(duì)用戶指定的 NebulaGraph 服務(wù)所在地址建立連接 Connection。如果在用集群部署方式部署了多個(gè) Graph 服務(wù),連接池會(huì)采用輪詢的策略來平衡負(fù)載,對(duì)每個(gè)地址建立近乎等量的連接。

連接池如何管理連接 Connection 呢?連接池內(nèi)維護(hù)了兩個(gè)隊(duì)列,空閑連接隊(duì)列 idleConnectionQueue 和使用中的連接隊(duì)列 activeConnectionQueue,連接池會(huì)定期檢測(cè)過期空閑的連接并將其關(guān)閉。這兩個(gè)隊(duì)列在增刪元素的時(shí)候會(huì)通過讀寫鎖來確保多線程執(zhí)行的正確性。當(dāng) Session 向連接池請(qǐng)求連接時(shí),會(huì)檢查空閑連接隊(duì)列中是否有可用的連接,如果有則直接返回給 Session 供用戶使用;如果沒有可用連接并且當(dāng)前的總連接數(shù)沒有超過配置中限定的最大連接數(shù) maxConnSize,則新建一個(gè)連接給 Session;如果已經(jīng)到達(dá)了最大連接數(shù)的限制,返回錯(cuò)誤。

大概流程和下面流程圖類似:

image

一般來說,只有在客戶端程序退出時(shí)才需要關(guān)閉連接池,在關(guān)閉時(shí)池中所有的連接都會(huì)被斷開。

Session

image

客戶端會(huì)話 Session 通過連接池 ConnectionPool 生成,用戶需要提供用戶密碼進(jìn)行校驗(yàn),在校驗(yàn)成功后用戶會(huì)獲得一個(gè) Session 實(shí)例,并通過 Session 中的連接與服務(wù)端進(jìn)行通信。最常用的接口是 execute(),如果在執(zhí)行時(shí)發(fā)生錯(cuò)誤,客戶端會(huì)檢查錯(cuò)誤的類型。如果是網(wǎng)絡(luò)原因或者和 session 通信的 graph 服務(wù) down 掉,客戶端會(huì)自動(dòng)重連,嘗試綁定一個(gè)可用的連接重發(fā)請(qǐng)求。

需要注意的是,一個(gè) Session 不支持被多個(gè)線程同時(shí)使用,正確的方式是用多個(gè)線程申請(qǐng)多個(gè) Session,每個(gè)線程使用一個(gè) Session。Session 被釋放時(shí),其持有的連接會(huì)被放回到連接池的空閑連接隊(duì)列 idleConnectionQueue中,以便于之后被其他 Session 復(fù)用。

Connection

連接 Connection 每個(gè)連接實(shí)例都是等價(jià)的,可以被任意 Session 持有。這樣設(shè)計(jì)的目的是這些連接可以被不同的 Session 復(fù)用,減少反復(fù)開關(guān) Transport 的開銷。連接會(huì)將客戶端的請(qǐng)求發(fā)送到服務(wù)端并將其結(jié)果返回給 Session。

社區(qū)用戶實(shí)踐

這里主要收錄了用戶在使用連接池、Session 遇到的比較有代表性的問題。

如何獲取多個(gè) Session

可通過 https://discuss.nebula-graph.com.cn/t/topic/3765 查看完整的交流對(duì)話。

Sharry2021gu 提問:連接池怎么會(huì)有多個(gè) Session 呢?用來測(cè)試并發(fā)性能。像下面的 pipeline 里怎么才能獲取不同的 session?

image

答:因?yàn)槟憬o Session 包了一層,你直接用 java-client 的 ConnectionPool 拿 Session 就可以了,ConnectionPool 是支持多線程調(diào)用 getSession 的接口。

對(duì) Session 管理的理解

下面部分收錄社區(qū)用戶 wuyou 對(duì) Session 管理的理解,你可以通過 https://discuss.nebula-graph.com.cn/t/topic/8777 了解全部內(nèi)容。這塊的內(nèi)容同上面客戶端交互流程有所重疊,不過都是需要注意的使用點(diǎn)。

  1. NebulaPool 的 maxConnSize 是最大連接數(shù),一個(gè) Session 只能使用一個(gè)連接,可以簡單地認(rèn)為 maxConnSize 就是這個(gè) NebulaPool 里面支持的最大 Session 數(shù)量,適當(dāng)調(diào)整就行了;

  2. NebulaPool 使用常規(guī)的單例就行,應(yīng)用程序結(jié)束時(shí)記得關(guān)閉就行了。Session 的話可以在 graph 配置中設(shè)置 session_idle_timeout_secs 讓其自動(dòng)銷毀就行了;

  3. Session 的創(chuàng)建和銷毀是有開銷的,會(huì)有五次 IO 交互:Client 和 Graphd 會(huì)有 3 次 IO 交互以及 Graphd 和 Metad 有 2 次 IO 交互。

    1. Client 和 Graphd IO 交互:
      1. 第一次是檢測(cè)連接是否是正常的;
      2. 第二次是做一次認(rèn)證獲取 sessionId;
      3. 第三次是 USE SPACE;
    2. Graphd 和 Metad IO 交互:
      1. 第一次是生成 sessionId;
      2. 第二次是獲取 space 信息。
        所以,一般情況下不建議每次請(qǐng)求都從 pool getSession,execute 之后再 release,這會(huì)有性能開銷,而且還會(huì)在服務(wù)端生成很多只用一次的 Session。
  4. Session 是線程不安全的,多個(gè)線程使用同一 Session 會(huì)直接報(bào)錯(cuò)。應(yīng)對(duì)多線程可以自己維護(hù)一份 Session 列表。如果是多個(gè) space 的話,可以針對(duì)每個(gè) space 維護(hù)一份 session 列表。這一點(diǎn)目前需要自己實(shí)現(xiàn),暫時(shí)沒有官方的好的方式。

自維護(hù) Session

wuyou 提問:官方說需要自己維護(hù) Session 是什么意思,感覺 NebulaPool 已經(jīng)在維護(hù)了,應(yīng)用層只需要每次直接 getSession 就完事兒了,每次執(zhí)行完 nGQL 之后 session.release 釋放掉 Session,讓其回到 pool 中就可以。

答:這里解釋下如何理解需要自己維護(hù) Session。NebulaPool 維護(hù)的只是 Connection,Connection 是無狀態(tài)的。Session 的維護(hù)是指多線程使用的情況下復(fù)用 Session 做多次查詢,比如:Session 內(nèi)部分 sessionInUse 和 idleSession隊(duì)列,新建的 Session 放 idle 隊(duì)列,用的時(shí)候起一個(gè)線程持有這個(gè) Session 并且移到 inUse 隊(duì)列,用完之后不用釋放 Session 放回 idleSession 供下次使用。

Connection 的釋放

wuyou 提問:放回連接池的 Connection 什么時(shí)候會(huì)被釋放?

答:有兩種方式來釋放 Connection。第一種,手動(dòng)關(guān)閉連接池時(shí)里面的連接會(huì)被釋放。另外一種是,連接池里的對(duì)象池通過 setSoftMinEvictableIdleTimeMillis() 自動(dòng)定期釋放。

空閑會(huì)話超時(shí)設(shè)置

可通過 https://discuss.nebula-graph.com.cn/t/topic/9037 查看完整的交流對(duì)話。

Ian 提問:設(shè)置空閑會(huì)話超時(shí)時(shí)間為 8 小時(shí),是以 SHOW SESSIONS 結(jié)果的 update_time 來加 8 小時(shí)嗎?如果一直在用,就不會(huì)過期?

答:是 udpate_time + 8H。使用過程中 session 的 idle time 會(huì)更新,如果你一直在用會(huì)話就不會(huì)過期。


謝謝你讀完本文 (///▽///)

要來近距離體驗(yàn)一把圖數(shù)據(jù)庫嗎?現(xiàn)在可以用用 NebulaGraph Cloud 來搭建自己的圖數(shù)據(jù)系統(tǒng)喲,快來節(jié)省大量的部署安裝時(shí)間來搞定業(yè)務(wù)吧~ NebulaGraph 阿里云計(jì)算巢現(xiàn) 30 天免費(fèi)使用中,點(diǎn)擊鏈接來用用圖數(shù)據(jù)庫吧~

想看源碼的小伙伴可以前往 GitHub 閱讀、使用、(з)-☆ star 它 -> GitHub;和其他的 NebulaGraph 用戶一起交流圖數(shù)據(jù)庫技術(shù)和應(yīng)用技能,留下「你的名片」一起玩耍呢~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容