一、 Nacos简介

1 简介

Nacos是由阿里巴巴提供的一款专门构建云本地应用的动态服务发现、配置中心和服务管理平台。
在Spring Cloud Alibaba中常使用Nacos作为注册中心和分布式配置中心。
Nacos 官网地址:

https://nacos.io/en-us/

Nacos github地址:

https://github.com/alibaba/nacos

2 特性

2.1 服务发现和管理

动态服务发现是以服务为中心(例如微服务或云原生)体系结构的关键。Nacos支持基于DNS和基于RPC(Dubbo,gRPC)的服务发现,并提供实时服务运行状况检查,以防止将路由请求发送到不正常的主机或服务实例。使用Nacos,您还可以轻松地为您的服务安装断路器。

2.2 动态配置服务

动态配置服务使您可以集中,外部化和动态地管理所有环境中的配置。动态配置使您不必在配置更新时重新部署应用程序和服务。您可以实施无状态服务并轻松实现按需扩展。

2.3 动态DNS服务

通过支持加权路由,动态DNS(域名系统,Domain Name System)服务可帮助您在数据中心内的生产环境中实现中间层负载均衡,更灵活的路由,流量控制和DNS解析服务。动态DNS服务还使您更容易实现基于DNS的服务发现,从而最大程度地降低了耦合到特定于供应商的服务发现API的风险。

3 为什么使用Nacos

3.1 易于使用

动态服务发现,配置管理和动态DNS服务的一站式解决方案
20多种现成的功能,以服务为中心的体系结构
轻巧的生产就绪控制台

3.2 更适合云架构

无缝支持kubernetes和Spring Cloud
易于在流行的公共云(例如AliCloud和AWS(亚马逊AWS(Amazon Web Services)))上部署和运行
支持多租户和多环境

3.3 生产等级

源自阿里巴巴集团经过时间考验的内部产品
支持数百万种服务的大规模方案
具有企业级SLA(服务级别协议)的开源产品

3.4 丰富的互联网应用场景亲和力

支持速率调节,大型促销计划以及多区域双活架构
直接或稍微扩展支持各种基于Internet的相关用例
流量调度和服务治理

4 谁在使用Nacos

Nacos已经在很多大型公司中作为企业级应用成功持续运行。
Spring Cloud Alibaba Nacos服务注册及配置中心 - 图1

二、 Nacos架构

1 架构图

Spring Cloud Alibaba Nacos服务注册及配置中心 - 图2

2 核心概念

u 服务 (Service)
服务是指一个或一组软件功能(例如特定信息的检索或一组操作的执行),其目的是不同的客户端可以为不同的目的重用(例如通过跨进程的网络调用)。Nacos 支持主流的服务生态,如 Kubernetes Service、gRPC|Dubbo RPC Service 或者 Spring Cloud RESTful Service.
u 服务注册中心 (Service Registry)
服务注册中心,它是服务实例及元数据的数据库。服务实例在启动时注册到服务注册表,并在关闭时注销。服务和路由器的客户端查询服务注册表以查找服务的可用实例。服务注册中心可能会调用服务实例的健康检查 API 来验证它是否能够处理请求。
u 服务元数据 (Service Metadata)
服务元数据是指包括服务端点(endpoints)、服务标签、服务版本号、服务实例权重、路由规则、安全策略等描述服务的数据
u 服务提供方 (Service Provider)
是指提供可复用和可调用服务的应用方
u 服务消费方 (Service Consumer)
是指会发起对某个服务调用的应用方
u 配置 (Configuration)
在系统开发过程中通常会将一些需要变更的参数、变量等从代码中分离出来独立管理,以独立的配置文件的形式存在。目的是让静态的系统工件或者交付物(如 WAR,JAR 包等)更好地和实际的物理运行环境进行适配。配置管理一般包含在系统部署的过程中,由系统管理员或者运维人员完成这个步骤。配置变更是调整系统运行时的行为的有效手段之一。

u 配置管理 (Configuration Management)
在数据中心中,系统中所有配置的编辑、存储、分发、变更管理、历史版本管理、变更审计等所有与配置相关的活动统称为配置管理。

