Nebula Graph源码分析

分类:编程技术 时间:2024-02-20 15:59 浏览:0 评论:0
0
本文介绍《Nebula Graph源码分析》的相关知识。在实际案例操作过程中,很多人都会遇到这样的困境。接下来就让小编带领大家学习一下这些情况的处理方法吧!我希望你能仔细阅读并学到一些东西!

简介

对于 Nebula Graph 的新手开放源码库 对于我的朋友来说,一开始你们可能和我一样。你想提高自己,看看高手的代码,尝试做点什么。也许你可以修复一个看起来并不那么困难的错误。但面对这么多的代码,我手足无措,不知道从哪里开始。最后我硬着头皮,一遍又一遍地阅读代码,跑完一个又一个用例后,终于有了一些想法。

下面将分享我个人学习Nebula Graph开源代码的过程。也希望朋友们刚接触Nebula Graph可以少走弯路,快速上手。另外,Nebula Graph本身也使用了一些开源库。详情请参阅附录。

在这篇文章中,我们将通过数据流来快速学习Nebula Graph。以用户在客户端输入nGQL语句SHOW SPACES为例,我们使用GDB来跟踪输入语句时的Nebula Graph。它是如何调用和运行的。

整体架构

一个完整的架构Nebula Graph 包含三个服务,分别是查询服务、存储服务和元服务。每个服务都有自己的可执行二进制文件。

查询服务主要负责

客户端连接的管理

将客户端传来的nGQL语句解析成抽象语法树AST,并将抽象树AST解析成一系列执行动作。

优化执行动作

执行优化的执行计划

Storage Service主要负责

数据的分布式存储

p>

Meta Service主要负责

添加、删除、检查和修改图表架构

集群管理

用户认证

这次我们主要分析查询服务

目录结构

一开始可以得到一个源码包,解压它。可以先看一下代码的层次关系。不同包的主要功能是什么?下面仅列出src目录:

|--src |--client // 客户端代码 |--common // 提供一些常用的基础组件 |--console |--daemons |- - dataman |--graph // 包含查询服务的大部分代码 |--interface // 主要是meta、storage、graph的一些通信接口定义 |--jni |--kvstore |--meta // 元数据管理elated |--parser // 主要负责词法和语法分析   |--storage // 存储层相关 |--tools |--webservice

代码跟踪

通过脚本目录中的脚本启动metad和存储的服务:

启动后,通过 nebula.service status all 检查当前服务状态

然后gdb运行nebula-graphd二进制文件bin目录下的程序

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 // 在主入口处断点

输入 在gdb中运行开始运行nebula-graphd程序,然后通过next逐步运行直到遇到 gServer->serve(); // 阻塞等待,直到通过gServer->stop()关闭,此时nebula-graphd的所有线程都被阻塞,等待客户端连接。这时候就需要找出客户端发起请求后,处理的是哪个函数。

由于Nebula Graph使用FBThrift来定义生成不同服务的通信代码,因此在src/interface/graph.thrift文件中可以看到GraphService接口的定义如下:

service GraphService { AuthResponse 验证(1:字符串用户名,2:字符串密码) oneway void Signout(1:i64 sessionId) ExecutionResponseexecute(1:i64 sessionId,2:字符串stmt)}  

gServer->serve()之前有

auto interface = std::make_shared(); 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。此时客户端没有响应,因为服务器还在阻塞调试。 ,返回服务器,输入继续,如下图:

session验证后,输入executionEngine->execute()

code>、step进入函数

auto plan = new ExecutionPlan(std::move(ectx));plan->execute();

继续step进入ExecutionPlanexecute函数,然后执行到

auto result = GQLParser().parse ( rctx->query());

解析该块主要使用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();去->setStepClause($2);去->setFromClause($3);去->setOverClause($4);去->setWhereClause($5); if ($6 == nullptr) { auto *cols = new Yiel dColumns(); for (auto e : $4->edges()) { if (e->isOverAll()) { 继续;继续; } } 自动 *edge = new std::string(*e->edge()); auto *expr = new EdgeDstIdExpression(edge); auto *col = new YieldColumn(expr); $6 = 新的 YieldClause(cols); } go->setYieldClause($6); ,最后,一个抽象的sy生成 ntax 树。 

词法语法分析结束后开始执行模块,继续gdb,进入excute函数,继续step直到进入 ShowExecutor::execute 函数。

继续next直到showSpaces()单步进入此函数

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,然后通过该进程进行调试uggdb Attach PID;

如果不想启动服务端和客户端进行调试,src目录下每个文件夹下都有一个test目录,里面包含相应模块或功能的单元测试。可以直接编译相应的单元模块,然后跟踪执行。方法如下:

通过对应目录下的CMakeLists.txt文件找到对应的模块名

在build目录下制作模块名,生成对应的模块名在build/bin/test目录下的二进制程序

gdb跟踪调试程序

《Nebula Graph源码分析》的内容就到此为止。感谢您的阅读。如果您想了解更多行业资讯,可以关注网站,小编将为大家输出更多优质实用文章!

1. 本站所有资源来源于用户上传或网络,仅作为参考研究使用,如有侵权请邮件联系站长!
2. 本站积分货币获取途径以及用途的解读,想在本站混的好,请务必认真阅读!
3. 本站强烈打击盗版/破解等有损他人权益和违法作为,请各位会员支持正版!
4. 编程技术 > Nebula Graph源码分析

用户评论