一、SpringCloud Alibaba Nacos 介绍
Nacos
全名为 Naming Configuration Service
,取 Naming
和 Configuration
的前两个字母和 Service
的 s
,是配置管理和服务管理中心。
简单来说 Nacos = Eureka + Config + Bus,即 注册中心+配置中心的组合。替代 Eureka 做服务注册中心,替代 Config 做服务配置中心。
各种注册中心比较
CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。
- 一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
- 可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
- 分区容忍性(P):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。
例如:
如果在某个分布式系统中数据无副本, 那么系统必然满足强一致性条件, 因为只有独一数据,不会出现数据不一致的情况,此时C和P两要素具备,但是如果系统发生了网络分区状况或者宕机,必然导致某些数据不可以访问,此时可用性条件就不能被满足,即在此情况下获得了CP系统,但是CAP不可同时满足。
因此在进行分布式架构设计时,必须做出取舍。当前一般是通过分布式缓存中各节点的最终一致性来提高系统的性能,通过使用多节点之间的数据异步复制技术来实现集群化的数据一致性。
二、 当前项目结构介绍
当前项目中包含九个模块:
- 公有API:cloud-api-commons
- 服务提供者: cloud-provider-payment8001(增加 Sleuth)/8002 (端口号8001 和 8002 )
- 服务消费者(restTemplate): cloud-consumer-order80 (端口号80 ,增加 Sleuth)
- 服务消费者(OpenFeign): cloud-consumer-feign-order80(端口号80 )
- 注册中心 Eureka: cloud-eureka-server7001(端口号7001 )
- 使用断路器实现的服务提供者 (Hystrix):cloud-provider-hystrix-payment8001(端口号8001)
- 使用断路器实现的服务消费者(Hystrix):cloud-consumer-feign-hystrix-order80(端口号80)
- 服务监控(hystrixDashboard):cloud-consumer-hystrix-dashboard9001(端口号9001)
- 网关(Gateway):cloud-gateway-gateway9527(端口号9527)
前文链接: https://blog.csdn.net/weixin_42547014/article/details/120334570
项目源码: https://gitee.com/zhangchouchou/spring-cloud-demo
三、搭建 Nacos 服务注册中心
查看 Spring Cloud Alibaba 版本
访问Spring 官网,查看 Spring Cloud Alibaba 版本信息,当前最新的稳定版是 2.2.1
1. 基于 Nacos 的服务提供者
1). 父项目添加 Alibaba
<!--spring cloud alibaba 2.2.1.RELEASE-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
2). 新建Module,POM 增加引用
同样以 maven 的方式创建模块 cloudalibaba-provider-payment9001
创建完成后在 pom 中增加引用
<dependencies>
<!--alibaba nacos-->
<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-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</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>
</dependencies>
3). 新增 YML
server:
port: 9001
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848 #配置Nacos地址
management:
endpoints:
web:
exposure:
include: '*' #默认只公开了/health和/info端点,要想暴露所有端点只需设置成星号
4). 添加启动类
包名仍与其余模块相同 org.zjh.springcloud
@EnableDiscoveryClient
@SpringBootApplication
public class AlibabaPaymentApplication {
public static void main(String[] args) {
SpringApplication.run(AlibabaPaymentApplication.class,args);
}
}
5). 新增 Controller
@RestController
public class AlibabaPaymentController {
@Value("${server.port}")
private String serverPort;
@GetMapping(value = "/payment/nacos/{id}")
public String getPayment(@PathVariable("id") Long id) {
return "nacos registry, serverPort: "+ serverPort+"\t id"+id;
}
}
6). 测试
启动 9001 后访问 Nacos,可以看到刚刚启动的服务。
查看服务详情
访问服务 http://localhost:9001/payment/nacos/1
,测试通过。
7). 新建 9002 端口
为了演示负载均衡,参照 9001 端口创建 9002 端口,这里直接采用拷贝虚拟端口映射的方式新建。
在 Services 面板中复制 9001
修改启动类名称,配置端口号 -DServer.port=9002
,点击 ok
右键启动
8). 测试
刷新 Nacos 页面,服务数增加
访问 9002 端口 http://localhost:9002/payment/nacos/1
再查看 9001 端口
测试通过。
2. 基于 Nacos 的服务消费者
1). 新建 Module
以 maven 形式新建模块 cloudalibaba-consumer-nacos-order83
2). POM 中新增引用
<dependencies>
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.zjh.springclouddemo</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</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-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</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>
</dependencies>
为什么nacos支持负载均衡
3). 添加 YML
server:
port: 83
spring:
application:
name: nacos-order-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
#消费者将要去访问的微服务名称(成功注册进nacos的微服务提供者【可选】,注意:nacos-payment-provider含有IP和端口)
service-url:
nacos-user-service: http://nacos-payment-provider
4). 新增启动类
包名与其余模块相同
package org.zjh.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class OrderNacosApplication {
public static void main(String[] args){
SpringApplication.run(OrderNacosApplication.class,args);
}
}
5). RestTemplate
方式进行模块间调用
创建配置类
@Configuration // 声明配置
public class ApplicationContextConfig{
@Bean
@LoadBalanced // 声明使用负载均衡
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
创建 Controller
@RestController
@Slf4j
public class OrderNacosController{
@Resource
private RestTemplate restTemplate;
@Value("${service-url.nacos-user-service}")
private String serverURL;
@GetMapping(value = "/consumer/payment/nacos/{id}")
public String paymentInfo(@PathVariable("id") Long id){
return restTemplate.getForObject(serverURL+"/payment/nacos/"+id,String.class);
}
}
测试
刷新 Nacos
访问 http://localhost:83/consumer/payment/nacos/1
进行负载均衡测试
四、Nacos 服务配置中心
1. 基础配置
1). 创建 Module,POM 中添加引用
以 Maven 形式创建新模块 cloudalibaba-config-nacos-client3377
<dependencies>
<!--nacos-config-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--nacos-discovery-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--web + actuator-->
<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-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</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>
</dependencies>
2). 添加 YML 配置文件
Nacos同springcloud-config一样,在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置之后,才能保证项目的正常启动
springboot中配置文件的加载是存在优先级顺序的,bootstrap优先级高于application
bootstrap.yml
server:
port: 3377
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: localhost:8848 #服务注册中心地址
config:
server-addr: localhost:8848 #配置中心地址
file-extension: yaml #指定yaml格式的配置(yml和yaml都可以)
#${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
#nacos-config-client-dev.yaml (一定要与file-extension值保持一致)
application.yml
spring:
profiles:
active: dev #表示开发环境
3). 添加主启动类
package org.zjh.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class NacosConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(NacosConfigClientApplication.class, args);
}
}
4). 添加Controller
@RestController
@RefreshScope //通过SpringCould原生注解@RefreshScope实现配置自动更新
public class ConfigClientController{
@Value("${config.info}") //从nacos配置中心获取配置信息,对应nacos配置:nacos-config-client-dev.yaml
private String configInfo;
@GetMapping("/config/info")
public String getConfigInfo() {
return configInfo;
}
}
5). 添加配置
访问 Nacos 界面,添加配置
Nacos Data ID 命名规则
上图中的 Data ID 是配置的标识,需要按照规范进行命名。
命名公式:${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
所以最后命名为: nacos-config-client-dev.yaml
Nacos Group
group表示分组,可以将配置信息根据项目分为不同的组,比如电商项目,医疗项目,在线教育等等。
Nacos 配置格式
Data ID 中是什么格式,配置格式中就选择什么格式
Nacos 配置内容
在之前的 Controller 中已经写好要获取 config.info
所以在配置内容加入下面内容,注意配置格式
config:
info: "我是config.info,我来自配置中心"
都填写好以后点击发布
6). 测试
启动服务,访问 http://localhost:3377/config/info
进行测试
7). 自动刷新配置测试
进入 Nacos 对配置进行修改
修改完成后刷新访问界面,测试通过。
2. 分类配置
实际开发过程中可能会遇到很多问题,比如:
- 通常一个系统会准备——dev开发环境、test测试环境、prod生产环境,那么如何保证指定环境启动时服务能正确读取到 Nacos上相应环境的配置文件呢?
- 一个大型分布式微服务系统会有很多微服务子项目,每一个微服务项目又会有相应的开发环境、测试环境、预发环境、正式环境….那怎么对这些微服务配置进行管理呢?
为了应付这种情况,Nacos 采用了 Namespace(命名空间)、Group(分组)和 Data ID(配置标识)的方法来进行管理。
他们之间的关系如下图所示:
Nacos 默认的命名空间是public,主要用来实现隔离。
比方说我们现在有三个环境:开发、测试、生产环境,我们就可以创建三个Namespace,不同的 Namespace之间是隔离的。Group默认是DEFAULT_GROUP,Group可以把不同的微服务划分到同一个分组里面去。Service就是微服务;一个Service可以包含多个Cluster(集群),Nacos默认Cluster是DEFAULT,Cluster是对指定微服务的一个虚拟划分。
比方说为了容灾,将Service微服务分别部署在了杭州机房和广州机房,这时就可以给杭州机房的Service微服务起一个集群名称(HZ),给广州机房的Service微服务起一个集群名字(GZ),还可以尽量让同一个机房的微服务互相调用,以提升性能。Instance,就是微服务的实例。
接下来进行测试
1). 创建新的命名空间
2). 在各自的命名空间中加入新的分组和配置
public 下
test_dev 下
3). 切换分组
没有更改命名空间,没有更改部署环境(dev)
在 config 下增加一条 group 的配置即可限定分组。
重启服务,访问 http://localhost:3377/config/info
进行测试
4). 切换 Data ID
在限定 Group 的基础上,部署环境切换为 test
通过 spring.profile.active 属性就能进行多环境下配置文件的读取
5). 切换 Namespace
现在限定访问 test_dev 空间下的 DEV_GROUP 分组的 dev 开发环境的配置
在配置文件中添加 Namespace ID
五、Nacos 集群和持久化配置
1. 集群部署架构图
vip : 代理服务器
推荐用户把所有服务列表放到一个vip下面,通过域名绑定这个 vip(代理服务器),并通过这个代理服务器将请求发给 Nacos1、Nacos2、Nacos3
2. 实际集群部署情况
Nacos 默认使用嵌入式数据库实现数据的存储。所以,如果启动多个默认配置下的Nacos节点,数据存储是存在一致性问题的。
为了解决这个问题,Nacos采用了集中式存储的方式来支持集群化部署,目前只支持MySQL 的存储。 也就是说,Nacos 部署信息持久化只能存到MySQL数据库中
3. Nacos 持久化配置
将 Nacos 配置信息持久化到 MySQL 数据库的方式在之前的下载安装 Nacos 的连接中已经介绍。具体位置在解决启动时报 Unable to start embedded Tomcat
错误的解决方式里
4. 搭建 Nacos 集群
官方推荐使用 Linux 系统搭建集群
准备条件