一、引言
项目落地银行有信创要求,需要将 Nacos 依赖的外源数据库从 MySQL 更换为达梦数据库。Nacos 官方不支持达梦数据库,需要修改源码进行适配。
二、正文
2.1 数据库准备
下载镜像
加载镜像
# 镜像上传到服务器后,执行加载命令 docker load -i dm8_20240715_x86_rh6_rq_single.tar容器启动
# 默认用户密码:SYSDBA/SYSDBA001 docker run -d \ -p 5236:5236 \ --restart=always \ --name=dm8 \ --privileged=true \ -e LD_LIBRARY_PATH=/opt/dmdbms/bin \ -e PAGE_SIZE=16 \ -e EXTENT_SIZE=32 \ -e LOG_SIZE=1024 \ -e UNICODE_FLAG=1 \ -e INSTANCE_NAME=dm8 \ -v /opt/dmdbms/data:/opt/dmdbms/data \ dm8_single:dm8_20240715_rev232765_x86_rh6_64
2.2 集成达梦驱动
下载依赖
可以选择在达梦官网或者Maven中央仓库下载:
达梦官网驱动地址:jdbc-20240326.zip
mvn install:install-file -Dfile=E:\dmdbms\drivers\jdbc\DmJdbcDriver18.jar -DgroupId=com.dameng -DartifactId=DmJdbcDriver18 -Dversion=8.1.3.140 -Dpackaging=jar- Maven中央仓库:DmJdbcDriver18
添加依赖
在nacos-all的pom中指定添加如下内容
<DmJdbcDriver18.version>8.1.2.192</DmJdbcDriver18.version> <dependency> <groupId>com.dameng</groupId> <artifactId>DmJdbcDriver18</artifactId> <DmJdbcDriver18.version>8.1.3.140</DmJdbcDriver18.version> </dependency>在nacos-config、nacos-naming 两个模块添加依赖:
<dependency> <groupId>com.dameng</groupId> <artifactId>DmJdbcDriver18</artifactId> </dependency>
2.3 初始化数据库
Nacos团队提供了达梦初始化脚本供参考:nacos-dm.sql,但其中有一些错误。
# 脚本把NACOS错写成NOCOS了,可以直接把脚本中的NOCOS去掉
# 复制脚本到容器容器
docker cp nacos-dm.sql dm8:/opt/dmdbms/data/
# 进入容器
docker exec -it dm8 bash
# 使用disql执行初始化脚本
CREATE USER "nacos" IDENTIFIED BY "NACOS1234";
/opt/dmdbms/bin/disql nacos/NACOS1234
start /opt/dmdbms/data/nacos-dm.sql该文件需要被放置到文件夹~\nacos-2.2.3\distribution\conf\下,打包的时候会一块打包进来。
2.4 修改源码
本次适配基于Nocos 2.2.3版本,可以根据自己需求拉取相应版本的代码:Nacos-2.2.3
利用 SPI 的原理,自定义实现各个表的 Mapper 实现类。
将nacos-datasource-plugin里的mysql的mapper文件复制到新的dm文件夹下改名,并修改将相应的常量和配置,具体如下:
~\nacos-2.2.3\plugin\datasource\src\main\java\com\alibaba\nacos\plugin\datasource\constants\DataSourceConstant.java
public class DataSourceConstant {
public static final String MYSQL = "mysql";
public static final String DERBY = "derby";
// 添加一行
public static final String DM = "dm";
}~\nacos-2.2.3\plugin\datasource\src\main\java\com\alibaba\nacos\plugin\datasource\impl\dm\ConfigInfoAggrMapperByDm.java
public class ConfigInfoAggrMapperByDm extends AbstractMapper implements ConfigInfoAggrMapper {
@Override
public String findConfigInfoAggrByPageFetchRows(int startRow, int pageSize) {
return "SELECT data_id,group_id,tenant_id,datum_id,app_name,content FROM config_info_aggr WHERE data_id= ? AND "
+ "group_id= ? AND tenant_id= ? ORDER BY datum_id LIMIT " + startRow + "," + pageSize;
}
@Override
public String getDataSource() {
return DataSourceConstant.DM;
}
}~\nacos-2.2.3\plugin\datasource\src\main\resources\META-INF\services\com.alibaba.nacos.plugin.datasource.mapper.Mapper
# 添加如下内容
com.alibaba.nacos.plugin.datasource.impl.dm.ConfigInfoAggrMapperByDm
com.alibaba.nacos.plugin.datasource.impl.dm.ConfigTagsRelationMapperByDm
com.alibaba.nacos.plugin.datasource.impl.dm.HistoryConfigInfoMapperByDm
com.alibaba.nacos.plugin.datasource.impl.dm.ConfigInfoTagMapperByDm
com.alibaba.nacos.plugin.datasource.impl.dm.ConfigInfoMapperByMyDm
com.alibaba.nacos.plugin.datasource.impl.dm.ConfigInfoBetaMapperByDm
com.alibaba.nacos.plugin.datasource.impl.dm.TenantInfoMapperByDm
com.alibaba.nacos.plugin.datasource.impl.dm.TenantCapacityMapperByDm
com.alibaba.nacos.plugin.datasource.impl.dm.GroupCapacityMapperByDm2.5 修改启动配置
~\Java\nacos-2.2.3\console\src\main\resources\application.properties
# application.properties配置
spring.datasource.platform=dm
spring.sql.init.platform=dm
db.num=1
db.pool.config.driverClassName=dm.jdbc.driver.DmDriver
db.url.0=jdbc:dm://192.168.102.115:30236
db.user=nacos
db.password=NACOS12342.6 本地运行Nacos
找到 com.alibaba.nacos.Nacos类,启动即可。需要在启动选项的VM options中加上-Dnacos.standalone=true


