xorm适配GaussDB开源开发任务心得

举报
SSK9 发表于 2024/11/11 09:08:21 2024/11/11
【摘要】 xorm适配GaussDB开源开发任务心得 从计划书开始开始从计划书了解到任务内容,这次适配的是ORM组件xorm,计划书很详细,也提到了适配方案:基于以下GaussDB第三方驱动进行扩展:https://support.huaweicloud.cn/distributed-devg-v8-gaussdb/gaussdb-12-0231.html实现dialect.Dialect接口,使...

xorm适配GaussDB开源开发任务心得

从计划书开始开始

从计划书了解到任务内容,这次适配的是ORM组件xorm,计划书很详细,也提到了适配方案:

  1. 基于以下GaussDB第三方驱动进行扩展:https://support.huaweicloud.cn/distributed-devg-v8-gaussdb/gaussdb-12-0231.html
  2. 实现dialect.Dialect接口,使其支持GaussDB的特定数据库语法和特性。
  3. 实现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大部分的功能。

适配方案1:

  1. 使用 openGauss-connector-go-pq 驱动。
  2. xorm增加opengauss结构体实现Dialect接口,重写部分方法,这里主要是考虑openGauss和PostgreSQL的趋向,其实也可以修改PostgreSQL的dialect适配openGauss。
  3. 复用已有的xorm PostgreSQL Driver接口,这里openGauss和PostgreSQL逻辑相同,可以复用,也可以扩展成为自己的Driver。

适配方案2(目前采用的方案):

  1. 使用官网提供的GaussDB驱动。
  2. 直接使用驱动名postgres,xorm已集成。
  3. 修改xorm的dialect方法,比如DBVersion,使能返回正确的版本号。

驱动分析

OpenGauss是基于PostgreSQL 9.2.4版本。

OpenGauss和PostgreSQL使用协议是一样的,libpq V3。

libpq协议分为V2和V3,从postgresql7.4开始支持V3。

libpq通信协议分为两个阶段:startup和normal。startup阶段主要进行认证连接,normal阶段主要是客户端sql请求和数据库响应。

  1. pq
  2. openGauss-connector-go-pq
  3. 官网的驱动

2个阶段

  1. 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 格式解密操作。

  • 更多待续

  1. 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开源开发任务》任务计划书的要求提供,没有偏离。

验收材料

  1. 开源软件fork地址:不涉及

  2. 开源软件修改记录(可以有多个修改记录):

    不涉及

  3. 推送上游社区PR(包括代码、文档、可以有多个):

    不涉及

  4. 验证DEMO地址:https://gitcode.com/sunsungk9/opensource-demo-xorm-241116/overview

  5. 验证DEMO修改记录(可以有多个修改记录,只包含和本任务验证强相关的提交记录,比如添加依赖、增加配置文件、演示开源软件功能使用的代码等):

  1. 博客地址:https://bbs.huaweicloud.cn/blogs/439216

资源清单

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接口的结果。

添加接口

修改接口

删除接口

列表接口

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。