零、原理
图中的流程是大家所熟悉的,不同的是在Nacos 中,服务注册时在服务端本地会通过轮询注册中心集群节点地址进行服务注册。
在注册中心上,即Nacos Server上采用了Map
保存实例信息,当然配置了持久化的服务会被保存到数据库中,在服务的调用方,为了保证本地服务实例列表的动态感知,Nacos与其他注册中心不同的是,采用了 Pull/Push同时运作的方式。
一、前言
本文将介绍如何使用Nacos做微服务的注册中心和配置中心。
需要提前安装好Nacos,如果还没有下载,请转至Nacos百度云下载地址及安装启动教程
二、用Nacos做注册中心
1.启动Nacos
2.创建多模块Maven项目,并创建两个Module,分别是服务提供者provider和服务消费者consumer
其中,父pom应负责版本依赖管理,完整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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.sca</groupId>
<artifactId>sca_study</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>sca_provider</module>
<module>sca_consumer</module>
<module>sca_config</module>
</modules>
<!-- 统一管理jar包版本 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<!-- 子模块继承之后,提供作用:锁定版本+子modlue不用写groupId和version -->
<dependencyManagement>
<dependencies>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud alibaba 2.1.0.RELEASE-->
<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>
</project>
3.服务提供者配置__8081端口
Application如下
@SpringBootApplication
@EnableDiscoveryClient
public class NacosProviderDemoApplication {
public static void main(String[] args) {
SpringApplication.run(NacosProviderDemoApplication.class, args);
}
@RestController
public class EchoController {
@GetMapping(value = "/echo/{string}")
public String echo(@PathVariable String string) {
return "Hello Nacos Discovery " + string;
}
}
}
服务提供者pom如下,需要引入spring cloud alibaba的依赖和springboot的依赖
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>sca_study</artifactId>
<groupId>org.sca</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sca_provider</artifactId>
<dependencies>
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
同时应指定nacos注册中心的地址为本地的8848端口
server.port=8081
spring.application.name=nacos-provider
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
management.endpoints.web.exposure.include=*
4.服务消费者配置__8082端口
@SpringBootApplication
@EnableDiscoveryClient
public class NacosConsumerApp {
@RestController
public class NacosController{
@Autowired
private LoadBalancerClient loadBalancerClient;
@Autowired
private RestTemplate restTemplate;
@Value("${spring.application.name}")
private String appName;
@GetMapping("/echo/app-name")
public String echoAppName(){
// 获取提供服务者实例
ServiceInstance serviceInstance = loadBalancerClient.choose("nacos-provider");
// 构造提供服务者路径
String path = String.format("http://%s:%s/echo/%s",serviceInstance.getHost(),serviceInstance.getPort(),appName);
// 打印要访问的服务者路径
System.out.println("request path:" +path);
// 通过RestTemplate访问并返回结果
return restTemplate.getForObject(path,String.class);
}
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(NacosConsumerApp.class,args);
}
}
这里需要注意的是@EnableDiscoveryClient
可以开启服务发现。
并且我们可以直接注入LoadBalancerClient
来实现负载均衡,这是因为,nacos-discovery
内部集成了ribbon依赖,ribbon可以实现负载均衡。
同时,服务消费者也需要引入服务注册的依赖以及springboot依赖,完整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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>sca_study</artifactId>
<groupId>org.sca</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sca_consumer</artifactId>
<dependencies>
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
同样我们需要在application.properties
指定注册中心的地址
server.port=8082
spring.application.name=nacos-consumer
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
management.endpoints.web.exposure.include=*
接下来,我们依次启动Nacos->服务提供者->服务消费者
说明一下为什么是这个结果,这里我们访问的是8082端口,即服务消费者的接口,服务消费者的controller逻辑是:
首先,获取提供服务者实例,根据这个实例拼接服务提供者路径
其次,使用RestTemplate带着消费者的名字去请求服务者controller。 而服务提供者则将请求附带的字符串拼接到Hello Nacos Discovery 后面。
三、用Nacos做配置中心
所谓配置中心的作用在于,我们可以在nacos dashboard上发布配置文件,当客户端与配置中心相绑定时,客户端会去nacos上拿最新的配置文件,达到动态配置的目的。
Nacos的动态配置
新建客户端Module__8083端口 用于测试动态配置更新
pom.xml内容
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>sca_study</artifactId>
<groupId>org.sca</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sca_config</artifactId>
<dependencies>
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--spring boot web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
Controller如下,需要特别注意的是我们需要@RefreshScope
注解来支持Nacos的动态刷新功能。Controller的目的在于打印出来根据nacos配置中心拿到的配置信息。
application.properties
spring.profiles.active=dev
bootstrap.properties,主要内容为:
指定服务注册和配置中心地址,都是我们本地的nacos 8848,并且指定app名字为nacos-config
,并通过spring.cloud.nacos.config.file-extension=properties
指定我们以后要动态配置的配置文件类型不是yaml而是properties
spring.application.name=nacos-config
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.file-extension=properties
server.port=8083
# nacos-config-dev.properties
@RestController
@RefreshScope //支持Nacos的动态刷新功能。
public class ConfigClientController
{
@Value("${config.info}")
private String configInfo;
@GetMapping("/config/info")
public String getConfigInfo() {
return configInfo;
}
}
/**
* @author 阳光大男孩!!!
*/
@EnableDiscoveryClient
@SpringBootApplication
public class NacosConfigApplication {
public static void main(String[] args) {
SpringApplication.run(NacosConfigApplication.class, args);
}
}
我们在Nacos上发布的配置文件应严格遵循以下格式,也就是下面的data-ID
# ${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
说人话就是 app名字-环境选项(这里我们已经指定是dev).配置文件的格式
并且我们指定配置内容,发布后,配置将被保存到nacos
这时我们再启动config Module,获取到的配置就是刚才在nacos上配置的
上面我们是使用dev环境做的测试,nacos还提供分类配置,从上到下有三个层级关系,分别是NameSpace、Group、DataID
,默认命名空间NameSpace为Public
,默认Group为DEFAULT_GROUP
我们也可以将application.properties
配置文件中的环境设置为测试环境,也就是test
同时我们在nacos上发布一个test环境的配置文件
内容标记为
再次进行测试
可以看到根据环境的变化,会拿到不同的配置文件。
参考
Nacos官方文档示例代码
B站尚硅谷,Pom配置