nacos2.2.3修改源码支持人大金仓数据库,并构建docker镜像

背景:项目要求数据库国产化,并最终选用微服务+人大金仓数据库,选中nacos作为配置中心,但nacos没有对人大金仓数据作支持。

注意:人大金仓与postgresql数据雷同,两个的支持操作是一致的,只需要把pg的驱动替换为人大金仓的驱动即可,以下操作用pg数据库为例

一.Nacos2.2版本数据库适配插件—

原文链接:https://github.com/wuchubuzai2018/nacos-datasource-extend-plugins

从2022年12月14日发布的Nacos2.2正式版本开始,Nacos提供了数据源扩展插件,以便让需要进行其他数据库适配的用户自己编写插件来保存数据。当前项目插件目前已简单适配Postgresql,并抽象了一套常见的兼容项的方言类,开发者可以基于该设计,实现自定义分页逻辑即可。

1.插件工程结构说明

nacos-datasource-plugin-ext工程主目录
----nacos-datasource-plugin-ext-base工程设计为数据库插件操作的适配抽象。
----nacos-all-datasource-plugin-ext工程计划可打包所有适配的数据库插件
----nacos-postgresql-datasource-plugin-ext工程可打包适配Postgresql的数据库插件

2、下载和使用

IDEA导入时导入nacos-datasource-plugin-ext这个目录作为根目录即可。

3.插件引入

方式一:源码方式
使用postgresql作为依赖引入到Nacos主分支源码中,使用Maven提前将当前工程Install到Maven仓库,然后在Pom.xml中引入如下依赖:

<dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-postgresql-datasource-plugin-ext</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>

或引入all模块。

方式二:打包形式引入(虽然该方式更简便,但由于要修改源码,我测通的是方式一)
在Nacos2.2的发布包环境下,下载当前插件项目源码,打包为jar包,将该文件放到nacos主目录下的plugins文件夹中,默认会使用Nacos的loader.path机制指定该插件的路径,打包插件可选择nacos-postgresql-datasource-plugin-ext打包即可。postgresql模块的打包默认会包含postgresql的jdbc驱动类和base依赖。

3.修改数据库配置文件

在application.properties文件中声明postgresql的配置信息:
src/main/resources/application.properties

spring.datasource.platform=postgresql
db.url.0=jdbc:postgresql://127.0.0.1:5432/nacos?tcpKeepAlive=true&reWriteBatchedInserts=true&ApplicationName=nacos_java
db.user=nacos
db.password=nacos
db.pool.config.driverClassName=org.postgresql.Driver
4.导入Postgresql的数据库脚本文件

导入nacos-postgresql的脚本文件,脚本文件在nacos-postgresql-datasource-plugin-ext/src/main/resources/schema文件夹下面.
上面操作完成后,启动Nacos即可。

5.其他数据库插件开发

可参考nacos-postgresql-datasource-plugin-ext工程,新创建Maven项目,实现AbstractDatabaseDialect类,重写相关的分页操作逻辑与方法,并创建相应的mapper实现,减少了适配的成本。
目前对于Oracle、达梦数据库,仍然需要修改Nacos2.2的主分支代码,因为要兼容默认的命名空间ID为空的查询情况,社区官网未处理。

二.修改源码支持pg数据库或者人大金仓数据库

版权声明:本文为CSDN博主「磕死在代码块上的小T同学」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/And__One/article/details/131283266

1.从nacos官网获取源码:

https://github.com/alibaba/nacos/releases

2.项目结构如下,项目启动在于console模块,选择主程序Nacos运行

image.png

3.添加依赖
  • 根pom添加pg依赖
<postgresql.version>42.5.1</postgresql.version>
 
 <dependency>
      <groupId>org.postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <version>${postgresql.version}</version>
</dependency>

如何是人大金仓数据库的时候, 由于人大金仓数据库没有更新到maven库,需要离线引入或者先上传到本地maven库

使用Maven的命令进行安装

mvn install:install-file -Dfile="xxxx/kingbase8-8.6.0.jar" -DgroupId="com.kingbase8" -DartifactId="kingbase8" -Dversion="8.6.0" -Dpackaging="jar"
<!--        人大金仓数据连接-->
<kingbase.version>8.6.0</kingbase.version>

<dependency>
    <groupId>com.kingbase8</groupId>
    <artifactId>kingbase8</artifactId>
    <version>${kingbase.version}</version>
</dependency>
  • config模块pom添加依赖
<dependency>
      <groupId>org.postgresql</groupId>
      <artifactId>postgresql</artifactId>
</dependency>
  • naming模块pom添加依赖
<dependency>
      <groupId>org.postgresql</groupId>
      <artifactId>postgresql</artifactId>
</dependency>

以下操作在nacos插件项目单独执行打包***********

  • plugin模块

/plugin/datasource/src/main/resources/META-INF/services 下增加以下数据
com.alibaba.nacos.plugin.datasource.mapper.Mapper

