Rainbond 这款产品一向致力于打通企业运用交给的全流程,这个流程中不可或缺的一环是企业运用的不断晋级、迭代。Rainbond 特有的才能,是能够将包含多个服务组件的企业运用体系进行打包,并履行一键装置、晋级以及回滚的操作。上述的内容只是处理了运用程序自身的版别操控问题。企业运用的晋级迭代流程想要彻底实现主动化,还需求能够主动处理数据库表结构(Schema)的版别操控。经过不断的探究,Rainbond 首先在源码构建范畴借助业界领先的 Liquibase 集成了云原生时代的数据库 Schema 版别办理的才能。
Schema版别办理难题
数据库表结构(Schema)界说了数据表(Table)的姓名,以及每一个数据表中所包含的数据列(Column)的姓名、特点等信息。它描绘了一个数据库所具有的结构,记录在数据库中的数据都需求遵循 Schema 里的界说。
区别于运用程序自身的晋级,Schema 版别办理问题,本质上是一种耐久化数据的晋级,这一特征伴随着两个疑问:
-
耐久化数据怎么晋级:云原生时代的交给,现已无法跳脱出容器化、渠道化的特征。各大云原生渠道在进行软件交给过程中,都不会容易将耐久化数据归入版别操控体系中去。原因很简单,每个交给环境中的数据都是不同的,晋级过程中很难挑选耐久化数据的一致版别办理计划。
-
哪些耐久化数据需求晋级:既然难以挑选耐久化数据的一致版别办理计划,那么退而求其次,是否能够优先挑选必要的耐久化数据进行版别办理。缩小规模之后,就突出了数据库表结构这一特殊耐久化数据类型。其版别办理的必要性是显而易见的,运用程序自身从V1版别晋级到了V2版别,那么对应的数据库表结构也需求增加必要的新表、新列。
这两个疑问引出了本文的宗旨:在企业级软件交给范畴,怎么合理的在每次晋级的过程中处理数据库表结构(Schema)的版别操控?
传统软件交给范畴,在 Schema 版别办理方面有两种干流的处理计划:
-
人工处理:这是最根底的 Schema 版别办理方法。现场交给人员不只需求处理运用程序的晋级流程,也直接操作数据库,完结 Schema 的晋级。这种方法最直接,可是无法主动化处理的流程都具有一些通病:低效、易错。
-
代码处理:这是一种进阶的方法。经过在运用程序内部引进第三方库,来进行 Schema 的版别办理。这一操作现已能够革除交给现场的人工处理流程,交给人员只需求将运用程序进行更新,程序自身会衔接到数据库,对 Schema 作出主动化的改变。这种方法的主动化程度现已能够满足要求,可是也具有引进第三方库的通病:技术本钱提升、侵入性、与言语或结构绑定。
云原生时代的处理思路
云原生时代,运用程序的运用者、交给者都期望经过所选用的渠道来赋能自己的运用程序。在本文讨论的范畴中,这种等待能够详细的描绘为:借助渠道才能,以无侵入的方法,将 Schema 版别办理才能赋予运用,使得运用在进行一键晋级时, Schema 也主动完结晋级。
Rainbond 作为一款云原生运用办理渠道,也在不断探究为运用赋能之道。在 Schema 版别办理范畴,实现了在源码构建过程中集成 Schema 版别办理的才能。运用自身不需求改动任何代码,只是需求将两种类型的文件放进代码根目录下的指定目录下即可。这两种文件别离是:界说了数据库实例衔接地址的配置文件,晋级 Schema 所运用的 Sql 脚本文件。
关于源码构建
源码构建功用,自身就是一种 Rainbond 对运用的赋能。云原生时代,运用都在向容器化的方向跨进。容器化的过程中看似无法革除 Dockerfile 的编写,实则不然。源码构建功用能够直接对接源代码,将其编译成为可运转的容器镜像。整个过程不需求开发人员的介入,供给代码库房地址即可,极大的降低了开发人员的技术担负。
在源码构建的流程中,以无侵入的方法集成了许多才能。比方经过归入 Pinpoint-agent 的方法集成 APM 才能。再比方经过归入 jmx-exporter 的方法集成自界说事务监控才能。今天要点描绘的,是经过归入 Liquibase 的方法,集成 Schema 版别操控才能。
关于Liquibase
Liquibase 是一款专门用于数据库表结构版别操控的 CI/CD 工具。从 2006 年开端,Liquibase 团队一向致力于让数据库改变办理更简单,尤其是在敏捷软件开发范畴。这一工具依据 Apache 2.0 协议开源。
经过长时间的迭代,Liquibase 现已十分老练可靠,经过 sql、yaml、xml、json 在内的多种文件格局,开发人员能够快速的界说出契合 Liquibase 风格的数据库表结构改变文件,这种文件被称之为 changelog。依据 changelog 中的界说,Liquibase 能够十分便利的在多个改变操作版别之间晋级与回滚。
Liquibase 供给多种方法供开发人员交互,包含一种通用的指令行操作模式,源码构建经过指令行形式集成 Liquibase 的 Schema 版别办理才能。
代码界说的Schema版别操控才能
Rainbond 源码构建推崇代码界说各种才能。关于 Schema 版别操控才能而言,也是经过代码库房中的指定文件来界说的,咱们能够扼要的称之为 Schema As Code,这种代码界说才能的实践,要求每一次 CI 作业都由一个代码库房地址开端,比方 Git。关于每一个数据库实例来说,经过指定目录下的配置文件和 changelog 来界说数据库表结构版别。默许情况下,是指代码根目录下的 Schema
目录。
下面是一个代码结构示例,Rainbond 官方一起供给了一份完整的代码示例 java-maven-demo :
.
├──Procfile
├──README.md
├──Schema
│├──changelog.sql#界说数据库表结构
│└──mysql.properties#界说数据库实例衔接信息
├──pom.xml
└──src
Schema
目录下的 mysql.properties
和 changlog.sql
文件界说了怎么进行 Schema 版别操控。
mysql.properties
界说了数据库实例的衔接方法,以及所引用的 changelog
文件地址。
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_DATABASE}?createDatabaseIfNotExist=true&characterEncoding=utf8
username=${MYSQL_USER}
password=${MYSQL_PASSWORD}
changeLogFile=changelog.sql
最简化界说项包含:
-
driver:指定运用的 jdbc 驱动,源码构建中集成的驱动支撑mysql、mariadb、mssql、mongo、postgresql、sqlite等常见类型数据库。
-
url:界说数据库衔接地址,能够经过 jdbc 的规范写法来预创数据库实例。
-
username&password:界说数据库实例的登录凭证。
-
changeLogFile:界说该数据库实例表结构改变文件的途径。
源码构建过程中,会遍历识别 Schema
目录下的所有 properties
文件,并在发动时处理每一个数据库实例的 Schema 版别操控流程。经过配置文件的组合,在以下各种常见场景中都能够很好的作业。
-
单个数据库实例
-
多个相同类型数据库实例,比方运用一起衔接了多个 mysql
-
多个不同类型数据库实例,比方运用一起衔接了mysql、mongo
-
同个数据库中的多个数据库实例,比方运用一起运用同个 mysql 中的多个库实例
changlog 的最佳实践
changelog
文件,是办理 Schema 的关键所在。以下是一个示例:
--liquibaseformattedsql
--changesetguox.goodrain:1
createtableperson(
idintprimarykey,
namevarchar(50)notnull,
address1varchar(50),
address2varchar(50),
cityvarchar(30)
);
--rollbackdroptableperson;
--changesetguox.goodrain:2
createtablecompany(
idintprimarykey,
namevarchar(50)notnull,
address1varchar(50),
address2varchar(50),
cityvarchar(30)
);
--rollbackdroptablecompany;
引荐运用 sql 类型的 changelog
文件来界说 Schema 版别,由于这最契合开发人员的习气。
changlog
文件经过注释来界说一些行为。常见如下:
#界说changelog文件的格局,这是每一个changelog文件的开头项
--liquibaseformattedsql
#界说改变集,后面跟随的,是开发人员姓名,以及改变集的序号,这个序号很重要,主张运用有序数字来界说
--changesetguox.goodrain:1
#界说回滚操作,每一个改变集都应该界说与之对应的回滚操作,这使得在改变出现问题时,快速回滚到指定版别的改变集
--rollbackdroptablestaff;
Liquibase 官方提出了一系列的最佳实践,有一些最佳实践应该作为开发人员的默许行为。
-
每个改变集仅包含一个改变,经过细化数据库表结构的改变版别,这能够防止失利的主动提交语句使数据库处于意外状况。
-
changeset 的 ID,挑选有序且绝无仅有的数列,或者对开发者友好的姓名。
-
让版别永远可回滚,为每一个 changeset 设置合理的回滚操作。
有关于 mysql.properties
和 changlog.sql
文件的写法,更多的特性请参考 liquibase 文档 ,这些特性都能够被源码构建所继承。
Schema生命周期流程
1. 构建流程
履行正常的源码构建流程时,会主动识别代码根目录下的 Schema
目录,预备 Schema 版别办理所需求的根底环境,包含 jre 和 Liquibase 工具包。
构建日志会有以下提示:
2. 发动流程
完结构建流程后,服务组件会主动进入发动过程中, Rainbond 渠道会依据代码中界说好的配置文件,针对每一个数据库实例,进行主动晋级处理。
处理过程中,在服务组件的日志中的头部位置,会打印相关的记录:
上图中演示了针对同一个 mysql 数据库中的多个库实例进行表结构的晋级操作。关于空的库实例而言,这也相当于一次初始化的操作。
在示例中,Rainbond 别离向运用所衔接的同个 mysql 数据库中的两个库实例(别离名为 Initialize
anotherdb
)进行了表结构初始化操作,别离创建了表company
、person
以及 another_company
、another_person
。在数据库组件的 Web终端登录后,能够验证:
3. 发布到组件库
Rainbond 特有的发布机制,能够将事务组件和数据库组件一致发布为一个运用模版。便利在不同的环境中一键装置交给。经过运用模版交给的运用,仍然具有 Schema 版别操控的才能。全新装置的运用模版,其数据库也会被初始化为上述状况。在这里,咱们称发布的运用为源运用,由运用模版装置而来的运用为已交给运用。
4. 代码更新
当开发人员继续迭代事务体系的时分,Schema 也随之改动,假定新版别的事务体系,要求 Initialize
新增表 staff
,并为已有的 person
表增加一个新的列 country
。那么开发人员应该为对应的 changelog.sql
文件新增以下内容,并和新的事务代码一起提交,确保事务代码和 Schema 保持一致。
--changesetother.goodrain:3
altertablepersonaddcolumncountryvarchar(2);
createtablestaff(
idintprimarykey,
namevarchar(50)notnull,
address1varchar(50),
address2varchar(50),
cityvarchar(30)
);
--rollbackdroptablestaff;
--rollbackaltertablepersondropcolumncountry;
在源运用处点击构建,Rainbond 会拉取最新的代码,更新事务运用的一起,为 Schema 进行晋级。
构建过程中没有任何改变,可是在发动过程中,针对更新的 Initialize
和保持原状的 anotherdb
库实例,Rainbond 给出两种不同的处理:
5. 依据运用模版的晋级
源运用有了新的版别,已交给运用也应随之有改变。首先,运用模版需求有一个更新的版别,重复发布流程,界说更高的版别号即可。已交给运用能够依据 Rainbond 的提示,一键晋级到更新后的版别。
6. 验证
登录已交给运用的数据库组件中,能够检查对应的 Schema 改变。
7. 回滚
数据库表结构的回滚操作是一个很严肃的问题。本着数据库表结构只增不减的原则,现已生效的 Schema 不会随着已交给运用的一键回滚而有任何变动。假如一定要进行回滚,则需求运维人员登录事务组件的 Web终端手动操作。
需求注意的是回滚的次序:数据库表结构应该先于运用程序回滚。这是由于一旦运用程序回滚完结, changlog 文件自身也回滚到了上个版别,无法再进行数据库表结构的回滚。
履行以下指令,能够依据指定的配置文件,对数据库表结构进行回滚操作,回滚起伏以 1 个 changeset 为单位。
cdSchema/
liquibaserollbackCount1--defaults-file=mysql.properties
鉴于回滚后的事务组件一旦重启或更新,就会比对 changelog 文件后重新晋级 Schema,所以在履行回滚操作后,必须增加环境变量 ALLOW_SCHEMA_UPDATE=false
来禁用 Schema 版别办理操控功用,直到新版别运用模版的晋级。
常见问题
- 怎么在
*.properties
配置文件中合理的界说所有数据库实例的衔接地址和凭证?
运用环境变量来替代
*.properties
配置文件中的数据路实例衔接地址和凭证信息,界说方法详见文中的示例。Rainbond 源码构建过程中,会拾取运转环境中的所有环境变量,对目标配置文件进行渲染,所以关于环境变量的命名并不重要,只需求确保界说的环境变量会在终究交给环境中生成即可。无论环境变量来自于自界说的环境配置仍是 Rainbond 独有的衔接信息机制。
- 履行回滚操作失利?
回滚怎么操作,界说在 changlog 文件中。必须确保每一个 changeset 都有对应的回滚战略,方可确保每次回滚都得到正确的成果。
- 履行 Schema 晋级的过程中报错:
!! Failed to check the database status. Check /app/Schema/xxx.properties.log
每一次履行 Schema 改变的过程中,都会先进行检查,包含数据库实例地址的连通性、changelog 文件的可履行性。假如检查不经过,则不会对数据库作出任何操作,可是检查的成果会记录在日志文件中,能够登录 Web 终端,检查提示中的日志文件内容。
- 老用户怎么获取 Schema 版别操控功用?
这一功用和 Rainbond 的版别脱离,所以老用户能够经过更新源码构建相关组件来获取这一才能。履行以下一组指令即可:
#以下指令在 Rainbond 集群内任意节点履行;假如你运用 dind-allinone 版别,则应该在 rainbond-allinone 容器中履行 hubpassword=$(kubectlgetrainbondcluster-oyaml-nrbd-system|greppassword|awk'{print$2}') dockerlogin--username=admin--password=${hubpassword}goodrain.me images=(builderrunner) forimagein${images[@]} do dockerpullregistry.cn-hangzhou.aliyuncs.com/goodrain/${image}:v5.5.0-release dockertagregistry.cn-hangzhou.aliyuncs.com/goodrain/${image}:v5.5.0-releasegoodrain.me/${image} dockerpushgoodrain.me/${image} done
References Link
Liquibase www.liquibase.com
java-maven-demo gitee.com/rainbond/ja…
关于Rainbond
Rainbond 是一个开源的云原生运用办理渠道,运用简单,不需求懂容器和Kubernetes,支撑办理多个Kubernetes集群,供给企业级运用的全生命周期办理,功用包含运用开发环境、运用商场、微服务架构、运用继续交给、运用运维、运用级多云办理等。
Github:github.com/goodrain/ra…
官网:www.rainbond.com
微信群:重视 Rainbond 大众号参加技术交流群
钉钉群:请搜索钉钉群号 31096419
本文运用 文章同步助手 同步