很多业务场景,业务功能必须用pg数据库,这时候注册中心如果用mysql的话,显得浪费资源,基于此,nacos源码修改持久化到postgreSQL数据库是一个必然需求,此处我们修改为只支持pg数据库,2.4版本的源码。
源码拉取和编译参考:前置内容
1、修改配置文件
修改console和nacos-distribution模块中的application.properties配置文件,内容如下:
spring.sql.init.platform=postgresql
db.num=1
db.url.0=jdbc:postgresql://14.xx.78.188:5432/nacos
db.user.0=postgres
db.password.0=123456
2、修改pom文件
#nacos-all中添加依赖
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.18</version>
</dependency>
#naming模块中添加依赖:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
#config模块中添加依赖:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
3、修改驱动加载相关类
ExternalDataSourceProperties.java 中的方法修改为:
private static final String JDBC_DRIVER_NAME = "org.postgresql.Driver";
List<HikariDataSource> build(Environment environment, Callback<HikariDataSource> callback) {
List<HikariDataSource> dataSources = new ArrayList<>();
Binder.get(environment).bind("db", Bindable.ofInstance(this));
Preconditions.checkArgument(Objects.nonNull(num), "db.num is null");
Preconditions.checkArgument(CollectionUtils.isNotEmpty(user), "db.user or db.user.[index] is null");
Preconditions.checkArgument(CollectionUtils.isNotEmpty(password), "db.password or db.password.[index] is null");
for (int index = 0; index < num; index++) {
int currentSize = index + 1;
Preconditions.checkArgument(url.size() >= currentSize, "db.url.%s is null", index);
DataSourcePoolProperties poolProperties = DataSourcePoolProperties.build(environment);
//修改如下
if (StringUtils.isEmpty(poolProperties.getDataSource().getDriverClassName())) {
String driverClassName = JDBC_DRIVER_NAME;
if ("postgresql".equals(EnvUtil.getProperty("spring.datasource.platform"))) {
driverClassName = "org.postgresql.Driver";
poolProperties.setDriverClassName(driverClassName);
}
}
poolProperties.setJdbcUrl(url.get(index).trim());
poolProperties.setUsername(getOrDefault(user, index, user.get(0)).trim());
poolProperties.setPassword(getOrDefault(password, index, password.get(0)).trim());
HikariDataSource ds = poolProperties.getDataSource();
if (StringUtils.isEmpty(ds.getConnectionTestQuery())) {
ds.setConnectionTestQuery(TEST_QUERY);
}
dataSources.add(ds);
callback.accept(ds);
}
Preconditions.checkArgument(CollectionUtils.isNotEmpty(dataSources), "no datasource available");
return dataSources;
}
ExternalDataSourceServiceImpl.java 和
LocalDataSourceServiceImpl.java 类中修改:
private String dataSourceType = "postgresql";
4、配置中心数据加载配置
MapperManager.java 类中方法的修改
public <R extends Mapper> R findMapper(String dataSource, String tableName) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("[MapperManager] findMapper dataSource: {}, tableName: {}", dataSource, tableName);
}
if (StringUtils.isBlank(dataSource) || StringUtils.isBlank(tableName)) {
throw new NacosRuntimeException(FIND_DATASOURCE_ERROR_CODE, "dataSource or tableName is null");
}
Map<String, Mapper> mysql = MAPPER_SPI_MAP.get("mysql");
MAPPER_SPI_MAP.put("postgresql", mysql);//添加pg数据库注册中心的表结构
Map<String, Mapper> tableMapper = MAPPER_SPI_MAP.get(dataSource);
if (Objects.isNull(tableMapper)) {
throw new NacosRuntimeException(FIND_DATASOURCE_ERROR_CODE,
"[MapperManager] Failed to find the datasource,dataSource:" + dataSource);
}
Mapper mapper = tableMapper.get(tableName);
if (Objects.isNull(mapper)) {
throw new NacosRuntimeException(FIND_TABLE_ERROR_CODE,
"[MapperManager] Failed to find the table ,tableName:" + tableName);
}
if (dataSourceLogEnable) {
return MapperProxy.createSingleProxy(mapper);
}
return (R) mapper;
}
5、所有limit ?,? 替换为 offset ? limit ? 以支持pg
WhereBuilder.java中修改:
public WhereBuilder limit(int startRow, int pageSize) {
where.append(" OFFSET ")
.append(startRow)
.append(" LIMIT ")//注意要有空格
.append(pageSize);
return this;
}
另外,修改mysql目录下的文件:
举例:ConfigInfoMapperByMySql.java
@Override
public MapperResult findConfigInfoByAppFetchRows(MapperContext context) {
final String appName = (String) context.getWhereParameter(FieldConstant.APP_NAME);
final String tenantId = (String) context.getWhereParameter(FieldConstant.TENANT_ID);
String sql = "SELECT id,data_id,group_id,tenant_id,app_name,content FROM config_info"
+ " WHERE tenant_id LIKE ? AND app_name= ?" + " OFFSET " + context.getStartRow() + " LIMIT "
+ context.getPageSize();
return new MapperResult(sql, CollectionUtils.list(tenantId, appName));
}
其他类依次修改完成即可。
注意: LIMIT 左右要有空格!
6、nacos 表结构导入pg
方案一:通过navicat 15以上版本,工具--数据传输,把mysql数据库中nacos的表结构和数据导入到pg库中:
成功之后,再pg库添加主键序列,比如:
CREATE SEQUENCE config_info_id_seq START WITH 1;
ALTER TABLE config_info ALTER COLUMN id SET DEFAULT nextval('config_info_id_seq');
CREATE SEQUENCE config_info_aggr_id_seq START WITH 18;
ALTER TABLE config_info_aggr ALTER COLUMN id SET DEFAULT nextval('config_info_aggr_id_seq');
CREATE SEQUENCE config_info_tag_id_seq START WITH 18;
ALTER TABLE config_info_tag ALTER COLUMN id SET DEFAULT nextval('config_info_tag_id_seq');
CREATE SEQUENCE config_tags_relation_id_seq START WITH 18;
ALTER TABLE config_tags_relation ALTER COLUMN id SET DEFAULT nextval('config_tags_relation_id_seq');
CREATE SEQUENCE group_capacity_id_seq START WITH 18;
ALTER TABLE group_capacity ALTER COLUMN id SET DEFAULT nextval('group_capacity_id_seq');
CREATE SEQUENCE his_config_info_nid_seq START WITH 1;
ALTER TABLE his_config_info ALTER COLUMN id SET DEFAULT nextval('his_config_info_nid_seq');
CREATE SEQUENCE permissions_id_seq START WITH 18;
ALTER TABLE permissions ALTER COLUMN id SET DEFAULT nextval('permissions_id_seq');
CREATE SEQUENCE roles_id_seq START WITH 18;
ALTER TABLE roles ALTER COLUMN id SET DEFAULT nextval('roles_id_seq');
CREATE SEQUENCE tenant_capacity_id_seq START WITH 18;
ALTER TABLE tenant_capacity ALTER COLUMN id SET DEFAULT nextval('tenant_capacity_id_seq');
CREATE SEQUENCE tenant_info_id_seq START WITH 18;
ALTER TABLE tenant_info ALTER COLUMN id SET DEFAULT nextval('tenant_info_id_seq');
数据不全,可以自行补充序列。
7、修改后的源码编译打包
mvn -Prelease-nacos clean install -U -DskipTests
打包成功
8、应用程序启动nacos
nacos-distribution 目录下找到 nacos-server-2.4.2.zip 文件
此包解压缩在win或者Linux环境 就可以启动了,比如在win环境启动:在bin目录下创建执行脚本
yd-startup.bat
startup.cmd -m standalone
其实执行命令也行。 此时访问 http://localhost:8848/nacos/ 没有进入登录页面,即没有鉴权,不安全,如果需要鉴权关闭服务,修改配置。
9、开启鉴权配置
修改console和nacos-distribution模块中的application.properties配置文件
### If turn on auth system: 修改
nacos.core.auth.enabled=true
### Turn on/off caching of auth information. By turning on this switch, the update of auth information would have a 15 seconds delay.
nacos.core.auth.caching.enabled=true
### Since 1.4.1, Turn on/off white auth for user-agent: nacos-server, only for upgrade from old version. 修改
nacos.core.auth.enable.userAgentAuthWhite=true
### Since 1.4.1, worked when nacos.core.auth.enabled=true and nacos.core.auth.enable.userAgentAuthWhite=false.
### The two properties is the white list for auth and used by identity the request from other server.修改
nacos.core.auth.server.identity.key=nacos
nacos.core.auth.server.identity.value=nacos
### worked when nacos.core.auth.system.type=nacos
### The token expiration in seconds:
nacos.core.auth.plugin.nacos.token.cache.enable=false
nacos.core.auth.plugin.nacos.token.expire.seconds=18000
### The default token (Base64 string):放开
nacos.core.auth.plugin.nacos.token.secret.key=SecretKey012345678901234567890123678901234567890123456789
#nacos.core.auth.plugin.nacos.token.secret.key=
然后再启动后就进入登录页面。
10、用户表结构修改
创建用户时失败:
原因是:代码里标识参数是bool类型,而数据库表结构里是int2类型,说明是数据表结构传输过程出错了,
修改方案sql:
ALTER TABLE users
ALTER COLUMN enabled
TYPE BOOLEAN
USING CASE
WHEN enabled = 1 THEN TRUE
ELSE FALSE
END;
到此,nacos源码修改持久化到postgreSQL数据库分享完成,当然持久到pg还有其他方案,后期可以分享nacos同时支持多种数据库,敬请期待!