SpringCloud 微服务基础系列之Nacos

为什么叫Nacos?

Nacos 名字的由来(取红色的英文字符): Dynamic Naming and Configuration Service 动态命名和配置服务

Nacos 是什么?

Nacos 是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

Nacos 既可以作为注册中心也可以作为配置中心,相当于SpringCloud中 Eureka + Config 的组合,并且Eureka 注册中心已经宣布停止更新了,Nacos提供了比它们更强大的功能,并将其合二为一帮助开发者更容易构建分布式系统。

Nacos 作为注册中心在不同场景下可以切换成 CAP理论中的 CPAP 模式

SpringCloud 微服务基础系列之Nacos

Nacos 的主要功能有哪些?

  • 服务发现与服务健康检测

  • 动态配置服务

  • 动态DNS服务

  • 服务机器元数据管理

Nacos 资料地址

Nacos官网地址

SpringCloud官网Nacos介绍

Github nacos-example

安装并运行 Nacos

下载安装包

下载地址

SpringCloud 微服务基础系列之Nacos

预备环境准备

Nacos 依赖 Java 环境来运行。如果您是从代码开始构建并运行Nacos,还需要为此配置 Maven环境,请确保是在以下版本环境中安装使用:

  1. 64 bit OS,支持 Linux/Unix/Mac/Windows,推荐选用 Linux/Unix/Mac。
  2. 64 bit JDK 1.8+;下载 & 配置
  3. Maven 3.2.x+;下载 & 配置

启动服务器

Linux/Unix/Mac

启动命令(standalone代表着单机模式运行,非集群模式):

sh startup.sh -m standalone

