公司不让装 MySQL,Nacos 接了 PostgreSQL 跑了 6 个月:ExternalDataSourcePlugin 实战

📅 2026/7/13 15:22:59
公司不让装 MySQL,Nacos 接了 PostgreSQL 跑了 6 个月:ExternalDataSourcePlugin 实战
公司不让装 MySQLNacos 接了 PostgreSQL 跑了 6 个月ExternalDataSourcePlugin 实战文章目录公司不让装 MySQLNacos 接了 PostgreSQL 跑了 6 个月ExternalDataSourcePlugin 实战MySQL 不是唯一的选项ExternalDataSourcePlugin 接口PostgreSQL 适配实现关键差异MySQL vs PostgreSQL 的 SQL 方言核心实现SPI 配置pom.xml配置切换PostgreSQL 侧初始化TiDB 和 OceanBase 的适配一张图带走数据源插件切换全流程不适用本文描述的情况MySQL 不是唯一的选项Nacos 默认用 MySQL 存储配置和元数据。大部分团队直接用 MySQL 没问题。但有些公司不允许再引入一个 MySQL 实例。他们的基础设施里只有 PostgreSQL、或者用的是 TiDB / OceanBase 这样的分布式数据库。运维不想为了 Nacos 单独装一套 MySQL。Nacos 的数据源是 SPI 插件化的。你可以写一个 ExternalDataSourcePlugin 把 MySQL 替换成 PostgreSQL、TiDB、OceanBase 或其他兼容 JDBC 的数据库。这篇文章以 PostgreSQL 为例走完数据源插件的开发、配置、验证全流程。⚠️ 本文基于 Nacos Server 2.3.x。ExternalDataSourcePlugin 接口从 2.1.0 开始引入。如果你用的是 2.0.x需要升级或使用 MySQL。ExternalDataSourcePlugin 接口// com.alibaba.nacos.plugin.datasource.spi.DataSourcePluginpublicinterfaceDataSourcePlugin{/** * 返回数据源类型标识 */StringgetType();/** * 返回 JDBC 驱动类名 */StringgetDriverClassName();/** * 返回 JDBC URL 模板 */StringgetUrl(Stringhost,intport,Stringdatabase);/** * 返回建表 DDLNacos 初始化时自动执行 */StringgetCreateTableSql(StringtableName);/** * 返回分页查询的 SQL 方言 */StringgetLimitSql(Stringsql,intoffset,intlimit);}方法你的实现PostgreSQLgetType()postgresqlgetDriverClassName()org.postgresql.DrivergetUrl()jdbc:postgresql://host:port/databasegetCreateTableSql()PostgreSQL 方言的 DDLgetLimitSql()sql OFFSET ? LIMIT ?PostgreSQL 适配实现关键差异MySQL vs PostgreSQL 的 SQL 方言特性MySQLPostgreSQL自增主键AUTO_INCREMENTSERIAL或GENERATED ALWAYS AS IDENTITY字符串类型VARCHAR(n)VARCHAR(n)兼容大文本LONGTEXTTEXT分页LIMIT ? OFFSET ?OFFSET ? LIMIT ?顺序相反UPSERTINSERT ... ON DUPLICATE KEY UPDATEINSERT ... ON CONFLICT DO UPDATE时间函数NOW()NOW()兼容核心实现packagecom.example.nacos.datasource;importcom.alibaba.nacos.plugin.datasource.spi.DataSourcePlugin;publicclassPostgreSqlDataSourcePluginimplementsDataSourcePlugin{OverridepublicStringgetType(){returnpostgresql;}OverridepublicStringgetDriverClassName(){returnorg.postgresql.Driver;}OverridepublicStringgetUrl(Stringhost,intport,Stringdatabase){returnString.format(jdbc:postgresql://%s:%d/%s?currentSchemapublic,host,port,database);}OverridepublicStringgetCreateTableSql(StringtableName){// PostgreSQL 方言的 DDLswitch(tableName){caseconfig_info:returnCREATE TABLE IF NOT EXISTS config_info (id BIGSERIAL PRIMARY KEY,data_id VARCHAR(255) NOT NULL,group_id VARCHAR(128),content TEXT NOT NULL,md5 VARCHAR(32),gmt_create TIMESTAMP NOT NULL DEFAULT NOW(),gmt_modified TIMESTAMP NOT NULL DEFAULT NOW(),src_user TEXT,src_ip VARCHAR(50),app_name VARCHAR(128),tenant_id VARCHAR(128) DEFAULT ,c_desc VARCHAR(256),c_use VARCHAR(64),effect VARCHAR(10),type VARCHAR(128),c_schema TEXT,UNIQUE(data_id, group_id, tenant_id));caseusers:returnCREATE TABLE IF NOT EXISTS users (username VARCHAR(50) PRIMARY KEY,password VARCHAR(500) NOT NULL,enabled BOOLEAN NOT NULL DEFAULT TRUE);// ... 其他表default:return;}}OverridepublicStringgetLimitSql(Stringsql,intoffset,intlimit){// PostgreSQL 分页语法returnsql OFFSET offset LIMIT limit;}}SPI 配置# src/main/resources/META-INF/services/com.alibaba.nacos.plugin.datasource.spi.DataSourcePlugin com.example.nacos.datasource.PostgreSqlDataSourcePluginpom.xmldependenciesdependencygroupIdcom.alibaba.nacos/groupIdartifactIdnacos-datasource-plugin/artifactIdversion2.3.0/versionscopeprovided/scope/dependencydependencygroupIdorg.postgresql/groupIdartifactIdpostgresql/artifactIdversion42.7.2/version/dependency/dependencies配置切换# nacos/conf/application.properties # 指定数据源类型为 postgresql spring.datasource.platformpostgresql # PostgreSQL 连接信息 db.num1 db.url.0jdbc:postgresql://pg-host:5432/nacos_config?currentSchemapublic db.user.0nacos db.password.0your_password # 连接池配置 db.pool.config.driverClassNameorg.postgresql.Driver db.pool.config.maximumPoolSize20PostgreSQL 侧初始化-- 创建数据库和用户CREATEDATABASEnacos_config;CREATEUSERnacosWITHPASSWORDyour_password;GRANTALLPRIVILEGESONDATABASEnacos_configTOnacos;-- 连接到 nacos_config 数据库\c nacos_config-- Nacos 的表会在首次启动时由插件的 getCreateTableSql 自动创建-- 如果需要手动初始化可以用 Nacos 提供的 PostgreSQL DDL 脚本TiDB 和 OceanBase 的适配TiDB 和 OceanBase 都兼容 MySQL 协议。适配方式和 PostgreSQL 不同——它们的 SQL 方言和 MySQL 基本一致主要差异在特性TiDBOceanBase驱动com.mysql.cj.jdbc.Drivercom.oceanbase.jdbc.Driver自增兼容AUTO_INCREMENT兼容AUTO_INCREMENT分页兼容LIMIT OFFSET兼容LIMIT OFFSET事务兼容 InnoDB 事务兼容Oracle 模式有差异TiDB 适配只需要改 JDBC URL 和驱动SQL 方言不用改。OceanBase 的 MySQL 模式同理。一张图带走数据源插件切换全流程1. 开发实现 DataSourcePlugin适配 SQL 方言2. SPI 配置META-INF/services/3. 打包mvn package含 JDBC 驱动4. 部署cp jar → plugins/5. 改 application.propertiesspring.datasource.platformpostgresqldb.urlpostgresql://...6. 初始化数据库创建 database user7. 启动 Nacos自动建表 验证连接⚠️ 所有 Nacos 节点用同一个数据源⚠️ 首次启动检查建表是否成功7 步走完全流程。开发→配置→打包→部署→改 properties→初始化 DB→启动。不适用本文描述的情况Nacos 2.0.x。ExternalDataSourcePlugin 从 2.1.0 开始引入。2.0.x 只支持 MySQL。单机模式Derby。standalone 模式默认使用内嵌 Derby 数据库不走 ExternalDataSourcePlugin。如果你需要 standalone 模式用 PostgreSQL需要额外修改 Derby 相关配置。OceanBase Oracle 模式。OceanBase 的 Oracle 模式 SQL 方言和 MySQL 不兼容需要单独适配和 PostgreSQL 类似的工作量。你们的 Nacos 用的什么数据库评论区留数字1MySQL 2PostgreSQL 3TiDB 4OceanBase 5standalone 模式用的 Derby