Nacos学习(六):Nacos配置中心服务端设置与客户端的调用

时间:2024-03-16 11:00:31

本文记录Nacos做为配置中心,服务器端的设置与客户端几种的访问方式。
实验用的环境如下:
Nacos Server集群:
192.168.20.30:8848
192.168.20.31:8848
192.168.20.32:8848

Nacos地址服务器:
192.168.20.33:8080

客户端:
192.168.20.100

为演示方便,我们假设Nacos Client上将使用如下的配置项
user-dev.properties:
user.type=user.dev
user.name=user_dev
user.birthday=2011-12-12
user.age=10

user-test.properties:
user.type=user.test
user.name=user_test
user.birthday=2011-12-13
user.age=11

manager-dev.properties:
manager.type=manager.dev
user.name=manager_dev
user.birthday=2011-12-14
user.age=12

manager-test.properties:
manager.type=manager.test
user.name=manager_test
user.birthday=2011-12-15
user.age=13

一、在Nacos Service上创建配置
1、创建namespace
namespace按"用户id:groupid:版本"设置为:"01:com.hhao.erp:01",如图:

Nacos学习(六):Nacos配置中心服务端设置与客户端的调用
2、分别创建以下Data Id:

DataId:user-dev.properties
Group:erp-user
配置内容:
user.type=user.dev
user.name=user_dev
user.birthday=2011-12-12
user.age=10

DataId:user-test.properties
Group:erp-user
配置内容:
user.type=user.test
user.name=user_test
user.birthday=2011-12-13
user.age=11

DataId:manager-dev.properties
Group:erp-manager
配置内容:
manager.type=manager.dev
user.name=manager_dev
user.birthday=2011-12-14
user.age=12

DataId:manager-test.properties
Group:erp-manager
配置内容:
manager.type=manager.test
user.name=manager_test
user.birthday=2011-12-15
user.age=13

Nacos学习(六):Nacos配置中心服务端设置与客户端的调用

二、创建Nacos Client
nacos client的Pom文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.hhao.nacos</groupId>
    <artifactId>nacos-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>nacos-client</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.RC1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.0.BUILD-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>

    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>
</project>
不得不说的是:在项目中,Spring Cloud用到了Hoxton.RC1版本,但是Spring官网上最新的spring-cloud-alibaba-dependencies不支持该版本;
以下是此时Spring官网上最新的spring-cloud-alibaba-dependencies版本
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.1.0.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
所以从阿里spring-cloud-alibaba下载了最新的spring-cloud-alibaba-dependencies
https://github.com/alibaba/spring-cloud-alibaba
版本如下:
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.0.BUILD-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
可以看到,还只是SNAPSHOT,实际上它也无法支持Spring Cloud Hoxton.RC1版本,所以,没有办法,下载了源码,修改了Maven依赖项,重新编绎生成2.2.0.BUILD-SNAPSHOT,让其支持到Spring Cloud Hoxton.RC1版本。所以,如果按上述POM设置运行不起来,可以降低Spring Cloud版本,但是具体除到哪个版本,没有试过。
真希望阿里的更新能够更加及时些。

三、客户端访问、监听配置中心的user.properties
客户端application.properties设置如下:
server.port=8080
#启用的配置文件
spring.profiles.active=dev
#**所有的端点的web方式请求
management.endpoints.web.exposure.include=*

客户端添加bootstrap.properties,并设置如下:
#接入点,地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址
spring.cloud.nacos.config.endpoint=192.168.20.33:8080
#配置中心的命名空间
spring.cloud.nacos.config.namespace=390a21f0-1826-4109-bfa6-c963fb170d59
#Group
spring.cloud.nacos.config.group=erp-user
#DataId前缀,默认等于spring.application.name
spring.cloud.nacos.config.prefix=user
#dataID后缀及内容文件格式,dataId的后缀,同时也是配置内容的文件格式,支持 properties,yml\yaml
spring.cloud.nacos.config.file-extension=properties
#配置内容的编码方式
spring.cloud.nacos.config.encode=UTF-8
#获取配置的超时时间,单位为ms
spring.cloud.nacos.config.timeout=3000

创建UserEndpoint类:

/**
 * @author Wan
 * @date 2019/10/31 9:59
 */
@RefreshScope
@RestController
public class UserEndpoint {
    @Value("${user.type}")
    String type;

    @Value("${user.name}")
    String name;

    @Value("${user.age}")
    Integer age;

    @Value("${user.birthday}")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    LocalDate birthday;

    @Autowired
    private NacosConfigManager nacosConfigManager;

    @GetMapping("/info")
    public String info(){
        return type + name + age + birthday + nacosConfigManager.getConfigService().getServerStatus();
    }
}

创建监听类NacosUserListener:
@Component
public class NacosUserListener implements ApplicationRunner {
    @Value("${user.type}")
    String type;

    @Value("${user.name}")
    String name;

    @Value("${user.age}")
    Integer age;

    @Value("${user.birthday}")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    LocalDate birthday;

    @Autowired
    private NacosConfigManager nacosConfigManager;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println(String.format("Initial type=%s,name=%s,age=%d,birthday=%s",type, name, age,birthday.format(DateTimeFormatter.BASIC_ISO_DATE)));

