Databend 源碼閱讀系列(二):Query server 啟動(dòng),Session 管理及請求處理
query 啟動(dòng)入口
Databend-query server 的啟動(dòng)入口在?databend/src/binaries/query/main.rs?下,在初始化配置之后,它會(huì)創(chuàng)建一個(gè)?GlobalServices
?和 server 關(guān)閉時(shí)負(fù)責(zé)處理 shutdown 邏輯的?shutdown_handle
GlobalServices
GlobalServices
?負(fù)責(zé)啟動(dòng) databend-query 的所有全局服務(wù),這些服務(wù)都遵循單一責(zé)任原則。
GlobalServices
?中的全局服務(wù)都實(shí)現(xiàn)了單例 trait,這些全局管理器后續(xù)會(huì)有對(duì)應(yīng)的源碼分析文章介紹,本文介紹與 Session 處理相關(guān)的邏輯。
ShutdownHandle
接下來會(huì)根據(jù)網(wǎng)絡(luò)協(xié)議初始化 handlers,并把它們注冊到?shutdown_handler
?的 services 中,任何實(shí)現(xiàn) Server trait 的類型都可以被添加到 services 中。

目前 Databend 支持三種協(xié)議提交查詢請求(mysql, clickhouse http, raw http)。
之后會(huì)創(chuàng)建一些其它服務(wù)
Metric service: 指標(biāo)服務(wù)
Admin service: 負(fù)責(zé)處理管理信息
RPC service: query 節(jié)點(diǎn)的 rpc 服務(wù),負(fù)責(zé) query 節(jié)點(diǎn)之間的通信,使用 arrow flight 協(xié)議
最后會(huì)將這個(gè) query 節(jié)點(diǎn)注冊到 meta server 中。
Session 相關(guān)
session 主要分為 4 個(gè)部分
session_manager: 全局唯一,負(fù)責(zé)管理 client session
session: 每當(dāng)有新的 client 連接到 server 之后會(huì)創(chuàng)建一個(gè)新的 session 并且注冊到 session_manager
query_ctx: 每一條查詢語句會(huì)有一個(gè) query_ctx,用來存儲(chǔ)當(dāng)前查詢的一些上下文信息
query_ctx_shared: 查詢語句中的子查詢共享的上下文信息

下面逐一來分析
SessionManager (query/src/sessions/session_mgr.rs)
SessionManager
?主要用來創(chuàng)建和銷毀 session,對(duì)應(yīng)方法如下
Session (query/src/sessions/session.rs)
session 主要存儲(chǔ) client-server 的上下文信息,代碼命名已經(jīng)很清晰了,這里就不再過多贅述。
Session
?的另一個(gè)大的功能是負(fù)責(zé)創(chuàng)建和獲取?QueryContext
,每次接收到新的 query 請求都會(huì)創(chuàng)建一個(gè)?QueryContext
?并綁定在對(duì)應(yīng)的 query 語句上。
QueryContext (query/src/sessions/query_ctx.rs)
QueryContext 主要是維護(hù)查詢的上下文信息,它通過?QueryContext::create_from_shared(query_ctx_shared)
創(chuàng)建。
其中?partition_queue
?主要存儲(chǔ)查詢對(duì)應(yīng)的 PartInfo,包括 part 的地址、版本信息、涉及數(shù)據(jù)的行數(shù),part 使用的壓縮算法、以及涉及到 column 的 meta 信息。在 pipeline build 時(shí)候會(huì)去設(shè)置 partition。pipeline 后續(xù)會(huì)有專門的文章介紹。?
precommit_blocks
?負(fù)責(zé)暫存插入操作的時(shí)已經(jīng)寫入到存儲(chǔ), 但是尚未提交的元數(shù)據(jù),DataBlock
?主要包含 Column 的元信息引用和 arrow schema 的信息。
QueryContextShared (query/src/sessions/query_ctx_shared.rs)
對(duì)于包含子查詢的查詢,需要共享很多上下文信息,這就是?QueryContextShared
存在的理由。
它提供了 query 上下文所需要的一切基本信息。
Handler
之前提到了 Databend 支持多種 handler,下面就以 mysql 為例,看一下 handler 的處理流程以及如何與 session 產(chǎn)生交互。 首
先?MySQLHandler
?會(huì)包含一個(gè)?SessionManager
?的引用
MySQLHandler
?在啟動(dòng)后,會(huì) spawn 一個(gè) tokio task 來持續(xù)監(jiān)聽 tcp stream,并且創(chuàng)建一個(gè) session 再啟動(dòng)一個(gè) task 去執(zhí)行之后的查詢請求。
在?MySQLConnection::run_on_stream
中,session 會(huì)先 attach 到對(duì)應(yīng)的 client host 并且注冊一個(gè) shutdown 閉包來處理關(guān)閉連接關(guān)閉時(shí)需要執(zhí)行的清理,關(guān)鍵代碼如下:
之后會(huì)啟動(dòng)一個(gè) MySQL InteractiveWorker 來處理后續(xù)的查詢。
該?InteractiveWorker
會(huì)實(shí)現(xiàn)?AsyncMysqlShim trait?的方法,比如:on_execute
、on_query
?等。查詢到來時(shí)會(huì)回調(diào)這些方法來執(zhí)行查詢。
這里以?on_query
?為例,關(guān)鍵代碼如下:
在?do_query
?中會(huì)創(chuàng)建?QueryContext?
并開始解析 sql 流程來完成后續(xù)的整個(gè) sql 查詢。關(guān)鍵代碼如下:
尾聲
以上就是從 Databend 啟動(dòng)服務(wù)到接受 sql 請求并開始處理的流程。最近我們因?yàn)橐恍┰颍–lickhouse tcp 協(xié)議偏向 clickhouse 的底層,協(xié)議沒有公開的文檔說明,同時(shí)里面歷史包袱比較重,排查問題浪費(fèi)大量精力)去掉了 ClickHouse native tcp client,具體請參見:?https://github.com/datafuselabs/databend/pull/7012
如果你閱讀完代碼有好的提議,歡迎來這里討論,另外如果發(fā)現(xiàn)相關(guān)的問題,可以提交到?issue?來幫助我們提高 Databend 的穩(wěn)定性。Databend 社區(qū)歡迎一切善意的意見和建議 :)
關(guān)于 Databend
Databend 是一款開源、彈性、低成本,基于對(duì)象存儲(chǔ)也可以做實(shí)時(shí)分析的新式數(shù)倉。期待您的關(guān)注,一起探索云原生數(shù)倉解決方案,打造新一代開源 Data Cloud。
Databend 文檔:https://databend.rs/
Twitter:https://twitter.com/Datafuse_Labs
Slack:https://datafusecloud.slack.com/
Wechat:Databend
GitHub :https://github.com/datafuselabs/databend
