1. 程式人生 > >新手閱讀 Nebula Graph 原始碼的姿勢

新手閱讀 Nebula Graph 原始碼的姿勢

> 摘要:在本文中,我們將通過資料流快速學習 Nebula Graph,以使用者在客戶端輸入一條 nGQL 語句 `SHOW SPACES` 為例,使用 GDB 追蹤語句輸入時 Nebula Graph 是怎麼呼叫和執行的。 > 首發於 Nebula Graph 部落格:https://nebula-graph.com.cn/posts/how-to-read-nebula-graph-source-code/ ![閱讀原始碼](https://www-cdn.nebula-graph.com.cn/nebula-blog/source-code.png) ## 導讀 對於一些剛開始接觸 [Nebula Graph](https://0x7.me/sourcecode2github) 開源庫的小夥伴來說,剛開始可能和我一樣,想要提高自己,看看大神們的程式碼然後試著能夠做點什麼,或許能夠修復一個看起來並不是那麼困難的 Bug。但是面對如此多的程式碼,我裂開了,不知道如何下手。最後硬著頭皮,再看了一遍又一遍程式碼,跑了一個又一個用例之後終於有點眉目了。 下面就分享下個人學習 Nebula Graph 開原始碼的過程,也希望剛接觸 Nebula Graph 的小夥伴能夠少走彎路,快速入門。另外 Nebula Graph 本身也用到了一些開源庫,詳情可以見附錄。 在本文中,我們將通過資料流快速學習 Nebula Graph,以使用者在客戶端輸入一條 nGQL 語句 `SHOW SPACES` 為例,使用 GDB 追蹤語句輸入時 Nebula Graph 是怎麼呼叫和執行的。 ## 整體架構 ![整體架構](https://www-cdn.nebula-graph.com.cn/nebula-blog/architecture.png) 一個完整的 Nebula Graph 包含三個服務,即 Query Service,Storage Service 和 Meta Service。每個服務都有其各自的可執行二進位制檔案。 Query Service 主要負責 - 客戶端連線的管理 - 解析來自客戶端的 nGQL 語句為抽象語法樹 AST,並將抽象樹 AST 解析成一系列執行動作。 - 對執行動作進行優化 - 執行優化後的執行計劃 Storage Service 主要負責 - 資料的分散式儲存 Meta Service 主要負責 - 圖 schema 的增刪查改 - 叢集的管理 - 使用者鑑權 這次,我們主要對 Query Service 進行分析 ## 目錄結構 剛開始,可以拿到一個 source 包,解壓,可以先看看程式碼的層級關係,不同的包主要功能是幹什麼的 下面只列出 src 目錄: ```markdown |--src |--client // 客戶端程式碼 |--common // 提供一些常用的基礎元件 |--console |--daemons |--dataman |--graph // 包含了Query Service的大部分程式碼 |--interface // 主要是一些 meta、storage 和 graph 的通訊介面定義 |--jni |--kvstore |--meta // 元資料管理相關 |--parser // 主要負責詞法和語法分析 |--storage // 儲存層相關 |--tools |--webservice ``` ## 程式碼跟蹤 通過 scripts 目錄下的指令碼啟動 metad 和 storaged 這兩個服務: ![閱讀原始碼](https://www-cdn.nebula-graph.com.cn/nebula-blog/console.png) 啟動後通過 `nebula.service status all` 檢視當前的服務狀態 ![閱讀原始碼](https://www-cdn.nebula-graph.com.cn/nebula-blog/service-status.png) 然後 gdb 執行 bin 目錄下的 `nebula-graphd` 二進位制程式 ```cpp gdb> set args --flagfile /home/mingquan.ji/1.0/nebula-install/etc/nebula-graphd.conf //設定函式入參 gdb> set follow-fork-mode child // 由於是守護程序,所以在 fork 子程序後 gdb 繼續跟蹤子程序 gdb> b main // 在 mian 入口打斷點 ``` 在 gdb 中輸入 `run` 開始執行 `nebula-graphd` 程式,然後通過 `next` 可以一步一步執行,直到遇到 `gServer->serve(); // Blocking wait until shut down via gServer->stop()`,此時 `nebula-graphd` 的所有執行緒阻塞,等待客戶端連線,這時需要找到客戶端發起請求後由哪個函式處理。 由於 Nebula Graph 使用 FBThrift 來定義生成不同服務的通訊程式碼,在 `src/interface/graph.thrift` 檔案中可以看到 GraphService 介面的定義如下: ```cpp service GraphService { AuthResponse authenticate(1: string username, 2: string password) oneway void signout(1: i64 sessionId) ExecutionResponse execute(1: i64 sessionId, 2: string stmt) } ``` 在 `gServer->serve()` 之前有 ```cpp auto interface = std::mak