如果您使用的是ubuntu系统,或者运行脚本报错提示[[符号找不到,可尝试如下运行:

bash startup.sh -m standalone

Windows

启动命令:

cmd startup.cmd

或者双击startup.cmd运行文件。

启动后打开Nacos服务地址 http://192.168.10.1:8848/nacos/index.html ,初始用户名和密码均是nacos。

SpringCloud 微服务基础系列之Nacos

服务注册&发现和配置管理

服务注册

curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=nacos.naming.serviceName&ip=20.18.7.10&port=8080'

SpringCloud 微服务基础系列之Nacos

服务发现

curl -X GET 'http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=nacos.naming.serviceName'

SpringCloud 微服务基础系列之Nacos

发布配置

curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=HelloWorld"

SpringCloud 微服务基础系列之Nacos

获取配置

curl -X GET "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"

SpringCloud 微服务基础系列之Nacos

关闭服务器

Linux/Unix/Mac

sh shutdown.sh

Windows

cmd shutdown.cmd

或者双击shutdown.cmd运行文件。

Nacos 管理界面介绍

下面是我们常见的nacos 界面,给大家介绍一个左侧的菜单功能

SpringCloud 微服务基础系列之Nacos

  • 配置管理:指的是配置中心的管理
    • 配置列表:展示所有的配置列表
    • 历史版本:每次修改后的例时记录
    • 监听查询
  • 服务管理
    • 服务列表
    • 订阅者列表

SpringCloud 微服务基础系列之Nacos

  • 权限控制
    • 用户列表:登录nacos界面的用户管理
    • 角色管理:用户所拥有的角色,需要绑定用户
    • 权限管理:角色拥有的权限管理,需要绑定角色,对不同命名空间中的数据拥有的权限

SpringCloud 微服务基础系列之Nacos

  • 命名空间:nacos 中根据不同命名空间区分不同服务,下面 dev 和 test 都是我自己配置的,可以编辑删除,public 是 nacos 默认保留的,不允许编辑和删除

SpringCloud 微服务基础系列之Nacos

  • 集群管理
    • 节点列表:Nacos 集群节点列表

SpringCloud 微服务基础系列之Nacos

Nacos 作为注册中心

本示例说明了如何使用 Nacos Discovery Starter 实现 SpringCloud 应用服务发现。

Nacos 是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

第一步: 创建一个普通的 SpringCloud 项目

第二步:在项目中添加 spring-cloud-starter-alibaba-nacos-discovery

完整 pom 文件如下所示:

<dependencies>
	<!-- nacos discovery -->
	<dependency>
		<groupId>com.alibaba.cloud</groupId>
		<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-actuator</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>

<dependencyManagement>
	<dependencies>
		<!--spring cloud alibaba 2.2.0.RELEASE-->
		<dependency>
			<groupId>com.alibaba.cloud</groupId>
			<artifactId>spring-cloud-alibaba-dependencies</artifactId>
			<version>2.2.0.RELEASE</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>

第三步:/src/main/resources/application.properties 文件中添加Nacos服务地址相关配置

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 # nacos地址
  application:
    name: nacos-provider-server # 服务名
    
server:
  port: 7001 # 端口号

第四步:主启动类中加入注解 @EnableDiscoveryClient 开启服务注册与发现

 @SpringBootApplication
 @EnableDiscoveryClient
 public class ProviderApplication {

 	public static void main(String[] args) {
 		SpringApplication.run(Application.class, args);
 	}

 	@RestController
 	class EchoController {
 		@GetMapping(value = "/echo/{string}")
 		public String echo(@PathVariable String string) {
 				return "Nacos server: " + string;
 		}
 	}
 }

第五步:启动Nacos服务器

第六步:启动应用

浏览器访问 http://localhost:7001/echo/HelloWorld

SpringCloud 微服务基础系列之Nacos

查看Nacos服务器管理台界面,可以看到在服务列表中多了刚才启动的服务

SpringCloud 微服务基础系列之Nacos

Nacos 服务发现

为了便于使用,NacosServerList 实现了 com.netflix.loadbalancer.ServerList 接口,并在 @ConditionOnMissingBean 的条件下进行自动注入。如果您有定制化的需求,可以自己实现自己的 ServerList。

Nacos Discovery Starter 默认集成了 Ribbon ,所以对于使用了 Ribbon 做负载均衡的组件,可以直接使用 Nacos 的服务发现。

下面按照步骤创建项目 cloud-nacos-consumer-8001 服务,验证如何使用 RestTemplate 与 FeignClient

SpringCloud 微服务基础系列之Nacos

(1)添加 @LoadBlanced 注解,使得 RestTemplate 接入 Ribbon

@Bean
@LoadBalanced
public RestTemplate restTemplate(){
	return new RestTemplate();
}

(2)配置 FeignClient

@FeignClient(name = "nacos-provider-server")
public interface EchoService {

    @GetMapping(value = "/echo/{str}")
    String echo(@PathVariable("str") String str);
}

使用 @FeignClient 注解将 EchoService 这个接口包装成一个 FeignClient,属性 name 对应服务名 service-provider。

echo 方法上的 @RequestMapping 注解将 echo 方法与 URL "/echo/{str}" 相对应,@PathVariable 注解将 URL 路径中的 {str} 对应成 echo 方法的参数 str。

(3)完成以上配置后,将两者自动注入到 TestController 中。

@RestController
public class TestController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private EchoService echoService;

    @GetMapping(value = "/echo-rest/{str}")
    public String rest(@PathVariable String str) {
        return restTemplate.getForObject("http://nacos-provider-server/echo/" + str, String.class);
    }
    @GetMapping(value = "/echo-feign/{str}")
    public String feign(@PathVariable String str) {
        return echoService.echo(str);
    }
}

(4)启动项目

(5)在浏览器输入 http://localhost:8001/echo-rest/helloWorld, http://localhost:8001/echo-feign/helloWorld 访问成功

SpringCloud 微服务基础系列之Nacos

SpringCloud 微服务基础系列之Nacos

Nacos 服务注册与发现原理

服务注册

Spring Cloud Nacos Discovery 遵循了 spring cloud common 标准,实现了 AutoServiceRegistration、ServiceRegistry、Registration 这三个接口。

在 spring cloud 应用的启动阶段,监听了 WebServerInitializedEvent 事件,当Web容器初始化完成后,即收到 WebServerInitializedEvent 事件后,会触发注册的动作,调用 ServiceRegistry 的 register 方法,将服务注册到 Nacos Server。

服务发现

NacosServerList 实现了 com.netflix.loadbalancer.ServerList 接口,并在 @ConditionOnMissingBean 的条件下进行自动注入,默认集成了Ribbon。

如果需要有更加自定义的可以使用 @Autowired 注入一个 NacosRegistration 实例,通过其持有的 NamingService 字段内容直接调用 Nacos API。

Nacos 作为配置中心

Nacos 配置中心介绍

Nacos 配置中心支持 namespace(命名空间)、group(分组)、dataId(数据id) 三个属性确定一个配置

  • namespace:即命名空间,可以配置成 dev、test、pro 用于切换不用环境的配置,默认 public
  • group:即分组,可以将同一个项目下的不用服务配置命名同一个分组统一管理,默认 DEFAULT_GROUP
  • dataId: 即数据id,通常 dataId = ${spring.application.name}.${file-extension:properties} 或者dataId =${spring.application.name}-${profile}.${file-extension:properties}两种情况组成
  • 三者都可以在配置文件中自定义配置

namespace、group、dataId 三者之间的关系如下图所示

SpringCloud 微服务基础系列之Nacos

SpringCloud 微服务基础系列之Nacos

如何在SpringCloud项目中使用Nacos Config

  • 添加依赖
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
  • 新建 bootstrap.yml 文件
spring:
  application:
    name: nacos-provider-server # 应用名
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848 # nacos 服务地址

server:
  port: 7001 #端口号
  • 如果需要使用域名配置nacos服务地址,格式必须按照 domain name:port,例如 nacos.abc.com:80
  • file-extension 默认值为 properties

注意:根据前面介绍的dataId生成规则,这里的 dataId = ${spring.application.name}.${file-extension:properties}

即:dataId = nacos-provider-server.properties

  • 主启动类中添加读取配置代码s
@SpringBootApplication
@EnableDiscoveryClient
public class NacosProviderMain7001 {

    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(NacosProviderMain7001.class, args);
        String userName = applicationContext.getEnvironment().getProperty("user.name");
        String userAge = applicationContext.getEnvironment().getProperty("user.age");
        System.err.println("user name :" +userName+"; age: "+userAge);
    }

    @RestController
    class EchoController {
        @GetMapping(value = "/echo/{string}")
        public String echo(@PathVariable String string) {
            return "Nacos server: " + string;
        }
    }
}
  • Nacos 服务器上添加 dataId = nacos-provider-server.properties 的配置

