一、前言
1、因为项目需要用到nacos,之前使用的是apollo,所以看了下nacos官方文档,和网上博客内容,总感觉,不是很流畅,所以这里整理一下。至于服务中心的文章等我后面抽空补上。
2、对于配置中心,我以springboot项目参考来说,对于服务发现中心,我已 spring cloud的实现之一,cloud alibaba来展开。
二、安装
1、nacos 分为服务端和不同语言的客户端,我们需要先部署一下服务端,当然部署的方式也有很多种,这里就不再详细说了,官网文档说的很清楚了。 Nacos 快速开始
2、我这里就下载win的方式,启动命令(standalone代表着单机模式运行,非集群模式):
startup.cmd -m standalone
3、当然你也可以用镜像的方式部署,官方文档都有,很清晰明了,就不再啰嗦了 4、访问 http://localhost:8848/nacos 界面如下,默认账号密码: nacos:nacos
三、spring boot 项目使用
3.1、官方完整模板代码,配合配置中心使用
1、、这里其实官方文档上面写了很清楚,网上博客也写的很清楚,但是我觉得很多网上博客只是作为一个简单的演示,而且看到官方提供的模板代码虽然又各种情况,但是注解又是混合使用,对于第一次使用的人,体验感不是很好。我第一次看的时候,有些不舒服。
3.2、假设一种项目发布的情况来说
1、这里抽取一下,已一个项目发布的情况来说 一个实践是:
- 使用NameSpace来定义环境,比如开发环境(dev)、测试环境(test)、生产环境(prod)。
- 使用GroupId来定义不同的应用,比如支付应用Pay,商品应用Goods。
- 使用DataId来区分配置,比如线程池的配置ThreadPoolConfig,数据源的配置,Redis配置,MQ配置等。
所以就可以有多条线:
项目 | 说明 |
---|
dev环境-pay应用-数据源配置。 | 说明 | dev环境-pay应用-Redis配置。 | 说明 | test环境-pay应用-数据源配置。 | 说明 | test环境-pay应用-Redis配置。 | 说明 | prod环境-pay应用-数据源配置 | 说明 | prod环境-pay应用-Redis配置 | 说明 |
或者简化一些就是 (这里就以这个来作为说明)
项目 | 说明 |
---|
dev环境-pay应用-所有配置配置 | 说明 | test环境-pay应用-所有配置 | 说明 | prod环境-pay应用-所有配置。 | 说明 |
3.3、nacos创建配置信息
1、创建dev命名空间,当然对于我们现在说的这种情况来说,比较适合springboot这种单体的项目
但是对于这种单体的项目其中还是有一些配置是一样的,比如,一个公司一个业务组有5个springboot的单体业务项目,但是他们的定时任务都使用的XXLJob,所以,他们的xxljob的配置是一样的,后面希望这个xxljob的地址改了,其他项目可以一起改,不用挨个项目改,我们就可以创建出一个公共的部分来使用。(这个就是后话了,有时间我会补充这部分文章)
2、在dev名称空间下创建一个album的数据标识,以及组名称(组名称在我们这个案例中意义就不是很大了,所以我选择默认就好) 3、注意配置格式是properties,不同的配置我们后面在项目配置中也是不一样的。
3.4、项目使用
1、pom.xml文件内容如下,注意boot和nacos的版本,有些版本不兼容。
<?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.3.1.RELEASE</version>
<relativePath/>
</parent>
<groupId>cn.gxm</groupId>
<artifactId>spring-boot-nacos</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-nacos</name>
<description>spring-boot-nacos</description>
<properties>
<java.version>1.8</java.version>
<nacos.config.version>0.2.10</nacos.config.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>${nacos.config.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
2、项目整体结构 3、NacosDemoController 内容
package cn.gxm.springbootnacos.controller;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/nacos")
public class NacosDemoController {
@NacosValue(value = "${log.leve:nacos}", autoRefreshed = true)
private String info;
@Value(value = "${log.leve:spring}")
private String springInfo;
@GetMapping("/info")
public String projectInfo() {
return info + "-" + springInfo;
}
}
4、SpringBootNacosApplication内容
package cn.gxm.springbootnacos;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootNacosApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootNacosApplication.class, args);
}
}
5、 application.properties 内容
# 默认开启 dev的环境
spring.profiles.active=dev
6、application-dev.properties 内容
# 这里的配置其实是全局配置,后面你还可以在不同的类上,修改相关配置。
# 开启提前加载,这样可以保证从nacos拉取配置的时间早于springboot读取配置的时间
# 这样我们可以把所有的 springboot 的配置都放到nacos中(比如我把项目启动的端口也在nacos中),
# 本地指配置nacos的信息
nacos.config.bootstrap.enable=true
# nacos服务地址
nacos.config.server-addr=127.0.0.1:8848
nacos.config.remote-first=true
# 名称空间 这里的这个值就是dev名称空间的值
nacos.config.namespace=fe123197-f4a1-4283-82d4-5ebd3d4b25df
# 数据id 这里用项目名称表示
nacos.config.data-ids=album
# 默认组
nacos.config.group=DEFAULT_GROUP
# 配置读取的默认格式,之前我们创建数据的时候,选择的格式,可以多选
nacos.config.type=properties
# 自动刷新
nacos.config.auto-refresh=true
# 尝试次数
nacos.config.max-retry=10
# 尝试时间
nacos.config.config-retry-time=2333
# 拉取配置超时时间
nacos.config.config-long-poll-timeout=46000
nacos.config.enable-remote-sync-config=true
nacos.config.username=nacos
nacos.config.password=nacos
7、创建dev名称空间以及相关的数据id,以及配置文件内容
8、application-dev.properties 文件内容,其实和上面dev差不多,除了名称空间值换成了 test(当然其他配置你也可以改)
# 这里的配置其实是全局配置,后面你还可以在不同的类上,修改相关配置。
# 开启提前加载,这样可以保证从nacos拉取配置的时间早于springboot读取配置的时间
# 这样我们可以把所有的 springboot 的配置都放到nacos中(比如我把项目启动的端口也在nacos中),
# 本地指配置nacos的信息
nacos.config.bootstrap.enable=true
# nacos服务地址
nacos.config.server-addr=127.0.0.1:8848
nacos.config.remote-first=true
# 名称空间 这里的这个值就是dev名称空间的值
nacos.config.namespace=be007f40-d723-4ceb-b4e2-4e8a2d468d2f
# 数据id 这里用项目名称表示
nacos.config.data-ids=album
# 默认组
nacos.config.group=DEFAULT_GROUP
# 配置读取的默认格式,之前我们创建数据的时候,选择的格式,可以多选
nacos.config.type=properties
# 自动刷新
nacos.config.auto-refresh=true
# 尝试次数
nacos.config.max-retry=10
# 尝试时间
nacos.config.config-retry-time=2333
# 拉取配置超时时间
nacos.config.config-long-poll-timeout=46000
nacos.config.enable-remote-sync-config=true
nacos.config.username=nacos
nacos.config.password=nacos
9、在application.properties文件中切换配置,访问接口。
10、这个时候你修改对应的命名空间下的参数,再请求接口,会发现获取的是你最新修改后的值。这是因为,我们在使用的时候,使用了autoRefreshed
11、我这里的配置文件说的不全,各个配置信息可以参考 Nacos配置文件的使用和经验总结 ,以及官方提供的demo
12、注意我们在application.properties文件中的内容是全局配置,里面有很多都是默认值,你不写也是可以。
3.5、其他使用方式
3.5.1、动态发布配置
1、我们可以通过nacos提供的 ConfigService 来动态发布配置,新增一个controller,如下
package cn.gxm.springbootnacos.controller;
import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/nacos/dynamic")
public class DynamicController {
public static final String content = "dept=Aliware\ngroup=Alibaba";
public static final String DATA_ID = "test";
@NacosInjected
private ConfigService configService;
@GetMapping("/add-config")
public String addConfig() throws NacosException {
if (configService.publishConfig(DATA_ID, Constants.DEFAULT_GROUP, content)) {
System.out.println("First runner success: " + configService
.getConfig(DATA_ID, Constants.DEFAULT_GROUP, 5000));
} else {
System.out.println("First runner error: publish config error");
}
return "ok";
}
@GetMapping("/get-config")
public String getConfig() throws NacosException {
return configService
.getConfig(DATA_ID, Constants.DEFAULT_GROUP, 5000);
}
}
2、我以dev 命名空间启动,下面只有一个album 数据id
2、调用增加配置的接口add-config ,就多了一个我们在代码里面写的数据 3、调用动态获取配置的接口get-config
3.5.2、局部配置大于全局配置
1、前面我们在application.properties文件中的配置都是全局配置,我们可以在不同的类上指定dataId ,和group ,但是不能重新指定名称空间namespace ,如下,新增一个controller,其中最重要的注解 @NacosPropertySource(name = “custom”, dataId = AreaConfigController.DATA_ID)
package cn.gxm.springbootnacos.controller;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.alibaba.nacos.spring.context.annotation.config.NacosPropertySource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/nacos/area")
@NacosPropertySource(name = "custom", dataId = AreaConfigController.DATA_ID)
public class AreaConfigController {
public static final String DATA_ID = "area";
@NacosValue(value = "${type:unknown}", autoRefreshed = true)
private String type;
@GetMapping("/type")
public String type() {
return type;
}
}
2、手动添加一个area的数据id,和默认组,方便我们上面的代码测试
3、最后访问,没有问题
3.5.3、key变化监听
1、新建一个controller ,内容如下
package cn.gxm.springbootnacos.controller;
import com.alibaba.nacos.api.config.annotation.NacosConfigListener;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/nacos/watch-change")
public class WatchChangeController {
@NacosValue(value = "${change.count:1}", autoRefreshed = true)
private String count;
public String getCount() {
return count;
}
public void setCount(String count) {
this.count = count;
}
@NacosConfigListener(dataId = "watchChange", timeout = 500)
public void onChange(String newContent) throws Exception {
System.out.println("onChange : " + newContent);
}
}
2、建立watchChange 数据id,方便上述代码测试 3、你一在nacos控制台修改内容,控制台就会显示,我们设置的刷新时间为500ms
3.5.4、配置多个数据id
1、在全局配置中,多加一个数据id,xxljob
2、新建一个controller ,内容如下,注意里面的ip属性album中是没有的。
package cn.gxm.springbootnacos.controller;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/nacos/many-data")
public class ManyDataIdsController {
@NacosValue(value = "${ip:unknown}", autoRefreshed = true)
private String ip;
@GetMapping("/ip")
public String ip() {
return ip;
}
}
3、新建一个 xxljob的数据id,方便上述代码测试 4、访问,说明访问到了 xxljob数据空间下。这个xxljob的配置,可以作为一个公共的配置来使用。
3.5.5、日志输出
1、我们在配置一个dataId 或者namespace 的时候,在启动的时候,都会把相应的参数给打出来,比如链接超时之类的。
3.5.6、最后整体的项目结构
3.6、配置结语
上面其实也只是一部分的使用,但是我相信对于大部分人来说都已经够用了,如果你想了解更细的方式,我建议你官方demo和文档是一定要看的。
五、springcloud 使用,配合服务发现使用。
spring Cloud 是一套规范,其实现很多,但是大家可能最熟悉的就是 netflix 的实现,其实还有很多,而spring cloud alibaba 是最有可能替代netflix 的一套方案。
|