ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Nacos 2.3.0接入PostgreSQL:数据源插件化改造与迁移实践

Nacos 2.3.0接入PostgreSQL:数据源插件化改造与迁移实践 早两年做微服务改造的时候注册中心选了Nacos 2.x存储介质老老实实配的MySQL。直到去年有个项目整体数据库标准化要求所有中间件、业务库统一走PostgreSQL我才开始认真研究nacos2.3.0接入pgsql这件事。网上关于Nacos配置的文章不少但绝大多数集中在安装、启动、集群搭建真正讲清楚怎么把Nacos的存储层从MySQL切到PostgreSQL或者其他数据库的内容非常少。我踩了不少坑也把插件化数据源的机制大致摸了一遍这篇就把整个实操过程、配置改动、验证方法和遇到的各种问题完整记录下来。1. 为什么我非要把Nacos的默认存储从MySQL换成PostgreSQL1.1 背景注册中心存储很少被关注但换库时它最麻烦很多团队对Nacos的认知停留在配置中心和注册中心觉得它本身就是一个服务数据存哪无所谓。实际上Nacos从1.x开始就把配置数据、用户权限数据、集群元数据持久化到外部数据库默认支持的是MySQL。日常用着没什么感觉因为配置中心里的数据量不大MySQL那点负载根本不算什么。真正让人头疼的是企业数据库标准化这类需求。当集团规定所有系统统一用PostgreSQL或者因为数据库许可、运维团队技能栈、数据分析需要等原因要把MySQL整体替换掉时Nacos就会成为最后几个顽固分子之一。你会发现在用的中间件里Redis、ES、MQ都有自己的存储体系唯独Nacos直接依赖关系型数据库而且默认只给你MySQL的脚本和配置模板。想换库没有现成答案只能自己研究。另外一个驱动因素是成本。小团队可能觉得多维护一个MySQL实例没什么但到了几十个微服务、多套环境的规模数据库类型越杂备份、监控、账号权限、SQL审核那套流程就越难统一。把Nacos并进已有的PostgreSQL集群里至少在运维侧少了一类数据库要维护。1.2 选型思考统一数据库带来的维护红利与迁移成本换库之前我也犹豫过毕竟Nacos MySQL是官方默认组合PostgreSQL接入在2.2.0之前几乎不可行。当时权衡了几个点团队对PostgreSQL更熟悉日常已经管理了几套PG集群不需要为了Nacos单独学MySQL运维。数据库实例数量减少备份策略、监控告警规则、账号审批流程都能复用现有规范。配置中心的数据量很小PostgreSQL承载完全没有压力IO表现甚至比单机MySQL更稳定。风险点主要在于Nacos对PostgreSQL的兼容是否完全可靠这个只能靠测试环境实测。我的结论是迁移成本主要集中在打通数据源插件和确认SQL兼容性上而不是数据库本身。一旦接入方案跑通后续所有环境都照做收益是长期的。如果你也在纠结要不要换建议从运维规范角度出发而不是从性能角度出发因为Nacos的配置存储本来就不是性能瓶颈。2. Nacos 2.2插件化数据源能接PG的底层原因2.1 插件化改造解决的是什么问题Nacos 2.2.0之前数据源是写死在代码里的数据库方言、默认建表脚本、分页查询语句这些都和MySQL绑定。你就算把application.properties里的连接串改成PostgreSQL地址启动时也会因为SQL语法不兼容或者表结构缺失而报错。社区里有人通过改源码重新编译的方式强行支持PG但那体验很差每升级一个Nacos版本都要重新维护一套分支。2.2.0版本之后Nacos把数据源部分抽成了可插拔的SPI扩展点。简单理解就是Nacos只定义了一套数据源接口默认带MySQL的实现你想用其他数据库就自己提供一个符合接口规范的插件启动时Nacos会通过Java的SPI机制把它加载进来。这样一来核心代码不用改升级Nacos版本时只要对应的插件还兼容就行。这套机制真正解决的是耦合问题。以前换数据库等于改Nacos源码现在换数据库等于换插件jar包边界清晰得多。也正因为这个改动PostgreSQL、达梦这些数据库才有可能通过社区插件或者自研插件接入Nacos 2.3.0。2.2 PG插件与SPI加载机制实际操作时我们需要关注三个组成部分数据源插件jar、JDBC驱动、application.properties配置。插件jar负责告诉Nacos我支持PostgreSQL方言我能提供连接池管理JDBC驱动负责底层与PostgreSQL通信配置里的spring.datasource.platformpostgresql则是对Nacos的一个提示让它去加载对应平台的数据源插件。加载过程大概是Nacos启动时扫描插件目录读取SPI描述文件把声明好的数据源插件实现类实例化然后根据spring.datasource.platform的值决定用哪一个。如果你只改了数据库连接串而没有部署对应插件Nacos会找不到PostgreSQL实现最终退回默认逻辑或者直接启动失败。所以不要把这三件事拆开看它们是一个整体。2.3 官方支持范围和技术边界需要说明的是Nacos 2.3.0官方发行版默认内置的还是MySQL数据源插件。PostgreSQL支持更多是社区插件或作者自己按扩展点实现的方案。我去翻过官方GitHub的issue和文档官方态度是通过插件机制可以支持更多数据库但官方只保证MySQL的稳定兼容。这意味着核心的配置发布、配置查询、登录认证这些功能在PG上实测是可用的。极冷门的高级特性可能没人验证过需要自己测试兜底。插件版本要和Nacos版本匹配尤其是大版本升级时务必重新验证。明白这层边界之后你就会知道不该指望官方开箱即用而是要走引入社区插件或自研插件这条路。这样心里有数后面遇到问题就不慌。3. 落地实操从PG实例到插件包再到配置修改3.1 准备PostgreSQL实例与nacos账号我这边用的PostgreSQL版本是14Nacos版本是2.3.0。如果你的PG版本是12或者15问题也不大因为Nacos用到的都是很基础的SQL能力。第一步是准备库和账号CREATE DATABASE nacos_config; CREATE USER nacos WITH PASSWORD your_strong_password; GRANT ALL PRIVILEGES ON DATABASE nacos_config TO nacos;注意PostgreSQL里GRANT ALL PRIVILEGES ON DATABASE只赋予库级别权限表级别权限需要在建表之后补充。最简单的做法是让nacos账号成为这个库的owner或者在建完表后显式授权。我遇到过一种情况表建好了nacos账号查询时报permission denied for table config_info就是因为表是postgres超级用户建的没有把权限给nacos。所以建表脚本执行完后记得补一句GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO nacos; GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO nacos;生产环境原则上不建议用超级用户跑Nacos给个独立账号是底线。反正PG的权限模型也不复杂把表、序列授权给这个账号就行。3.2 建库建表SQL脚本转换的三种选择Nacos官方仓库里提供的是nacos-mysql.sql脚本直接拿到PG里执行是不行的。需要转换主要有三种路子第一种去社区找现成的nacos-postgresql.sql。GitHub上搜索Nacos PostgreSQL SQL能找到一些项目但要注意脚本对应的Nacos版本。我见过有人拿着2.2.0的PG脚本去配2.3.0虽然大部分表结构没变但如果是认证模块加了字段后面登录和权限功能就会出怪问题。所以尽量找和你的Nacos版本匹配的脚本或者至少确认表字段一致。第二种自己从MySQL脚本手工转换。核心改动点包括把AUTO_INCREMENT换成BIGSERIAL或者GENERATED BY DEFAULT AS IDENTITY把DATETIME换成TIMESTAMP把ENGINEInnoDB DEFAULT CHARSETutf8mb4这种建表属性去掉把ON UPDATE CURRENT_TIMESTAMP调整为PG触发器或者省略。Nacos表里还有encrypted_data_key这种字段在MySQL里可能是mediumtextPG里直接text就行。第三种也是我推荐的方式用工具辅助转换再做人工校验。Navicat、DBeaver这类工具导出MySQL表结构后可以通过一些转换规则生成PG版本但不保证百分百准确。我这次是先找个现成的PG脚本来对再拿MySQL脚本里最新的字段定义逐项核对确认没有缺失。Nacos核心表主要有config_info配置主表、config_history_info历史配置表、config_tags_relation标签关系表、users、roles、permissions认证授权相关表、tenant_info命名空间租户表。如果你的Nacos版本启用了user_roles之类的表也要一并建好。脚本执行成功后再查询一下表清单确保一张不少。3.3 获取并部署数据源插件jar这一步是接入PostgreSQL的关键。理论上你可以自己实现Nacos的DataSourcePlugin接口然后打包成jar放进插件目录。但绝大多数公司不需要重复造轮子社区里已经有编译好的PostgreSQL数据源插件。我的做法是在GitHub上搜索Nacos PostgreSQL DataSource Plugin筛选标准有三个第一是插件版本要和Nacos 2.3.0匹配第二是看最近是否有维护记录第三是看issue里有没有人反馈严重的生产问题。下载对应的jar包之后加上PostgreSQL JDBC驱动jar一起放到Nacos发行包的plugins目录下。不同发行版对插件目录的约定可能略有差异我在2.3.0的tar包解压后是在conf同级目录下有plugins目录自己再创建一个postgresql子目录放jarNacos启动时能扫到。如果你选择自己编译插件思路也不复杂新建一个Maven工程依赖Nacos的数据源插件API实现接口里创建DataSource的方法内部可以基于HikariCP返回一个连接池然后在META-INF/services里声明实现类最后把jar和驱动一起部署。整个过程不超过200行代码但对Nacos内部的数据源接口版本要求比较高接口签名和Nacos 2.3.0不完全对应的话启动时会出现类加载异常。3.4 修改application.properties并启动Nacos 2.3.0的conf/application.properties里数据库相关配置默认长这样spring.datasource.platformmysql db.num1 db.url.0jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncodingutf8connectTimeout1000socketTimeout3000autoReconnecttrueuseUnicodetrueuseSSLfalseserverTimezoneAsia/Shanghai db.user.0nacos db.password.0nacos接入PostgreSQL时改成spring.datasource.platformpostgresql db.num1 db.url.0jdbc:postgresql://127.0.0.1:5432/nacos_config?stringtypeunspecified db.user.0nacos db.password.0你的密码 db.pool.config.connectionTimeout30000 db.pool.config.maximumPoolSize20注意stringtypeunspecified这个参数是我在配置发布遇到空字符串报错时加上的后面踩坑部分会细说。改完之后单机模式直接执行startup.sh -m standalone启动。观察日志如果出现Nacos启动成功的标志并且没有数据源相关的异常基本就接上了。4. 验证链路配置发布、动态刷新、数据落库4.1 控制台操作与落库检查接入不能只看启动成功还要验证数据真的写进了PostgreSQL。我习惯按这个链路来先在Nacos控制台创建一个命名空间比如叫test-ns然后在里面新建一个配置。接着用DBeaver或者命令行连到PG的nacos_config库查一下tenant_info表里有没有多出一条命名空间记录再查config_info表里有没有刚新建的配置。如果控制台操作成功但表里查不到数据十有八九是连接串指向的库不对或者Nacos实际用的是另一个数据源。这时候先看启动日志里的数据源初始化信息确认jdbc:postgresql://地址正确再看配置文件的db.num和db.url.0有没有被环境变量覆盖。Nacos配置优先级有点绕如果服务器上设了NACOS_DATASOURCE_PLATFORM或者DB_URL这类环境变量可能你改的application.properties根本没生效。4.2 客户端动态刷新验证配置中心还有一个核心能力是动态刷新也正是很多团队关心的nacos热更新。我的验证方法是准备一个Spring Boot应用引入nacos-config-spring-boot-starter用NacosConfigListener监听一个配置项然后去控制台修改这个配置并发布观察客户端是否在几秒内收到变更回调并打印出新值。这一步在PG存储下和MySQL存储下没有任何区别因为Nacos的数据源插件已经屏蔽了底层差异。如果这一步失败优先怀疑的不是PG接入问题而是客户端版本和服务端版本不匹配或者监听器注解的数据Id不对。要注意的是动态刷新的中间状态会写到config_history_info表可以顺手查一下历史记录表确认每次发布都有对应记录。4.3 集群模式下的额外验证如果你部署的是Nacos集群还要额外关注节点间数据同步是否正常。一个简单的测试是在节点A的控制台上创建一份配置然后过几秒去节点B的控制台看同一份配置是否存在。Nacos的分布式一致性协议会处理数据同步但数据源插件异常时可能出现部分节点写失败的情况。集群环境建议每个节点都接入同一个PostgreSQL数据库然后通过nacos的集群管理页面确认所有节点的健康状态。集群环境下连接数也要算一下。Nacos每个节点都会维护自己的数据源连接池如果三节点集群每个池默认20个连接那最多会占用PG的60个连接。PG默认max_connections是100看似够用但如果这台PG上还跑了其他业务连接数很容易被打满。我后面专门调整了连接池参数避免互相影响。5. 我踩过的坑驱动冲突、连接串、大小写与连接数5.1 postgresql驱动被mysql驱动干扰第一次部署PG插件后启动日志里报了一个挺隐蔽的错误大意是找不到数据库驱动或者驱动类无法加载。排查之后发现是插件目录里同时存在MySQL驱动和PostgreSQL驱动而Nacos插件类加载器扫描时把两个驱动都加载进来了导致DriverManager.getDriver在处理jdbc:postgresql://协议时判断异常。解决方式是把没有必要的MySQL驱动从插件目录移走只保留PostgreSQL相关jar。如果你的Nacos发行版里plugins目录下本来就有MySQL驱动并且你不打算再用MySQL作为数据源那直接清掉也没问题。这个坑最烦人的地方在于它不是必现和插件类加载顺序有关有时候换一台机器启动就正常了建议从一开始就把插件目录整理干净。5.2 stringtypeunspecified解决空串问题启动和基础配置都没问题但我在控制台发布一条新配置时Nacos日志报了一个关于column app_name is of type text but expression is of type character varying或者类似类型不匹配的错误。这个和PostgreSQL对空字符串、null值的严格类型推导有关。解决方案就是在db.url.0后加上stringtypeunspecified。这个参数的作用是让PG驱动把字符串类型交给数据库自己推断而不是在客户端强行绑定成varchar。加上之后之前那个配置发布报错再也没有出现过。这个问题不算高频但如果你的Nacos版本内部SQL对参数类型做了严格绑定就会踩到。5.3 表名大小写与schema定位问题PostgreSQL对表名大小写的处理是不带引号的标识符会被转成小写。Nacos的表名本来全是小写看起来没问题但如果你在初始化脚本时用了带引号的大写表名比如CREATE TABLE Config_Info那后续Nacos查询config_info就会报relation config_info does not exist。另外如果你的PG库不是用默认的publicschema而是自己建了业务schema那连接串里必须显式指定currentSchema你的schema名。Nacos的SQL查询语句一般不会带schema前缀所以只能靠连接串来定位别忘了加参数。5.4 连接池参数的运维心得Nacos接入PG后连接池调参会直接影响到PG实例的总体连接数。我把db.pool.config.maximumPoolSize从默认20调到了10因为配置中心这种场景并发写量很小连接数根本用不满。集群三节点的话总量就是30个连接给PG留出余量。还要注意connectionTimeout不要设置太短Nacos启动时需要初始化数据源如果PG响应慢一点而你只给了3秒超时启动就会失败。生产环境我一般设置成10到30秒。运维层面建议给PG里的nacos账号单独统计连接数可以通过pg_stat_activity查看。如果发现空闲连接一直不释放不是Nacos的问题就是HikariCP在保活不用太紧张。6. 扩展到其他数据库插件思路与边界6.1 自定义数据源插件其实没那么神秘很多人一听为Nacos写数据库插件就觉得门槛高其实想通了之后就是一个适配器。Nacos核心需要数据库做的事情无非是执行一套固定的CRUD SQL、分页查询、事务提交。你的插件只要实现数据源创建接口让Nacos拿到一个能用的DataSource对象然后保证方言适配即可。如果你所在的公司用的是国产数据库比如达梦、人大金仓、OceanBase这些只要它们的驱动兼容PostgreSQL或MySQL协议接入难度可以大幅降低。比如达梦本身有兼容PG/MySQL模式的配置驱动协议和SQL方言都做了适配那你甚至可以复用现有插件再改改连接串。我见过一个项目用达梦切PG场景核心工作就是把业务SQL里的方言差异梳理一遍Nacos这类中间件反而简单。6.2 其他数据库接入的注意点不是所有数据库都能像PostgreSQL那样平滑接入。MySQL以外的数据库主要看三点第一驱动是否符合JDBC规范如果驱动本身不完善Nacos启动时拿连接都会失败第二SQL方言兼容性分页语法、自增主键、日期函数这些是否和Nacos预期一致第三事务隔离级别和连接池兼容性Nacos底层用的是HikariCP如果目标数据库驱动和HikariCP配合不好会有连接泄漏风险。所以我的建议是随便玩玩可以直接改配置生产环境一定要先做功能清单验证。至少覆盖这几项登录认证、命名空间增删改查、配置发布和查询、配置删除、历史配置查看、用户权限管理。这些功能都走通了才可以考虑替换存储。6.3 一个稳妥的迁移与回滚方案最后聊聊回滚。有人会觉得我把MySQL里的配置手工搬到PG里再切换不就行了实际上Nacos有更平滑的方式先搭建一套新的Nacos集群存储指向PG然后通过Nacos的配置导出导入功能把旧集群里所有配置、命名空间一次性导入到新集群。等新集群验证通过后再把应用客户端的注册中心地址从旧集群切到新集群。这个方案的好处是旧集群一直在运行随时可以回滚。客户端切过去之后如果发现问题改回旧地址就行Nacos的配置刷新会有短暂延迟但不会丢数据。我自己操作下来的感受是数据库接入本身只占30%精力剩下70%都花在了方案设计、验证和回滚准备上。只要把这条链路想清楚nacos接入pgsql或其他数据库这件事就没有想象中那么困难。
返回列表