com.alibaba.nacos.plugin.datasource.impl.postgresql.ConfigInfoAggrMapperByPostgreSql
com.alibaba.nacos.plugin.datasource.impl.postgresql.ConfigInfoBetaMapperByPostgreSql
com.alibaba.nacos.plugin.datasource.impl.postgresql.ConfigInfoMapperByPostgreSql
com.alibaba.nacos.plugin.datasource.impl.postgresql.ConfigInfoTagMapperByPostgreSql
com.alibaba.nacos.plugin.datasource.impl.postgresql.ConfigTagsRelationMapperByPostgreSql
com.alibaba.nacos.plugin.datasource.impl.postgresql.HistoryConfigInfoMapperByPostgreSql
com.alibaba.nacos.plugin.datasource.impl.postgresql.TenantInfoMapperByPostgreSql
com.alibaba.nacos.plugin.datasource.impl.postgresql.TenantCapacityMapperByPostgreSql
com.alibaba.nacos.plugin.datasource.impl.postgresql.GroupCapacityMapperByPostgreSql

*详情查看nacos制作插件

4.直接在nacos-console模块中引入
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-postgresql-datasource-plugin-ext</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
5.源码修改:

ExternalDataSourceProperties.java

private static final String JDBC_DRIVER_NAME = "com.mysql.cj.jdbc.Driver";
/**
* Build serveral HikariDataSource.
*
* @param environment {@link Environment}
* @param callback Callback function when constructing data source
* @return List of {@link HikariDataSource}
*/
List<HikariDataSource> build(Environment environment, Callback<HikariDataSource> callback) {
// ...
// 原代码
// poolProperties.setDriverClassName(JDBC_DRIVER_NAME);
// 修改后
// 支持postgresql与mysql
 
if (PropertiesConstant.POSTGRESQL.equalsIgnoreCase(
        EnvUtil.getProperty(SPRING_DATASOURCE_PLATFORM))) {
    // 增加对postgresql数据库的支持
    poolProperties.setDriverClassName(JDBC_DRIVER_NAME_POSTGRESQL);
    System.out.println("jdbcDriverName=增加对postgresql数据库的支持" + JDBC_DRIVER_NAME_POSTGRESQL);
} else {
    // 默认使用mysql驱动
    poolProperties.setDriverClassName(JDBC_DRIVER_NAME);
}
 
// ...
}

com.alibaba.nacos.config.server.service.repository.extrnal.ExternalConfigInfoPersistServiceImpl
当修改配置文件的时候前端页面显示成功,但是配置数据没有更新,我们通过执行源码可以发现,这是由于2.2.3版本修改配置文件的接口和新增是同一个接口insertOrUpdate,执行的依据就是先拿着这个dataId(该配置文件的id)去新增,如果新增失败,并且报主键重复的异常才去执行更新操作:
image.png
但这里要注意的是,这个异常是mysql的异常,当使用pg数据库时候,报的错不是主键重复的异常,导致虽然新增是由于主键重复失败了,但是没有走update的方法,所以虽然前端显示更新成功,但是数据没有更新,这里我们修改源码,改成pg数据库的主键重复的异常(或者简单粗暴直接扩大异常的范围使逻辑进入update方法)
修改后的源码:

   @Override
    public void insertOrUpdate(String srcIp, String srcUser, ConfigInfo configInfo, Timestamp time,
            Map<String, Object> configAdvanceInfo, boolean notify) {
        try {
            addConfigInfo(srcIp, srcUser, configInfo, time, configAdvanceInfo, notify);
        } catch (DataIntegrityViolationException ive) { // Unique constraint conflict
            updateConfigInfo(configInfo, srcIp, srcUser, time, configAdvanceInfo, notify);
        }
    }

pg报错是出现的DataIntegrityViolationException这个异常错误,我们用这个异常替换mysql的主键重复异常来使得update方法正常执行。

6.启动Nacos

nacos-console模块: 使用console模块配置文件
src/main/resources/application.properties
单机模式启动,注意配置

7.源码编译

在Terminal窗口执行命令

mvn -Prelease-nacos '-Dmaven.test.skip=true' '-Dcheckstyle.skip=true' clean install -U

注意:编译之前此处需要加上版本号,不用可能会报错,如下图(根据实际情决定是否需要)

注意,如果编译失败的话,有可能是nacos配置了PMD检查导致,根据错误提示找到对应的文件修改就行,一般是注释或者过期代码未删除导致
image.png

image.png

三.构建docker镜像

1.首先使用git拉取nacos官方提供的镜像制作工具
git clone https://github.com/nacos-group/nacos-docker.git

拉取成功后目录是这样,我们只是制作一个镜像,只需要用到其中的build文件夹

1、将第一步中构建成功的tar包复制到build文件夹下,让他们出于同一目录

2、修改Dockerfile文件


注意:下载的所有文件格式如果是在linux系统执行的话,会有格式问题

正常编写的.sh文件拷贝到docker容器,启动时报错no such file or directory,大概率是格式问题
可以用notepad++转换成unix格式,在拷贝到linux环境

如果在linux环境下,我们可以用vi命令打开文件,然后在普通模式下输入:set ff
在命令窗口下输入:set ff可查看当前文件格式

如果显示fileformat=dos,我们可以使用命令:set ff=unix修改文件格式