u 名字服务 (Naming Service)
提供分布式系统中所有对象(Object)、实体(Entity)的“名字”到关联的元数据之间的映射管理服务,例如 ServiceName -> Endpoints Info, Distributed Lock Name -> Lock Owner/Status Info, DNS Domain Name -> IP List, 服务发现和 DNS 就是名字服务的2大场景。

u 配置服务 (Configuration Service)
在服务或者应用运行过程中,提供动态配置或者元数据以及配置管理的服务提供者。

三、 基于Docker安装Nacos

1 拉取Nacos镜像

docker pull nacos/nacos-server

2 创建目录及配置文件

创建两个目录,分别是初始化目录和日志目录。
# mkdir -p /opt/nacos/init.d /opt/nacos/logs
新建配置文件
# vim /opt/nacos/init.d/custom.properties
在文件中添加以下内容

management.endpoints.web.exposure.include=*


3 创建并启动容器

端口8848
Mode=standalone 单机版
挂载配置文件和日志文件
—restart always 自动启动容器
使用内置Derby(Apache的一款小巧数据库)数据库。也可以修改为MySQL数据库,需要额外配置-e环境变量,具体如下:
Spring Cloud Alibaba Nacos服务注册及配置中心 - 图3
# docker run -d -p 8848:8848 -e MODE=standalone -e PREFER_HOST_MODE=hostname -v /opt/nacos/init.d/custom.properties:/home/nacos/init.d/custom.properties -v /opt/nacos/logs:/home/nacos/logs —restart always —name nacos nacos/nacos-server

4 访问Nacos可视化管理界面

启动过程需要花费一定时间,需要稍等一会才能访问。
访问: http://192.168.8.128:8848/nacos
默认的用户名和密码都是nacos
Spring Cloud Alibaba Nacos服务注册及配置中心 - 图4

四、 使用Nacos作为注册中心

Nacos支持HTTP和RPC协议访问。在导入Nacos依赖后内置Ribbon。和Eureka相同,都支持同名应用程序的负载均衡。
所以在使用Nacos作为注册中心的时候除了和Eureka依赖及配置文件不一样,其他流程都是一样的。
注意:Spring Cloud Alibaba依赖的Spring Boot最高版本只能是2.3.x。更高版本的spring boot和 spring cloud alibaba有兼容错误。启动失败。
注意:spring cloud alibaba 2021版本依赖,在使用openfeign技术做远程服务调用的时候,需要spring boot2.4.2及更高版本中的loadbalancer支持。但是启动的时候,必须使用spring boot 2.3.x版本中的spring-boot-context才能启动。有依赖冲突。无法实现服务的正常发现。暂时使用spring cloud alibaba2.2.x版本可以正常基于openfeign实现远程服务调用。

1 新建父项目

新建项目NacosParent。
在pom.xml导入相关依赖

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.5.RELEASE</version> </parent><dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR10</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.6.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>

2 新建Provider项目

在NacosParent下新建子项目Provider

2.1 配置pom.xml

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

2.2 编写配置文件

新建application.yml。
server-addr:配置nacos的ip和端口。

server:
port: 8080
spring:
application:
name: provider
cloud:
nacos:
discovery:
server-addr: 192.168.8.128:8848

2.3 新建控制器

新建com.bjsxt.controller.ProviderController。
该控制器是为了让另一个项目调用的。

@RestController
public class ProviderController {
@RequestMapping(“/provider”)
public String provider(){
return “provider-controller”;
}
}

2.4 新建启动类

新建com.bjsxt.ProviderApplication

@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class,args);
}
}

2.5 启动项目

启动项目中可以在Nacos可视化控制台中发现注册的信息。
Spring Cloud Alibaba Nacos服务注册及配置中心 - 图5

3 新建Consumer项目

在NacosParent项目下新建Consumer子项目。

3.1 配置pom.xml

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

3.2 新建配置文件

在resources下新建application.yml.
注意:
端口和应用程序名不要重复了。

server:
port: 8081
spring:
application:
name: consumer
cloud:
nacos:
discovery:
server-addr: 192.168.8.128:8848

3.3 新建配置类

新建com.bjsxt.config.ConsumerConfig

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

3.4 新建service及实现类

新建com.bjsxt.service.ConsumerService及实现类。
http://provider/provider 中第一个provider是另一个项目的应用程序名。第二个provider是控制器名称。

