新手阅读 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/
导读
对于一些刚开始接触 Nebula Graph 开源库的小伙伴来说,刚开始可能和我一样,想要提高自己,看看大神们的代码然后试着能够做点什么,或许能够修复一个看起来并不是那么困难的 Bug。但是面对如此多的代码,我裂开了,不知道如何下手。最后硬着头皮,再看了一遍又一遍代码,跑了一个又一个用例之后终于有点眉目了。
下面就分享下个人学习 Nebula Graph 开源代码的过程,也希望刚接触 Nebula Graph 的小伙伴能够少走弯路,快速入门。另外 Nebula Graph 本身也用到了一些开源库,详情可以见附录。
在本文中,我们将通过数据流快速学习 Nebula Graph,以用户在客户端输入一条 nGQL 语句 SHOW SPACES
为例,使用 GDB 追踪语句输入时 Nebula Graph 是怎么调用和运行的。
整体架构
一个完整的 Nebula Graph 包含三个服务,即 Query Service,Storage Service 和 Meta Service。每个服务都有其各自的可执行二进制文件。
Query Service 主要负责
- 客户端连接的管理
- 解析来自客户端的 nGQL 语句为抽象语法树 AST,并将抽象树 AST 解析成一系列执行动作。
- 对执行动作进行优化
- 执行优化后的执行计划
Storage Service 主要负责
- 数据的分布式存储
Meta Service 主要负责
- 图 schema 的增删查改
- 集群的管理
- 用户鉴权
这次,我们主要对 Query Service 进行分析
目录结构
刚开始,可以拿到一个 source 包,解压,可以先看看代码的层级关系,不同的包主要功能是干什么的 下面只列出 src 目录:
|--src
|--client // 客户端代码
|--common // 提供一些常用的基础组件
|--console
|--daemons
|--dataman
|--graph // 包含了Query Service的大部分代码
|--interface // 主要是一些 meta、storage 和 graph 的通讯接口定义
|--jni
|--kvstore
|--meta // 元数据管理相关
|--parser // 主要负责词法和语法分析
|--storage // 存储层相关
|--tools
|--webservice
代码跟踪
通过 scripts 目录下的脚本启动 metad 和 storaged 这两个服务:
启动后通过 nebula.service status all
查看当前的服务状态
然后 gdb 运行 bin 目录下的 nebula-graphd
二进制程序
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 接口的定义如下:
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()
之前有
auto interface = std::make_shared<GraphService>();
status = interface->init(ioThreadPool);
gServer->setInterface(std::move(interface));
gServer->setAddress(localIP, FLAGS_port);
可以知道是由 GraphService
对象来处理客户端的连接和请求,因此可以在 GraphService.cpp:``future_execute
处打断点,以便跟踪后续处理流程。
此时重新打开一个终端进入 nebula 安装目录,通过 ./nebule -u=root -p=nebula
来连接 nebula 服务,再在客户端输入 SHOW SPACES
,此时客户端没有反应,是因为服务端还在阻塞调试中,回到服务端输入 continue,如下所示:
经过 session
验证后,进入 executionEngine->execute()
中,step
进入函数内部
auto plan = new ExecutionPlan(std::move(ectx));
plan->execute();
继续 step
进入ExecutionPlan
的 execute
函数内部,然后执行到
auto result = GQLParser().parse(rctx->query());
parse
这块主要使用 flex & bison
,用于词法分析和语法解析构造对象到抽象语法树,其词法文件是 src/parser/scanner.lex,语法文件是 src/parser/parser.yy,其词法分析类似于正则表达式,语法分析举例如下:
go_sentence
: KW_GO step_clause from_clause over_clause where_clause yield_clause {
auto go = new GoSentence();
go->setStepClause($2);
go->setFromClause($3);
go->setOverClause($4);
go->setWhereClause($5);
if ($6 == nullptr) {
auto *cols = new YieldColumns();
for (auto e : $4->edges()) {
if (e->isOverAll()) {
continue;
}
auto *edge = new std::string(*e->edge());
auto *expr = new EdgeDstIdExpression(edge);
auto *col = new YieldColumn(expr);
cols->addColumn(col);
}
$6 = new YieldClause(cols);
}
go->setYieldClause($6);
$$ = go;
}
其在匹配到对应到 go 语句时,就构造对应的节点,然后由 bison 处理,最后生成一个抽象的语法树。
词法语法分析后开始执行模块,继续 gdb
,进入 excute
函数,一直 step
直到进入ShowExecutor::execute
函数。
继续 next
直到 showSpaces()
,step
进入此函数
auto future = ectx()->getMetaClient()->listSpaces();
auto *runner = ectx()->rctx()->runner();
'''
'''
std::move(future).via(runner).thenValue(cb).thenError(error);
此时 Query Service 通过 metaClient 和 Meta Service 通信拿到 spaces
数据,之后通过回调函数 cb
回传拿到的数据,至此 nGQL 语句 SHOW SPACES;
已经执行完毕,而其他复杂的语句也可以以此类推。
- 如果是正在运行的服务,可以先查出该服务的进程 ID,然后通过 gdb attach PID 来调试该进程;
- 如果不想启动服务端和客户端进行调试,在 src 目录下的每个文件夹下都有一个 test 目录,里面都是对对应模块或者功能进行的单元测试,可以直接编译对应的单元模块,然后跟踪运行。方法如下:
- 通过对应目录下的 CMakeLists.txt 文件找到对应的模块名
- 在 build 目录下 make 模块名,在 build/bin/test 目录下生成对应的二进制程序
- gdb 跟踪调试该程序
附录
阅读 Nebula Graph 源码需要了解的一些库:
- flex & bison:词法分析和语法分析工具,将客户端输入的 nGQL 语句解析为抽象语法树
- FBThrift:Facebook 开源的 RPC 框架,定义并生成了 Meta 层、Storage 层和 Graph 层的通讯过程代码
- folly:Facebook 开源的 C++14 组件库,提供了类似 Boost 和 std 库的功能,在性能上更加优化
- Gtest:Google 开源的 C++ 单元测试框架
其中数据库资料可以参考:
喜欢这篇文章?来来来,给我们的 GitHub 点个 star 表鼓励啦~~ ♂️♀️ [手动跪谢]
交流图数据库技术?交个朋友,Nebula Graph 官方小助手微信:NebulaGraphbot 拉你进交流群~~
作者有话说:Hi,我是明泉,是图数据 Nebula Graph 研发工程师,主要工作和数据库查询引擎相关,希望本次的经验分享能给大家带来帮助,如有不当之处也希望能帮忙纠正,谢谢~
新手阅读 Nebula Graph 源码的姿势的更多相关文章
- 使用 Docker 构建 Nebula Graph 源码
Nebula Graph 介绍 Nebula Graph 是开源的高性能分布式图数据库.项目使用 C++ 语言开发,cmake 工具构建.其中两个重要的依赖是 Facebook 的 Thrift RP ...
- daily news新闻阅读客户端应用源码(兼容iPhone和iPad)
daily news新闻阅读客户端应用源码(兼容iPhone和iPad),也是一款兼容性较好的应用,可以支iphone和ipad的阅读阅读器源码,设计风格和排列效果很不错,现在做新闻资讯客户端的朋友可 ...
- 如何阅读Android系统源码-收藏必备
对于任何一个对Android开发感兴趣的人而言,对于android系统的学习必不可少.而学习系统最佳的方法就如linus所言:"RTFSC"(Read The Fucking So ...
- 教你阅读 Cpython 的源码(二)
第二部分:Python解释器进程 在上节教你阅读 Cpython 的源码(一)中,我们从编写Python到执行代码的过程中看到Python语法和其内存管理机制. 在本节,我们将从代码层面去讨论 ,Py ...
- android新闻项目、饮食助手、下拉刷新、自定义View进度条、ReactNative阅读器等源码
Android精选源码 Android仿照36Kr官方新闻项目课程源码 一个优雅美观的下拉刷新布局,众多样式可选 安卓版本的VegaScroll滚动布局 android物流详情的弹框 健身饮食记录助手 ...
- android选择器汇总、仿最美应用、通用课程表、卡片动画、智能厨房、阅读客户端等源码
Android精选源码 android各种 选择器 汇总源码 高仿最美应用项目源码 android通用型课程表效果源码 android实现关键字变色 Android ViewPager卡片视差.拖拽及 ...
- android五子棋游戏、资讯阅读、大学课程表、地图拖拽检测、小说搜索阅读app等源码
Android精选源码 Android 自动生成添加控件 android旋转动画.圆形进度条组合效果源码 一款很强的手机五子棋app源码 android地图拖拽区域检测效果源码 实现Android大学 ...
- android优化中国风应用、完整NBA客户端、动态积分效果、文件传输、小说阅读器等源码
Android精选源码 android拖拽下拉关闭效果源码 一款优雅的中国风Android App源码 EasySignSeekBar一个漂亮而强大的自定义view15 android仿蘑菇街,蜜芽宝 ...
- Cognitive Graph for Multi-Hop Reading Comprehension at Scale(ACL2019) 阅读笔记与源码解析
论文地址为:Cognitive Graph for Multi-Hop Reading Comprehension at Scale github地址:CogQA 背景 假设你手边有一个维基百科的搜索 ...
随机推荐
- 安装nodejs,npm,yarn
先安装nodejs和npm sudo apt update sudo apt install nodejs npm #验证一下 nodejs --version npm --version 如果nod ...
- Halcon一维测量1D Measuring解析
一维测量(也叫一维计量或卡尺)的概念非常直观.沿着一个预定的区域(主要是垂直于RIO感兴趣区域的方向) 边缘的位置.这里的边缘为从暗到亮或从亮到暗的过渡. 基于提取的边缘,可以测量零件的尺寸.例如,可 ...
- 【XCTF】ics-05
信息: 题目来源:XCTF 4th-CyberEarth 标签:PHP.伪协议 题目描述:其他破坏者会利用工控云管理系统设备维护中心的后门入侵系统 解题过程 题目给了一个工控管理系统,并提示存在后门, ...
- python 并发专题(七):Twisted相关函数以及实现
一.基础原理 二.基本函数 三.爬虫实现 四.web服务器与客户端实现
- 数据可视化之分析篇(五)如何使用Power BI计算新客户数量?
https://zhuanlan.zhihu.com/p/65119988 每个企业的经营活动都是围绕着客户而开展的,在服务好老客户的同时,不断开拓新客户是每个企业的经营目标之一. 开拓新客户必然要付 ...
- vscode切换虚拟环境报错无法加载文件 E:\Python_project\shop_env\Scripts\Activate.ps1,因为在此系统上禁止运行 脚本。
在使用vscode切换python的虚拟环境时报错 解决方法如下: Windows+x打开面板,选择以管理员身份运行PowerShell,输入: set-executionpolicy remotes ...
- git怎么合并远程分支
一共就五步: 1.把代码clone到本地仓库 git clone https://github.com/573734817pc/shop.git 2.在本地创建dev分支并与远程dev分支对应 git ...
- 盘点 6 个被淘汰的 Java 技术,它们都曾经风光过!
大家好啊,今天栈长给大家分享下我的开发历程中,我知道的那些被淘汰的技术或者框架,有些我甚至都没有用过,但我知道它曾经风光过. 废话不多说,下面我要开始吹了-- 1.Swing 下面这个是用 swing ...
- 学会这个,助你升值加薪自动化框架之python+selenium+pytest
1.概述 selenium: 基于JavaScript代码库的自动化测试框架,通过脚本语言,模拟用户行为操作,最接近用户真实场景,实现对web自动测试. Selenium,是目前的最火爆企业最主流的w ...
- Windows下安装Python 3.X 版本
一. Python下载 Python官方下载地址 演示下载的版本为Python 3.8.3 ,你可以根据自己的选择安装其他版本的Python 二. Python 安装 下载完安装包双击安装时出错(Wi ...