本文首发于 Nebula Graph Community 公众号
开源之夏
开源软件供应链点亮打算 – 暑期 2021(下简称:开源之夏)是由中国科学院软件研究所与 openEuler 社区独特举办的一项面向高校学生的暑期流动,旨在激励在校学生积极参与开源软件的开发保护,促成优良开源软件社区的蓬勃发展。中科院联结包含 Nebula Graph 在内的国内各大开源社区,针对重要开源软件的开发与保护提供我的项目,并向寰球高校学生凋谢报名。学生在自由选择我的项目后,与社区导师沟通实现计划并撰写我的项目计划书。被选中的学生将在社区导师领导下,按计划实现开发工作,并将成绩奉献给社区。依据我的项目的难易水平和实现状况,参与者将取得由主办方发放的 6,000 – 12,000 不等的我的项目奖金。
流动官网:https://summer.iscas.ac.cn/
本期分享来自 Nebula Graph 社区郑东阳同学(图数据库 Nebula Graph 反对 JDBC 协定)的我的项目教训。
我的项目信息
项目名称:图数据库 Nebula Graph 反对 JDBC 协定
我的项目详情
让 Nebula Graph 能够对接 JDBC 协定,实现 Nebula JDBC driver,实现 JDBC 的相干接口。要求:用户可间接应用 JDBC 驱动操作 Nebula 服务,我的项目 repo 有主动运行的单元测试。
Nebula Graph 简介
一个牢靠的分布式、线性扩容、性能高效的图数据库;世界上惟一可能包容千亿个顶点和万亿条边,并提供毫秒级查问延时的图数据库解决方案。Nebula Graph 特点
- 开源:致力于与社区单干,遍及及促成图数据库的倒退;
- 平安:具备基于角色的权限管制,受权能力拜访;
- 扩展性:反对 Spark、Hadoop、GraphX、Plato 等等多种周边生态工具;
- 高性能:Nebula Graph 在维持高吞吐量的同时仍旧能做到低时延的读写;
- 扩容:基于 shared-nothing 分布式架 Nebula Graph 反对线性扩容;
- 兼容 openCypher:逐渐兼容 openCypher9,Cypher 用户可轻松上手 Nebula Graph;
- 高可用:反对多种形式复原异样数据,保障在部分失败的状况下服务的高可用性;
- 稳固发行版:通过一线互联网大厂,诸如京东、美团、小红书在生产环境上的业务考验。
Nebula Graph 具备沉闷的社区与及时的技术支持,这是官网:https://nebula-graph.com.cn 和 GitHub 仓库:https://github.com/vesoft-inc/nebula,欢送关注及应用 Nebula Graph,一起成为 Nebula Graph 的 Contributor,为图数据库的倒退贡献力量!!!
我的项目落地
计划形容
后期理解 Nebula Graph 相干性能,把握其根本应用;调研 JDBC 的驱动开发,浏览 JDBC 标准文档,理解一些须要实现的接口;中期参考 Neo4j 的 neo4j-jdbc:https://github.com/neo4j-contrib/neo4j-jdbc 实现,克隆 nebula-java:https://github.com/vesoft-inc/nebula-java 我的项目,学习源码,理解我的项目代码的次要逻辑和代码格调;前期利用已有的轮子 nebula-java:https://github.com/vesoft-inc/nebula-java 实现与数据库的通信,编写代码为 Nebula Graph 实现 JDBC 的相干接口,编写单元测试。
实现形容
这个我的项目实现的思路很清晰:implements JDBC 标准中的一系列接口(次要位于 java.sql 包中),实现接口中的办法。JDBC 标准中所有的类加起来须要实现的办法有好几百个。JDBC 次要面向的数据库是传统的关系型数据库(RDB),而 Nebula Graph 作为新一代的图数据库,比起久经倒退的关系型数据库来说没有它那么齐备的性能个性,然而又比关系型数据库多出许多新的特点,所以 JDBC 标准中的办法对于 Nebula Graph 而言既有多余(不须要真正实现)也有有余。(须要实现然而没有在相干接口中定义)
在具体的实现中,定义出一些抽象类间接 implements 标准中的次要接口,再定义出具体的实现类实现接口中一些重要的办法,这样一来实现类中的办法在浏览时不会显得很杂很乱。对于接口中须要实现的办法:
for(method : 接口的办法){if(method BELONG_TO 不须要具体实现的办法){// 比方 Statement::getGeneratedKeys()
在该抽象类中 Override,办法体中抛出一个 SQLFeatureNotSupportedException;
}else if(method BELONG_TO 须要实现然而不是外围办法){// 比方 Statement::isClosed()
在该抽象类中 Override;}else if(method BELONG_TO 须要实现且是外围办法){// 比方 Statement::execute(String nGql)
在具体实现类中 Override
}else if(method BELONG_TO 在接口中没有定义然而须要实现){// 比方 NebulaResult::getNode getEdge getPath ( 点, 边, 门路是图数据库特有概念)
在具体实现类中实现
}
}
我的项目中次要的一些 implements 和 extends 关系如下:(蓝色实线是类之间的 extends 关系,绿色实线是接口之间的 implements 关系,绿色虚线是抽象类与接口之间的 implements 关系)。
工作流程及类中次要办法剖析:
// 用户首先通过 NebulaDriver 注册驱动,其中有 NebulaPool 属性,用于获取 Session 与数据库通信
// NebulaDriver 中提供两个构造函数,无参构造函数配置默认的 NebulaPool,接管一个 Properties 类型参数的构造函数能够自定义 NebulaPool 配置
public NebulaDriver() throws SQLException {this.setDefaultPoolProperties();
this.initNebulaPool();
// 将本身注册到 DriverManager
DriverManager.registerDriver(this);
}
public NebulaDriver(Properties poolProperties) throws SQLException {
this.poolProperties = poolProperties;
this.initNebulaPool();
// 将本身注册到 DriverManager
DriverManager.registerDriver(this);
}
// 注册驱动后用户能够 DriverManager::getConnection(String url) 获取连贯。在 NebulaConnection 的构造函数中会通过 NebulaDriver 中的 NebulaPool 获取 Session 接着连贯拜访在 url 中指定的图空间
// 获取到 Connection 后用户能够用 Connection::createStatement 和 Connection::prepareStatement 拿到 Statement 或者 PreparedStatement 对象,调用其中的 execute 办法向数据库发送命令,数据库执行此命令后的后果会封装在 NebulaResult 中,再调用其中各种获取数据的办法能够失去不同数据类型的数据
// 目前 NebulaResult 中实现的获取数据办法有以下这些,Nebula Graph 中不同的数据类型都有对应实现
public String getString();
public int getInt();
public long getLong();
public boolean getBoolean();
public double getDouble();
public java.sql.Date getDate();
public java.sql.Time getTime();
public DateTimeWrapper getDateTime();
public Node getNode();
public Relationship getEdge();
public PathWrapper getPath();
public List getList();
public Set getSet();
public Map getMap();
我的项目进度
已实现工作
- 部署 Nebula Graph 并把握其根本应用;
- 浏览 JDBC:https://download.oracle.com/otn-pub/jcp/jdbc-4_2-mrel2-spec/jdbc4.2-fr-spec.pdf?AuthParam=1628844546_d5f078af230e42dcbe0ba3d183af7495 标准文档,明确实现要求;
- 学习 nebula-java:https://github.com/vesoft-inc/nebula-java 源码;
实现以下实现:
遇到的问题及解决方案
如何与数据库通信的问题 :
项目前期过程中不晓得如何与数据库通信,在钻研友商 Neo4j 的 neo4j-jdbc 实现后利用 Http 框架通过 Nebula Graph 的 API(毛糙地)实现了与数据库的通信;实现后与导师分割询问该想法是否可行,导师通知我能够用已有的轮子 nebula-java,通过 rpc 与 Nebula Graph 通信。
数据统计采纳了计算复合指标的办法,计算得出各家企业在企业规模、社会影响、发展潜力和社会责任四个维度上的得分,加权均匀后确定排名。
对于获取 Connection 的问题 :
NebulaPoolConfig 类中的一些参数是可配置的,我的想法是以在连贯字符串中指定的模式进行配置,如:”jdbc:nebula://ip:port/graphSpace?maxConnsSize=10&reconnect=true”。
征询导师后导师倡议能够让用户获取连贯的时候,反对两种接口,一种是用默认配置,一种是让用户指定配置,如:
// default configuration
DriverManager.getConnection(url, username, password);
// customized configuration
DriverManager.getConnection(url, config);
对于 PreparedStatement 的问题 :
关系型数据库反对查问语句预编译的性能,PreparedStatement 能够向 DBMS 发送 SQL 让其预编译而后再传参数,进步了性能且能避免 SQL 注入攻打;目前 Nebula Graph 暂无此性能,所以在本地解析 nGQL 中的占位符再将参数填充进去,实质上与 Statement 雷同。
nebula-java 版本问题 :
一开始在我的项目中引入的依赖的 2.0.0 版本,在一次查问中发现其门路返回后果与控制台返回后果不统一,征询导师后发现这是这个版本中的 bug,改用最新的 2.0.0-SNAPSHOT 版本。
updateCount 问题 :
JDBC 接口中一些办法要求返回值是收到此办法影响的数据量 updateCount,但目前服务端没有 updateCount 统计返回给用户。如果用户一条插入语句外面同时插入多个点或者多条边,这外面可能有局部胜利,但服务端只会返回通知用户失败了,然而其实用户可能能查到局部数据。这个 updateCount 依照 0 返回,而后在接口增加正文阐明不反对。
NebulaPool 初始化问题 :
一开始我是在初始化 NebulaConnection 时初始化 NebulaPool 再获取 Session,而且搞混了对于 NebulaPool 的配置和对于 Session 的配置。这样的话用户每次获取 Connection 时都会从新初始化 NebulaPool,是不合理的,我提交代码到 Gitlab 导师 review 后指出了我的谬误,倡议我将 NebulaPool 的 初始化和敞开移到 NebulaDriver 中,再进步默认配置和自定义配置两种形式初始化 NebulaPool。
后续工作安顿
- 实现接口中应该实现但未实现的办法 ;
- 欠缺代码正文 ;
- 实现单元测试 ;
- 编写应用阐明 .
致谢
这次流动促成了开源软件的倒退和优良开源软件社区建设,减少开源我的项目的活跃度,推动开源生态的倒退;感激 @开源之夏主办方 为这次流动提供的平台与机会。
感激导师 @laura.ding 在这过程中认真地 review 我 PR 的代码,予以我粗疏的领导让我通晓本人的有余;感激 @Nebula Graph 经营小姐姐寄给我的社区周边,LUCKY!
本文为郑东阳同学的原创文章。
深圳 Meetup 流动进行中,本周六你如果想来和 Nebula 技术团队来个面对面交换的话,记得戳上面链接报名哟~
nMeetup 报名链接