public interface ConsumerService {
String consumer();
}
@Service
public class ConsumerServiceImpl implements ConsumerService {
@Autowired
private RestTemplate restTemplate;

@Override
public String consumer() {
String result = restTemplate.getForObject(http://provider/provider, String.class);
return result;
}
}

3.5 新建控制器

新建com.bjsxt.controller.ConsumerController

@RestController
public class ConsumerController {
@Autowired
private ConsumerService consumerService;

@RequestMapping(“/consumer”)
public String consumer(){
return consumerService.consumer();
}
}

3.6 新建启动类

新建com.bjsxt.ConsumerApplication

@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}

3.7 运行项目,测试是否注册成功

运行项目在Nacos管理中心中查看是否已经成功注册。
Spring Cloud Alibaba Nacos服务注册及配置中心 - 图6

4 测试服务调用

在浏览器地址栏输入http://localhost:8081/consumer
如果是下面结果,说明使用Nacos作为注册中心案例成功。
Spring Cloud Alibaba Nacos服务注册及配置中心 - 图7

五、 使用Nacos作为Dubbo的注册中心

1 新建父项目

新建父项目DubboParent

1.1 配置pom.xml

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.5.RELEASE</version> </parent> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR9</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.3.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.3.5.RELEASE</version> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>2.2.3.RELEASE</version> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-dubbo</artifactId> <version>2.2.3.RELEASE</version> </dependency> </dependencies> </dependencyManagement>

2 新建API子项目

新建子项目api.
此项目作为Dubbo发布接口的项目。

2.1 新建接口

新建com.bjsxt.api.DemoApiService。接口名和包名不要和其他项目重复了,尤其不要和Consumer的Service接口名重复了。

public interface DemoApiService {
String demo();
}

3 新建Provider子项目

新建子项目provider

3.1 配置pom.xml

在依赖中要依赖api项目

<dependencies> <dependency> <artifactId>api</artifactId> <groupId>com.bjsxt</groupId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-dubbo</artifactId> </dependency> </dependencies>

3.2 新建配置文件

新建application.yml。
dubbo.scan.backages: 扫描@DubboService所在包。

dubbo:
# scan:
# base-packages: com.bjsxt.service.impl
# cloud:
# subscribed-services: dubbo-provider # 订阅的服务,默认 *
protocol:
# dubbo 协议
name: dubbo
# dubbo 协议端口( -1 表示自增端口,从 20880 开始)
port: -1
registry:
# 挂载到注册中心
address: nacos://192.168.8.128:8848
spring:
application:
# Dubbo 应用名称
name: dubbo-provider
# main:
# Spring Boot 2.1 需要设定
# allow-bean-definition-overriding: true
cloud:
nacos:
# Nacos 服务发现与注册配置
discovery:
server-addr: 192.168.8.128:8848

3.3 新建实现类

新建com.bjsxt.service.impl.DemoServiceImpl

@DubboService
public class DemoServiceImpl implements DemoApiService {
@Override
public String demo() {
return “dubbo-provider-service”;
}
}

3.4 新建启动类

新建com.bjsxt.ProviderApplication

@SpringBootApplication
@EnableDiscoveryClient
@EnableDubbo
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class,args);
}
}

4 新建Consumer项目

4.1 配置pom.xml

<dependencies> <dependency> <artifactId>api</artifactId> <groupId>com.bjsxt</groupId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-dubbo</artifactId> </dependency> </dependencies>

4.2 新建配置文件

新建application.yml

dubbo:
registry:
# 挂载到 Spring Cloud 注册中心
address: nacos://192.168.8.128:8848
# cloud:
# subscribed-services: dubbo-provider
protocol:
# dubbo 协议
name: dubbo
# dubbo 协议端口( -1 表示自增端口,从 20880 开始)
port: -1
server:
port: 8081
spring:
application:
# Dubbo 应用名称
name: dubbo-consumer
# main:
# Spring Boot 2.1 需要设定
# allow-bean-definition-overriding: true
cloud:
nacos:
# Nacos 服务发现与注册配置
discovery:
server-addr: 192.168.8.128:8848

4.3 新建service及实现类

新建com.bjsxt.service.ConsumerService