SpringCloud 微服务基础系列之Nacos

  • 测试,启动项目

SpringCloud 微服务基础系列之Nacos

Nacos 配置动态刷新

  • nacos 支持配置动态刷新
  • nacos 配置动态刷新是默认开启的
  • 如果想要关闭动态刷新功能,修改配置为spring.cloud.nacos.config.refresh.enabled=false 即可关闭动态刷新
  • 如果需要在SpringBoot 配置类中动态读取 Nacos 配置有两种方式
    • 配置类上加注解 @RefreshScope(springcloud 提供) ,配置属性上依然使用 @Value 注解
    • 或者直接将配置属性上的@Value注解替换为@NacosValue(nacos 提供)注解,并设置autoRefreshed=true
  • 测试代码
@SpringBootApplication
@EnableDiscoveryClient
public class NacosProviderMain7001 {

    public static void main(String[] args) throws InterruptedException {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(NacosProviderMain7001.class, args);
        while (true){
            String userName = applicationContext.getEnvironment().getProperty("user.name");
            String userAge = applicationContext.getEnvironment().getProperty("user.age");
            System.err.println("user name :" +userName+"; age: "+userAge);
            TimeUnit.SECONDS.sleep(1);
        }
    }

    @RestController
    class EchoController {
        @GetMapping(value = "/echo/{string}")
        public String echo(@PathVariable String string) {
            return "Nacos server: " + string;
        }
    }
}

如果在项目启动过程中修改 nacos中的配置,那么控制台打印的结果也会随之变化

Nacos 集群与持久化配置

Nacos支持三种部署模式

  • 单机模式 - 用于测试和单机试用。
  • 集群模式 - 用于生产环境,确保高可用。
  • 多集群模式 - 用于多数据中心场景