2.7 打包并运行
Nacos源码打包命令
# 打包一定要选择CMD而不是PowerShell执行,不然会报错
mvn -Prelease-nacos -Dmaven.test.skip=true -Dpmd.skip=true -Dcheckstyle.skip=true clean install -U成功后,nacos包会在~\nacos\distribution\target\目录下:

重新解压nacos-2.2.3.zip,修改conf\application.properties,然后执行启动脚本
# windows环境
startup.cmd -m standalone
# linux环境
startup.sh -m standalone三、遇到的问题
3.1 执行打包脚本失败
报错
[ERROR] Unknown lifecycle phase “.test.skip=true“. You must specify a valid lifecycle phase or a ...
原因
我的IdeaUI命令行默认打开powerShell而不是Command Prompt
方案
改用CMD而不是PowerShell执行打包命令
3.2 新增文件没有凭证
报错
Too many files with unapproved license
原因
新增文件没有协议头导致报错
方案
新增的代码文件头部加入以下内容
/* * Copyright 1999-2022 Alibaba Group Holding Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */
3.3 更新配置信息,提示违反唯一性约束
报错
caused: PreparedStatementCallback; 违反表[CONFIG_INFO]唯一性约束; nested exception is dm.jdbc.driver.DMException: 违反表[CONFIG_INFO]唯一性约束;caused: 违反表[CONFIG_INFO]唯一性约束
原因
见官方仓库issue:#12289和#10335,insertOrUpdate操作捕获的异常从2.2.1开始从
DataIntegrityViolationException改为DuplicateKeyException,而达梦不会抛出DuplicateKeyException异常并处理,导致异常直接抛到上层了。方案
方案一:参考提交Handling DataIntegrityViolationException and DuplicateKey#11405修改文件
~/nacos/config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoPersistServiceImpl.java主要将两处涉及DuplicateKeyException的异常捕获做进一步捕获并处理。将
} catch (DuplicateKeyException ive) { // Unique constraint conflict return updateConfigInfo(configInfo, srcIp, srcUser, configAdvanceInfo); }改为
} catch (DuplicateKeyException ignore) { // Must be unique constraint conflict. return updateConfigInfo(configInfo, srcIp, srcUser, configAdvanceInfo); } catch (DataIntegrityViolationException dive) { // Might be unique constraint conflict or some of other data integrity violation. try to update. try { return updateConfigInfo(configInfo, srcIp, srcUser, configAdvanceInfo); } catch (Exception e) { LogUtil.FATAL_LOG .error("[db-error] try to update config failed, with DataIntegrityViolationException, {}", dive.getMessage(), e); throw e; } }- 方案二:基于Nacos 2.3及以上版本进行达梦数据库的适配
四、附录
达梦数据库建表规范(临时)
- 表名和字段名均需要COMMENT,且能清晰的标注表名和字段名的含义
- 数据表如果使用显式主键,无特殊情况下要求使用非自增,snowflake生成
- boolean使用tinyint(为了跨平台兼容),使用is开头
- 逻辑删除的字段,建议使用is_deleted或enabled等字段
- 不使用包括但不限于DOMAIN、VERIFY等达梦数据库的保留关键字作为字段名和表名
- varchar根据长度酌情使用8、32、50、128、255等几个范围,超长使用text,避免空间浪费
五、参考文献
- 【达梦技术文档】DM 数据库安装-Docker安装
- 【CSDN】DBever连接达梦
- 【CSDN】Nacos2.2.3适配达梦数据库编译打包完整教程
- 【GitHub】add_nacos_support_dameng
- 【CSDN】Nacos源码启动报错找不到符号com.alibaba.nacos.consistency.entity
- 【CSDN】Unknown lifecycle phase “.test.skip=true“. You must specify a valid lifecycle phase or a ...
- 【CSDN】Nacos Too many files with unapproved license:
- 【GitHub】2.2.1、2.2.2、2.2.3、2.2.4版本,在达梦数据库下,更新配置信息,提示违反唯一性约束