一定要注意,不只是DockerFile文件,你挂载到docker容器内的所有文件都可能有这个错误,都要检查一遍,我是将.sh文件挂载到容器内,只修改了dockerfile文件,没有关注sh文件,卡了一下午!
image.png

dockerfile命令工具:

//可以通过以下命令查看docker容器内是否有需要的文件
RUN ls -n /home/nacos/
//由于这个展示的结果太快,我们可以把执行结果保存在文件中查看
docker build -t nacos-kingbase:2.2.3 . > build.log 2>&1
//如果给定的程序有问题导致docker容器挂掉,我们可以先用下面的指令替换,让容器一直运行
ENTRYPOINT ["tail","-f","/dev/null"]

问题记录:
nacos把数据库错误封装了,连不上数据库就报 No DataSource set
我先是在docker容器内查看到外部配置文件挂载成功,然后在源码中打印了外部配置文件的数据库连接信息,确认能获取到,然后在容器内检查网络与端口通畅,最后在 手动连接数据库才获取到根本问题。
image.png
image.png
image.png
以下是大佬的解决方案:

人大金仓kingbase invalid value for parameter client_encoding ANSI_X3.4-1968

作者:dsjaikdnsajdnua
链接:https://www.jianshu.com/p/877872aa3cfb
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

错误

应用连接数据库的时候提示以下错误:


    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.cloud.autoconfigure.RefreshAutoConfiguration$JpaInvokerConfiguration.init(RefreshAutoConfiguration.java:120)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157)
    ... 26 common frames omitted
解决步骤
  1. 解决初始化连接返回的乱码信息
com.kingbase8.util.KSQLException: ������������: ������ "client_encoding" ������������: "ANSI_X3.4-1968"

在以上信息可以看到,这个应该是链接的时候返回的,第一反应就是去查看kingbase日志:/data/kingbase/ES/V8/data/sys_log。可以看到如下信息:

2021-04-14 16:18:43 CST 致命错误:  参数 "client_encoding" 的值无效: "ANSI_X3.4-1968"

终于发现错误本体了,但是,是什么导致了乱码?乱码肯定是中文不是英文了,所以应该有什么地址可以设置日志的编码。不过kingbase基本和postgresql一致,所以按照postgresql的方法修改日志的编码即可。大致找了下kingbase的日志,发现在这个文件kingbase.conf
修改kingbase.conf日志编码

lc_messages = 'zh_CN.UTF-8'
//修改成:
lc_messages = 'en_US.UTF-8'

之后可以看到java的日志打印正常了:FATAL: invalid value for parameter “client_encoding”: “ANSI_X3.4-1968”
2.调试源码
根据提示信息查找,发现并没有查看到有用的信息,所以尝试调试源码
在以下文件的对应方法[com.kingbase8.core.v3.ConnectionFactoryImpl#openConnectionImpl]找到了108行关键代码:

newStream = new KBStream(socketFactory, hostSpec, connectTimeout);
String client_encoding;
if (KBProperty.CLIENT_ENCODING.get(info) == null) {
client_encoding = System.getProperty("file.encoding");
info.setProperty("clientEncoding", client_encoding);
LOGGER.log(Level.FINE, "Use current JVM default encoding {0}", client_encoding);
}

client_encoding = KBProperty.CLIENT_ENCODING.get(info);
newStream.setEncoding(Encoding.getJVMEncoding(client_encoding));
  • 可以看到初始化连接的时候,获取了jvm_encoding。这里,我们可以调试一下,在容器下的jvm_encoding究竟是什么编码?

可以使用arthas修改容器class文件打印以下,或者随便在启动的时候日志打印以下System.getProperty(“file.encoding”)。容器只记录日志的输出,所以可能使用System.out.println会无法显示。
修改docker的jvm_encoding
在dockerfile添加以下代码即可:ENV JAVA_TOOL_OPTIONS -Dfile.encoding=UTF8
完整的Dockerfile大致如下

修改重新build了之后可以发现,连接正常了。

网上关于人大金仓的资料比较少,如果遇到问题,可以尝试把关键字更换成postgresql再查看,也许更容易查找到答案

3、修改conf/application.properties(注意编码)

4.将整个build文件夹上传到服务器的某个目录下

5、构建镜像和容器

方法一:

进入build目录下,利用dockerfile文件构建nacos镜像

docker build -t nacos-server . (注意此行命令nacos-server后面有一个空格 和 . ),执行结束 ,docker images命令即可查看镜像

通过镜像构建容器

docker run -d --name nacos-server -e MODE=standalone -e DB_SERVICE_HOST=127.0.0.1 -e DB_SERVICE_PORT=5432 -e DB_SERVICE_USER=postgres -e DB_SERVICE_PASSWORD=jsjm123.0 -e DB_SERVICE_DB_NAME=nacos -e SPRING_DATASOURCE_PLATFORM=postgresql -p 8848:8848 nacos-server

方法二:通过docker-compose文件,构建镜像和容器

编写docker-compose文件:然后 直接在docker-compose.yml文件所在的目录执行 docker-compose up -d nacos 即可完成镜像和容器的构建

  • 13
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值