public interface ConsumerService {
String consumer();
}
@Service
public class ConsumerServiceImpl implements ConsumerService {
@DubboReference
private DemoApiService demoApiService;
@Override
public String consumer() {
return demoApiService.demo();
}
}

4.4 新建控制器

新建com.bjsxt.controller.ConsumerController

@RestController
public class ConsumerController {
@Autowired
private ConsumerService consumerService;

@RequestMapping(“/consumer”)
public String consumer(){
return consumerService.consumer();
}
}

4.5 新建启动类

新建com.bjsxt.ConsumerApplication

@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}

4.6 基于OpenFeign实现远程服务调用

4.6.1 修改pom.xml

增加依赖

<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>

4.6.2 定义OpenFeign调用接口
@FeignClient(“dubbo-provider”)
public interface CallProviderInterface {
@RequestMapping(“/provider”)
String test();
}

4.6.3 修改控制器
@RestController
public class ConsumerController {
@Autowired
private ConsumerService consumerService; @Autowired
private CallProviderInterface callProviderInterface; @RequestMapping(“/consumer2”)
public String consumer(){
return callProviderInterface.test();
} @RequestMapping(“/consumer”)
public String consumer(){
return consumerService.consumer();
}
}

4.6.4 修改启动类
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}

4.6.5 小结

由此可见。使用Spring Cloud Alibaba Dubbo技术开发微服务工程时,远程调用机制基于OpenFeign更加方便快捷。此方式为现今常见开发应用方式

5 测试结果

在浏览器输入 http://localhost:8081/consumer
Spring Cloud Alibaba Nacos服务注册及配置中心 - 图8

六、 实现Nacos作为配置中心

1 在nacos中新建配置文件

1.1 访问Nacos可视化管理界面

在配置列表中点击“+”
Spring Cloud Alibaba Nacos服务注册及配置中心 - 图9

1.2 添加配置文件信息

Data ID:名称任意。此名称作为配置文件名称(又可以叫前缀(prefix))
Group: 在没有自己建立组时默认为DEFAUL_GROUP。此值不需要修改
配置格式:选择properties或yml。此配置影响到客户端加载配置文件时配置。
配置内容:根据所选配置格式,按照指定格式填写内容。
Spring Cloud Alibaba Nacos服务注册及配置中心 - 图10

1.3 点击发布按钮后弹出配置文件信息

点击确定按钮不会自动关闭这个页面,而是回到编辑视图。

Spring Cloud Alibaba Nacos服务注册及配置中心 - 图11

1.4 在配置列表中查看

Spring Cloud Alibaba Nacos服务注册及配置中心 - 图12

2 新建项目

新建任意名称项目

3 编写pom.xml

spring-cloud-stater-aliobaba-nacos-config 是nacos配置中心客户端依赖。

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.5.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.3.5.RELEASE</version> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>2.2.3.RELEASE</version> </dependency> </dependencies> <dependencyManagement> <dependencies>






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

4 编写配置文件

新建配置文件。
新建bootstrap.yml

server:
port: 8070
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.8.128:8848
config: # 指定配置中心的地址和配置中心使用的数据格式 server-addr: 192.168.8.128:8848
# 默认加载文件扩展名为properties
file-extension: properties
# group默认值为DEFAULT_GROUP
# group: DEFAULT_GROUP
# 加载的配置文件名称默认值为应用程序名
# prefix: ${spring.application.name}
application:
name: config-client

5 新建service及实现类

新建com.bjsxt.service.ConfigClientService及实现类。
Nacos支持动态刷新功能。在获取分布式配置中心内容的类上添加@RefreshScope可以热刷新。

public interface ConfigClientService {
String configClient();
}
@Service
@RefreshScope
public class ConfigClientServiceImpl implements ConfigClientService {
@Value(“${my.name}”)
private String name;
@Value(“${my.age}”)
private Integer age;
@Override
public String configClient() {
return name+“—-“+age;
}
}

6 新建控制器

com.bjsxt.controller.ConfigServerController

@RestController
public class ConfigServerController {
@Autowired
private ConfigClientService configClientService;

@RequestMapping(“/“)
public String configServer(){
return configClientService.configClient();
}
}

7 新建启动类

新建com.bjsxt.ConfigClientApplication

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