        nacosConfigManager.getConfigService().addListener(
                "user.properties", "erp-user", new Listener() {

                    /**
                     * Callback with latest config data.
                     *
                     * For example, config data in Nacos is:
                     *
                     * user.name=Nacos user.age=25
                     * @param configInfo latest config data for specific dataId in Nacos
                     * server
                     */
                    @Override
                    public void receiveConfigInfo(String configInfo) {
                        Properties properties = new Properties();
                        try {
                            properties.load(new StringReader(configInfo));
                        }
                        catch (IOException e) {
                            e.printStackTrace();
                        }
                        System.out.println("config changed: " + properties);
                    }

                    @Override
                    public Executor getExecutor() {
                        return null;
                    }
                });
    }
}

启动类NacosClientApplication:
@SpringBootApplication
public class NacosClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(NacosClientApplication.class, args);
    }
}
启动NacosClientApplication。
访问http://192.168.20.100:8080/info看输出,也可以看Console中看输出。
可以在Nacos Server端变更属性值,在客户端可以看到值的变更响应;
可以在Nacos 客户端的application.propertis中修改源活的配置文件为spring.profiles.active=test,查看加载属性的不同;

Nacos学习(六):Nacos配置中心服务端设置与客户端的调用

四、客户端同时访问user.properties和manager.properties
修改bootstrap.properties,设置如下:

#接入点,地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址
spring.cloud.nacos.config.endpoint=192.168.20.33:8080
#配置中心的命名空间
spring.cloud.nacos.config.namespace=390a21f0-1826-4109-bfa6-c963fb170d59
#user.properties加载,注意,此种方式不支持配置文件组合成data-id,须要自己处理成user-dev.properties或user-test.properties,nacos的不足
spring.cloud.nacos.config.ext-config[0].data-id=user-dev.properties
spring.cloud.nacos.config.ext-config[0].group=erp-user
spring.cloud.nacos.config.ext-config[0].refresh=true
#manager.properties加载,注意,此种方式不支持配置文件组合成data-id,须要自己处理成manager-dev.properties或manager-test.properties,nacos的不足
spring.cloud.nacos.config.ext-config[1].data-id=manager-dev.properties
spring.cloud.nacos.config.ext-config[1].group=erp-manager
spring.cloud.nacos.config.ext-config[1].refresh=true

#配置内容的编码方式
spring.cloud.nacos.config.encode=UTF-8
#获取配置的超时时间,单位为ms
spring.cloud.nacos.config.timeout=3000

修改NacosUserListener类,查看是否两个配置都加载了,以及加载后如果属性重复,则nacos的处理方法。
@Component
public class NacosUserListener implements ApplicationRunner {
    @Value("${manager.type}")
    String managerType;

    @Value("${user.type}")
    String type;

    @Value("${user.name}")
    String name;

    @Value("${user.age}")
    Integer age;

    @Value("${user.birthday}")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    LocalDate birthday;

    @Autowired
    private NacosConfigManager nacosConfigManager;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println(String.format("Initial type=%s %s,name=%s,age=%d,birthday=%s",type,managerType ,name, age,birthday.format(DateTimeFormatter.BASIC_ISO_DATE)));

        nacosConfigManager.getConfigService().addListener(
                "user.properties", "erp-user", new Listener() {

                    /**
                     * Callback with latest config data.
                     *
                     * For example, config data in Nacos is:
                     *
                     * user.name=Nacos user.age=25
                     * @param configInfo latest config data for specific dataId in Nacos
                     * server
                     */
                    @Override
                    public void receiveConfigInfo(String configInfo) {
                        Properties properties = new Properties();
                        try {
                            properties.load(new StringReader(configInfo));
                        }
                        catch (IOException e) {
                            e.printStackTrace();
                        }
                        System.out.println("config changed: " + properties);
                    }

                    @Override
                    public Executor getExecutor() {
                        return null;
                    }
                });
    }
}
运行NacosClientApplication,输出:

Nacos学习(六):Nacos配置中心服务端设置与客户端的调用
可以看到,两个项都加载,但合并后相同的属性,后面的会覆盖前面的。

五、客户端同时访问user.properties和manager.properties另一种方式
修改bootstrap.properties,设置如下:
#接入点,地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址
spring.cloud.nacos.config.endpoint=192.168.20.33:8080

spring.cloud.nacos.config.shared-data-ids=user-dev.properties,manager-dev.properties
spring.cloud.nacos.config.refreshable-dataids=user-dev.properties,manager-dev.properties

#配置内容的编码方式
spring.cloud.nacos.config.encode=UTF-8
#获取配置的超时时间,单位为ms
spring.cloud.nacos.config.timeout=3000

用shared-data-ids和refreshable-dataids配置共享的多个配置项(refreshable-dataids控制刷新),不过,这种方式只支持默认的public命名空间、DEFAULT_GROUP的Group,所以Nacos Server端要在public命名空间、DEFAULT_GROUP组下创建user-dev.properties,manager-dev.properties配置项。
这种局限还挺大的,nacos代码这部份没有完善。

终上所述,目前比较靠谱的加载方法即第二种:
spring.cloud.nacos.config.ext-config[1].data-id=manager-dev.properties
spring.cloud.nacos.config.ext-config[1].group=erp-manager
spring.cloud.nacos.config.ext-config[1].refresh=true
不过,这种也有缺限,不像第一种那样,能够自动识别配置文件。不过,一般情况下,配置环境的分隔可以话到Nacos服务器地址那去做,这里也就无所谓配置文件了。
所以,尽量不要在data id中用到配置文件的标识。