xorm适配GaussDB开源开发任务心得
xorm适配GaussDB开源开发任务心得
从计划书开始开始
从计划书了解到任务内容,这次适配的是ORM组件xorm,计划书很详细,也提到了适配方案:
- 基于以下GaussDB第三方驱动进行扩展:https://support.huaweicloud.cn/distributed-devg-v8-gaussdb/gaussdb-12-0231.html
- 实现dialect.Dialect接口,使其支持GaussDB的特定数据库语法和特性。
- 实现dialect.Driver接口,使其能够解析GaussDB的数据源名称。
了解任务内容之后,开始着手xorm和驱动开发的分析。
官网驱动(重要!!!)
官网的驱动 是 openGauss-connector-go-pq 的修改版本。
- 主要是新增了postgre、gaussdb驱动名称注册,使可以用postgres驱动名称接入驱动
- 以这种方式提供主要2个弊端
- 原开源项目内容难以更新,openGauss-connector-go-pq 更新的一些BUG修复,代码优化,在没有版本管理情况下难以同步,目前代码已经滞后 openGauss-connector-go-pq。
- 管理方式不便利。
适配分析
xorm分析
xorm基于go的标准库 database/sql,该标准库提供了SQL数据库操作接口和方法,
该标准库不提供驱动,必须注册一个数据库驱动配合使用。
-
database/sql
- sql.Register 注册驱动,openGauss驱动调用该方法注册。
- sql.Open 打开数据库,会从drivers Map中找到对应的的driver初始化并返回,xorm的newEngine方法调用sql.Open连接数据库。
-
xorm提供Dialect接口和Driver接口:
- Dialect接口提供一些处理数据库DDL的方法。
- Driver接口提供一些驱动特征信息、DSN解析等方法。
-
任务适配的是数据库GaussDB,基于PostgreSQL开发而来,也就是现有的PostgreSQL驱动能兼容GaussDB大部分的功能。
- GaussDB提供的驱动包是开源项目openGauss的驱动包,openGauss-connector-go-pq。
- openGauss-connector-go-pq 基于驱动 github/lib/pq,开源项目修改了 github/lib/pq 认证方法和一些其他适配,认证方法适配openGauss SHA256/SM3 密码认证。
- PostgreSQL使用的是加盐SHA256和MD5等方法
- OpenGauss提倡使用SHA256
适配方案1:
- 使用 openGauss-connector-go-pq 驱动。
- xorm增加opengauss结构体实现Dialect接口,重写部分方法,这里主要是考虑openGauss和PostgreSQL的趋向,其实也可以修改PostgreSQL的dialect适配openGauss。
- 复用已有的xorm PostgreSQL Driver接口,这里openGauss和PostgreSQL逻辑相同,可以复用,也可以扩展成为自己的Driver。
适配方案2(目前采用的方案):
- 使用官网提供的GaussDB驱动。
- 直接使用驱动名postgres,xorm已集成。
- 修改xorm的dialect方法,比如DBVersion,使能返回正确的版本号。
驱动分析
OpenGauss是基于PostgreSQL 9.2.4版本。
OpenGauss和PostgreSQL使用协议是一样的,libpq V3。
libpq协议分为V2和V3,从postgresql7.4开始支持V3。
libpq通信协议分为两个阶段:startup和normal。startup阶段主要进行认证连接,normal阶段主要是客户端sql请求和数据库响应。
2个阶段
- startup
-
授权,openGauss-connector-go-pq 讲 pq 的 SCRAM-SHA-256 修改成 SHA-256,并增加了MD5-SHA-256,SM3
| pq | openGauss-connector-go-pq |
|----------|:-------------:|
| SCRAM-SHA-256 | SHA-256 |
| | MD5-SHA-256 |
| | SM3 | -
TLS,openGauss-connector-go-pq 增加了 PEM 格式解密操作。
-
更多待续
- normal
-
因为Openguass有多兼容模式,比如A、B、C、PG。分别表示兼容O(Oracle)、MY(MySQL)、TD(TDSQL)和POSTGRES。所以这个阶段,Openguass会对各个模式特殊处理,比如B模式下,true改成了1。
-
更多待续
fork代码
还没有加入HuaweiCloudDeveloper,这次先fork xorm 代码到个人代码仓库,即将进入开发阶段。
适配方案1
因为Gaussdb基于PostgreSQL,而且相关的驱动库已经就绪,所以这次任务的重点是为xorm添加适配代码和测试兼容性。
xorm定义了dialects和drivers全局Map变量。
var dialects = map[string]func() Dialect{}
var drivers = map[string]Driver{}
在初始化时候注册进去
func init() {
regDrvsNDialects()
}
从以下可以知道,使用了postgre原有的pqDriver作为Driver,新增了关于openguass自己的Dialect。
func regDrvsNDialects() bool {
providedDrvsNDialects := map[string]struct {
dbType schemas.DBType
getDriver func() Driver
getDialect func() Dialect
}{
// 省略...
"postgres": {"postgres", func() Driver { return &pqDriver{} }, func() Dialect { return &postgres{} }},
// 使用了postgre原有的pqDriver,新增了关于openguass自己的Dialect。
"opengauss": {"postgres", func() Driver { return &pqDriver{} }, func() Dialect { return &openGauss{} }},
// 省略...
}
// 这里注入全局变量dialects和drivers
for driverName, v := range providedDrvsNDialects {
if driver := QueryDriver(driverName); driver == nil {
// 这里对opengauss特别处理,不然丢失opengauss的dialect
if driverName == "opengauss" {
RegisterDialect("opengauss", v.getDialect)
} else {
RegisterDialect(v.dbType, v.getDialect)
}
}
}
return true
}
// OpenDialect opens a dialect via driver name and connection string
func OpenDialect(driverName, connstr string) (Dialect, error) {
// 这里获取要特别处理opengauss
var dialect Dialect
if driverName == "opengauss" {
dialect = QueryDialect("opengauss")
} else {
dialect = QueryDialect(uri.DBType)
}
if dialect == nil {
return nil, fmt.Errorf("unsupported dialect type: %v", uri.DBType)
}
}
新增了openGauss结构体,继承了postgres的方法,并重写了部分方法。
type openGauss struct {
postgres
}
然后实现openGauss结构体需要重写的方法,这样,编码部分的工作就基本完成了。
适配方案2(本任务采用的方案)
将 官网的驱动 替换掉开源 openGauss-connector-go-pq 驱动。
require (
gitee.com/opengauss/openGauss-connector-go-pq v1.0.4
)
// 将
replace gitee.com/opengauss/openGauss-connector-go-pq => ./third/gitee.com/opengauss/openGauss-connector-go-pq
直接使用postgres驱动进行注册。官网驱动已为我们多注册了postgres、postgresql驱动名称。
db, err = xorm.NewEngine("postgres", req.DSN)
if err != nil {
return
}
验证任务DEMO开发完成。
部署
本次部署demo使用的是华为云codeArt部署,包括一台华为云CES,华为云GaussDB集群,其中CES中部署了一个nginx,一个Go应用程序,
前端托管在nginx服务中。
这里为什么是使用CES主机单机部署,因为对华为云整体云使用、前端使用的nextjs框架还不熟练,所以考虑传统的部署方式,希望下个项目能使用容器化部署。
部署过程待时间充裕补充。
总结
开发到此完成,如果如有发现思路不对,代码错误,或者有更好的方案,请发消息给我,告诉我您宝贵的指导意见。
对于个人,从这次经历中学到很多,开源项目中有很多值得学习的优秀代码,学习到解决问题的方式,多样性等等,还有最重要的是要看项目的Readme,这个是悲伤的经历,开源开发任务不是想象中的简单,要敬畏开源工作。
从这次任务中,发现需要反思的地方还挺多,希望下次能得以改进。
需要改进的地方:
- 尽早联系社区。
- 合理分配时间很重要,这并不是轻松的工作。
- 花更多时间到测试上。
- 使用更多的辅助工具,比如go-callvis来获取调用关系,使更好地了解代码流程。
通过投入开源,努力提高自身水平,希望下次能够做的更好。
验收说明
本文提供的验收材料按照《xorm适配GaussDB开源开发任务》任务计划书的要求提供,没有偏离。
验收材料
-
开源软件fork地址:不涉及
-
开源软件修改记录(可以有多个修改记录):
不涉及
-
推送上游社区PR(包括代码、文档、可以有多个):
不涉及
-
验证DEMO地址:https://gitcode.com/sunsungk9/opensource-demo-xorm-241116/overview
-
验证DEMO修改记录(可以有多个修改记录,只包含和本任务验证强相关的提交记录,比如添加依赖、增加配置文件、演示开源软件功能使用的代码等):
资源清单
CCE
产品名称 | 集群类型 | 集群版本 | 集群规模 |
---|---|---|---|
云容器引擎CCE | Turbo集群 | V1.29 | 50 |
ECS
产品名称 | CPU架构 | 实例类型 | 公共镜像 | 镜像版本 |
---|---|---|---|---|
弹性云服务器 | 鲲鹏计算 | 鲲鹏通用计算增强型 | Huawei Cloud EulerOS | Huawei Cloud EulerOS 2.0标准版 64位 ARM版(10GiB) |
GuassDB
产品名称 | 产品类型 | 数据库引擎版本 | 内核引擎版本 | 实例类型 | 部署形态 |
---|---|---|---|---|---|
云数据库GaussDB | 基础版 | V2.0-8.* | 505.2.* | 集中式 | 1主2备 |
验证截图
验证思路
官方提供的驱动包的兼容了PostgreSQL和GaussDB,可以直接使用。
验证方案是:使用官方提供的驱动包,连接华为云数据库的GaussDB。然后设计新增,修改,删除,列表共4个REST接口。
测试截图分别是执行4个REST接口的结果。
添加接口
修改接口
删除接口
列表接口
- 点赞
- 收藏
- 关注作者
评论(0)