DAOS 通過兩個緊密整合的平面進行運轉。資料平面處理繁重的運輸操作,而控制平面負責程式編排和儲存管理,簡化資料平面的操作。
模組介面
I/O 引擎支援一個模組介面,該介面允許按需載入伺服器端程式碼。每個模組實際上都是一個庫,由 I/O 引擎通過 dlopen 動態載入。模組和 I/O 引擎之間的介面在 dss_module
資料結構中定義。
每個模組應指定:
- 模組名
daos_module_id
中的模組識別符號- 特徵位掩碼
- 一個模組初始化和銷燬函式
此外,模組還可以選擇配置:
- 在整個堆疊啟動並執行後呼叫的配置和清理函式
- CART RPC 處理程式
- dRPC 處理程式
執行緒模型與 Argobot 整合
I/O 引擎是一個多執行緒程式,使用 Argobot 進行非阻塞處理。
預設情況下,每個 Target 都會建立一個 main xstream 和 no offload xstreams。offload xstream 的實際數量可以通過 daos_engine 命令列引數進行配置。此外,還建立了一個額外的 xstream 來處理傳入的後設資料請求。每個 xstream 都繫結到一個特定的 CPU 核心。main xstream 接收來自客戶端和其他伺服器的 Target 傳入請求。一個特定的 ULT (User Level Thread) 會在網路和 NVMe I/O 操作方面提供幫助。
Thread-local Storage (TLS)
每個 xstream 分配的私有儲存可以通過 dss_tls_get()
函式進行訪問。
註冊時,每個模組可以指定一個模組金鑰,該金鑰的資料結構大小將由 TLS 中的每個 xstream 進行分配。
dss_module_key_get()
函式的作用是:返回特定註冊模組金鑰的資料結構。
Incast Variable 整合
DAOS 使用 IV (incast variable) 在單個 IV 名稱空間(組織結構為樹)下的伺服器之間共享值和狀態。樹的根節點稱為 IV leader,伺服器可以是葉子節點也可以是非葉子節點。
每個伺服器都維護自己的 IV 快取。在獲取過程中,如果本地快取不能完成請求,它會將請求轉發給其父快取,直到到達根快取 (IV leader)。對於更新操作,伺服器首先更新它的本地快取,然後轉發到它的父快取,直到到達根快取,然後將更改傳播到其他的伺服器。
IV 名稱空間是屬於每個 Pool 的,在 Pool 連線期間建立,在 Pool 斷開連線期間銷燬。
要使用 IV,每個使用者需要在 IV 名稱空間下注冊自己以獲得識別符號,然後使用者將使用這個 ID 來獲取或更新自己在 IV 名稱空間下的 IV 值。
dRPC 伺服器
I/O 引擎包括一個 dRPC 伺服器,它監聽給定 Unix Domain Socket 上的活動。
有關 dRPC 的基礎知識以及 Go 和 C 中的底層 API 的更多詳細資訊,請參閱 dRPC Documentation。
dRPC 伺服器定期輪詢傳入的客戶端連線和請求。它可以通過 struct drpc_progress_context
物件同時處理多個客戶端連線,該物件管理監聽 Socket 的 struct drpc
物件以及任何活動的客戶端連線。
伺服器在 xstream 0 自己的 ULT (User Level Thread) 中迴圈執行。dRPC Socket 已設定為非阻塞的,並且使用無超時輪詢。這允許伺服器在 ULT 中執行,而不是在自己的 xstream 中執行,預計該通道的流量相對較低。
dRPC 程式
drpc_progress
表示 dRPC 伺服器迴圈的一次迭代。其工作流程如下:
- 在監聽 Socket 和任何開啟的客戶端連線上同時進行超時輪詢。
- 如果在客戶端連線上看到任何活動:
- 如果資料已輸入:呼叫
drpc_recv
處理輸入的資料。 - 如果客戶端已斷開連線或連線被破壞:釋放
struct drpc
物件並將其從drpc_progress_context
中刪除。
- 如果資料已輸入:呼叫
- 如果在監聽器上發現任何活動:
- 如果有新的連線進入:呼叫
drpc_accept
並將新的struct drpc
物件新增到drpc_progress_context
中的客戶端連線列表中。 - 如果有錯誤:將
-DER_MISC
返回給呼叫者。I/O 引擎中會記錄該錯誤,但不會中斷 dRPC 伺服器迴圈。在監聽器上獲取到錯誤是意外情況。
- 如果有新的連線進入:呼叫
- 如果沒有看到任何活動,則將
-DER_TIMEDOUT
返回給呼叫者。這純粹是為了除錯目的,實際上,I/O 引擎會忽略此錯誤程式碼,因為缺少活動實際上並不是一種錯誤。
dRPC 處理程式註冊
單個 DAOS 模組可以通過註冊一個或多個 dRPC 模組 ID 的處理函式來實現對 dRPC 訊息的處理。
註冊處理程式很簡單。在 dss_server_module
的欄位 sm_drpc_handlers
中,靜態分配一個 struct dss_drpc_handler陣列,該陣列的最後一項為零,以指示列表的結尾。將欄位設定為 NULL 表示沒有要註冊的處理程式。當 I/O 引擎載入 DAOS 模組時,它將自動註冊所有 dRPC 處理程式。
注意:
- dRPC 模組 ID 與 DAOS 模組 ID 不同。
- 這是因為給定的 DAOS 模組可能需要註冊多個 dRPC 模組 ID,具體數量取決於 DAOS 模組所涵蓋的功能。
- dRPC 模組 ID 必須是系統範圍內唯一的,並且列在一箇中心標頭檔案 `src/include/daos/drpc_modules.h 中。
dRPC 伺服器使用函式 drpc_hdlr_process_msg
來處理傳入的訊息。此函式檢查傳入訊息的模組 ID,搜尋處理程式。
- 如果找到處理程式,則執行該處理程式,並返回
Drpc_Response
。 - 如果找不到,它將生成自己的
Drpc_Response
,指示模組 ID 未註冊。
相關資訊
GitHub: https://github.com/storagezhang
Emai: debugzhang@163.com
華為雲社群: https://bbs.huaweicloud.com/blogs/255571
DAOS: https://github.com/daos-stack/daos
本文翻譯自 https://github.com/daos-stack/daos/blob/master/src/control/README.md