# nacos-plugin-ext **Repository Path**: yanweiling/nacos-plugin-ext ## Basic Information - **Project Name**: nacos-plugin-ext - **Description**: No description available - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: nacos-ywl - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-12-31 - **Last Updated**: 2025-01-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # nacos-plugin A collection of Nacos plug-ins that provide pluggable plug-in capabilities for Nacos and support user customization and high scalability ![](https://tva1.sinaimg.cn/large/008i3skNly1gxmnilyukqj30qp0fgglx.jpg) 基于官方的nacos-plugin-ext,做了如下调整 基于dev 分支, 1.将oracle相关的module删除 2. 2.3.0-SNAPSHOT 将此版本改为: 2.4.0 3.初始化postgresql的脚本指定了schema,采用脚本nacos-pg-schema.sql 4.新增类 ```java package com.alibaba.nacos.plugin.datasource.enums; import java.util.HashMap; import java.util.Map; public enum TrustedPostgreSqlFunctionEnum { /**sange * NOW(). */ NOW("NOW()", "NOW()"); private static final Map LOOKUP_MAP = new HashMap<>(); static { for (TrustedPostgreSqlFunctionEnum entry : TrustedPostgreSqlFunctionEnum.values()) { LOOKUP_MAP.put(entry.functionName, entry); } } private final String functionName; private final String function; TrustedPostgreSqlFunctionEnum(String functionName, String function) { this.functionName = functionName; this.function = function; } /** * Get the function name. * * @param functionName function name * @return function */ public static String getFunctionByName(String functionName) { TrustedPostgreSqlFunctionEnum entry = LOOKUP_MAP.get(functionName); if (entry != null) { return entry.function; } throw new IllegalArgumentException(String.format("Invalid function name: %s", functionName)); } } ``` 修改类: ```java /* * 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. */ package com.alibaba.nacos.plugin.datasource.impl.postgresql; import com.alibaba.nacos.plugin.datasource.constants.DatabaseTypeConstant; import com.alibaba.nacos.plugin.datasource.enums.TrustedPostgreSqlFunctionEnum; import com.alibaba.nacos.plugin.datasource.impl.base.BaseConfigInfoMapper; /** * The postgresql implementation of ConfigInfoMapper. * * @author Long Yu **/ public class ConfigInfoMapperByPostgresql extends BaseConfigInfoMapper { //这里是新增的 @Override public String getFunction(String functionName) { return TrustedPostgreSqlFunctionEnum.getFunctionByName(functionName); } @Override public String getDataSource() { return DatabaseTypeConstant.POSTGRESQL; } } ``` 编译打包好nacos-postgresql-datasource-plugin-ext-1.0.0-SNAPSHOT.jar 将此包上传到linux中 4.在linux中 安装V2.4.3版本的nacos docker镜像 地址:https://hub.docker.com/ >docker pull nacos/nacos-server:2.4.3 启动docker >docker run -d –name nacos -e MODE=standalone -p 8848:8848 -p 9848:9848 nacos/nacos-server:v2.4.3 >查看日志 docker logs -f nacos 启动正常以后,我们可以通过docker exec -it nacos /bin/bash 进入容器的/home/nacos中可以查看里面的目录信息 >copy 关键目录 接下来把data,logs,conf拷贝到宿主机上 cd 到mynacos目录下,执行 >docker cp nacos:/home/nacos/logs/ . docker cp nacos:/home/nacos/data/ . docker cp nacos:/home/nacos/conf/ . 这样就把nacos 的文件拷贝到本地了 4. 停止且删除容器 >docker rm -f nacos 5.重新启动nacos,并指定挂载目录 >docker run -d \ --name nacos \ -e MODE=standalone \ -p 8848:8848 \ -p 9848:9848 \ -v /xx/mynacos/logs/:/home/nacos/logs \ -v /xx/mynacos/conf/:/home/nacos/conf \ -v /xx/mynacos/data/:/home/nacos/data \ nacos/nacos-server:v2.4.3 docker run -itd --restart unless-stopped 增加这个参数可以让docker 挂了以后,自动重启 此时就要准备配置postgresql 的存储插件了 启动容器后,进入到容器中: >docker exec -it nacos /bin/bash > cd /home/nacos > mkdir plugins > exit 退出以后,在宿主机中,将宿主机中的插件拷贝到容器中 >dokcer cp /xx/mynacos/plugins/nacos-postgresql-datasource-plugin-ext-1.0.0-SNAPSHOT.jar nacos:/home/nacos/plugins 然后要修改启动的配置 > >spring.datasource.platform=postgresql db.num=1 db.url.0=jdbc:postgresql://localhost:5432/mydatabase?tcpKeepAlive=true&reWriteBatchedInserts=true&ApplicationName=nacos_java¤tSchema=nacos db.user.0=用户名 db.password.0=密码 db.pool.config.driverClassName=org.postgresql.Driver > 其中 currentSchema=nacos 是指定了schema 另外还可以打开鉴权: nacos.core.auth.plugin.nacos.token.secret.key= 需要用base64加密一串长度不少于32位的字符串 我采用的是如下方式 ```java System.out.println("d166d71a-f8f2-49a0-a42a-9941f4914e26".length());; String base64Str = Base64.getEncoder().encodeToString("d166d71a-f8f2-49a0-a42a-9941f4914e26".getBytes()); ``` 这里我是自定义了一样的值 nacos.core.auth.server.identity.key=xxx nacos.core.auth.server.identity.value=xxx nacos.core.auth.enabled=true 打开鉴权: ```shell nacos.core.auth.plugin.nacos.token.expire.seconds=${NACOS_AUTH_TOKEN_EXPIRE_SECONDS:18000} ### The default token: #nacos.core.auth.plugin.nacos.token.secret.key=${NACOS_AUTH_TOKEN:} nacos.core.auth.plugin.nacos.token.secret.key=ZDE2NmQ3MWEtZjhmMi00OWEwLWE0MmEtOTk0MWY0OTE0ZTI2 ### 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=${NACOS_AUTH_CACHE_ENABLE:false} nacos.core.auth.enable.userAgentAuthWhite=${NACOS_AUTH_USER_AGENT_AUTH_WHITE_ENABLE:false} #nacos.core.auth.server.identity.key=${NACOS_AUTH_IDENTITY_KEY:} nacos.core.auth.server.identity.key=xxx #nacos.core.auth.server.identity.value=${NACOS_AUTH_IDENTITY_VALUE:} nacos.core.auth.server.identity.value=xxx ## spring security config ### turn off security nacos.security.ignore.urls=${NACOS_SECURITY_IGNORE_URLS:/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**} # metrics for elastic search management.metrics.export.elastic.enabled=false management.metrics.export.influx.enabled=false nacos.naming.distro.taskDispatchThreadCount=10 nacos.naming.distro.taskDispatchPeriod=200 nacos.naming.distro.batchSyncKeyCount=1000 nacos.naming.distro.initDataRatio=0.9 nacos.naming.distro.syncRetryDelay=5000 nacos.naming.data.warmup=true nacos.console.ui.enabled=true nacos.core.param.check.enabled=true #新加属性 nacos.core.auth.enabled=true ``` 默认登录的账号密码对是nacos nacos https://www.volcengine.com/docs/6738/1223801 ----配置文件加密 在java客户端,引入包: 对应的springboot版本是 ```shell org.springframework.boot spring-boot-starter-parent 2.1.7.RELEASE ``` ```json com.alibaba.boot nacos-discovery-spring-boot-starter 0.2.10 com.alibaba.boot nacos-config-spring-boot-starter 0.2.10 com.alibaba.boot nacos-config-spring-boot-actuator 0.2.10 ``` 在application.yml中配置 ```yaml nacos: config: # bootstrap: # enable: true # log-enable: true server-addr: localhost:8848 auto-fresh: true remote-first: true namespace: MYSPACE-${spring.profiles.active} group: MYSPACE enabled: true # false以后,本地nacos缓存依然有效,可能就不更新nacos最新配置了 file-extension: yaml # 只是针对默认和profile 的配置,定义的后缀 username: 用户名 password: 密码 ``` ```java //自上而下加载,最好加载的会覆盖前面的配置 @SpringBootApplication @NacosPropertySources({ @NacosPropertySource(type = ConfigType.YAML, dataId = "comm.yml",groupId = "MYSPACE",autoRefreshed = true, first = true, before = SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, after = SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME), @NacosPropertySource(type = ConfigType.YAML, dataId = "application-${spring.profiles.active}.yml",groupId = "MYSPACE",autoRefreshed = true, first = true, before = SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, after = SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME), @NacosPropertySource(type = ConfigType.YAML, dataId = "application-${spring.profiles.active}-nacos.yml",groupId = "MYSPACE",autoRefreshed = true, first = true, before = SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, after = SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME) }) @EnableNacosConfig public class MyPlatformApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(MyPlatformApplication.class, args); } } ``` 这样在nacos服务控制台上,就可以配置MYSPACE-dev namespace 在此命名空间下,新建配置了 java端监听配置的变化 ```java @Component public class EnvironmentListener { @NacosConfigListener(dataId = "base.yml",groupId = "MYSPACE", type = ConfigType.YAML) public void onChange(String content) { System.out.println("receive config change event, content:" + content); } } ``` 还可以额外监听某个配置文件的,某个prefix下的值 ```java @Configuration @Data @NacosConfigurationProperties(groupId = "MYSPACE",prefix = "filenacos.hadoop",dataId = "fileSystem-${spring.profiles.active}-nacos.yml",type = ConfigType.YAML, autoRefreshed = true) public class NacosConfig { //不加注解,如果nacos没有数据,则获取不到值; // 如果@Value 所在的类上NacosConfigurationProperties,效果同NacosValue一样 // 如果单独使用@Value可以从nacos和本地获取,但是不会监测到nacos变更更新刷新数据 @Value("${filenacos.hadoop.basePath}") private String basePath; @Value("${filenacos.hadoop.clusterName}") private String clusterName; @Value("${filenacos.hadoop.clusterHostUrl}") private String clusterHostUrl; @Value("${filenacos.hadoop.authMode}") private String authMode; @Value("${filenacos.hadoop.csvFiles}") private String csvFiles; } ``` 也可以在普通配置文件中,监听配置的变化 ```java @Configuration @Data public class BussinessConfig { @NacosValue(value = "${ftp.newkey:default}",autoRefreshed = true) private String ftpNewKey; @NacosValue(value = "${mytest.newKey}",autoRefreshed = true) private String newKey; @Value("${mytest.freshkey1}") private String freshkey1; @NacosValue(value = "${mytest.freshkey2}",autoRefreshed = true) private String freshkey2; } ``` 也可以通过API的方式获取数据变化 ```java import com.alibaba.fastjson.JSONObject; import com.alibaba.nacos.api.NacosFactory; import com.alibaba.nacos.api.config.ConfigService; import com.alibaba.nacos.api.config.listener.Listener; import com.alibaba.nacos.api.exception.NacosException; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import java.io.IOException; import java.util.Properties; import java.util.concurrent.Executor; public class NacosTest { private static final String NACOS_SERVER_ADDRESS = "http://localhost:8848"; private static final String NACOS_LOGIN_API ="/nacos/v1/auth/login"; private static final String USERNAME = "nacos"; private static final String PASSWORD = "nacos"; private static final String CONFIG_FETCH_API = "/nacos/v1/cs/configs?accessToken=${TOKEN}&dataId=${DATAID}&group=${GROUP}&tenant=${NAMESPACEID}"; public static void main(String[] args) throws IOException, InterruptedException { monitor(); } private static void loginAndFetchConfig(){ String token = getToken(); String config = fetchConfigValue(token,"base.yml","MYSPACE","MYSPACE-dev"); System.out.println(config); } private static String fetchConfigValue(String token,String dataId,String group,String namespaceId){ RestTemplate restTemplate = new RestTemplate(); String url = StringUtils.replace(NACOS_SERVER_ADDRESS + CONFIG_FETCH_API,"${TOKEN}",token) .replace("${DATAID}",dataId) .replace("${GROUP}",group) .replace("${NAMESPACEID}",namespaceId); ResponseEntity response = restTemplate.getForEntity(url, String.class); if (response.getStatusCode().is2xxSuccessful()) { return response.getBody(); } return "Failed to get config from Nacos"; } private static String getToken() { RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); MultiValueMap map = new LinkedMultiValueMap<>(); map.add("username", USERNAME); map.add("password", PASSWORD); HttpEntity> requestEntity = new HttpEntity<>(map, headers); ResponseEntity response = restTemplate.postForEntity(NACOS_SERVER_ADDRESS + NACOS_LOGIN_API, requestEntity, String.class); String responseBody = response.getBody(); if(StringUtils.isNotBlank(responseBody) && responseBody.contains("accessToken")){ return JSONObject.parseObject(responseBody).getString("accessToken"); } return null; } private static void monitor(){ try { String serverAddr = "localhost:8848"; String dataId = "base.yml"; String group = "MYSPACE"; Properties properties = new Properties(); properties.put("serverAddr", serverAddr); properties.put("username","nacos"); properties.put("password","nacos"); properties.put("namespace","MYSPACE-dev"); ConfigService configService = NacosFactory.createConfigService(properties); String content = configService.getConfigAndSignListener(dataId, group, 5000, new Listener() { @Override public void receiveConfigInfo(String configInfo) { System.out.println("recieve1:" + configInfo); } @Override public Executor getExecutor() { return null; } }); System.out.println(content); } catch (NacosException e) { e.printStackTrace(); } } } ```