Spring Boot集成Nacos
启动配置管理
1. 添加依赖
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.8</version>
</dependency>
2. 在 application.properties
中配置 Nacos server 的地址
nacos.config.server-addr=127.0.0.1:8848
3. 配置加载获取
-
使用
@NacosPropertySource
加载dataId
为example
的配置文件,并开启自动更新@SpringBootApplication
@NacosPropertySource(dataId = "example", autoRefreshed = true)
public class NacosExampleApplication {
public static void main(String[] args) {
SpringApplication.run(NacosExampleApplication.class, args);
}
}
-
通过 Nacos 的
@NacosValue
注解设置属性值@Controller
@RequestMapping("config")
public class ConfigController {
@NacosValue(value = "${useLocalCache:false}", autoRefreshed = true)
private boolean useLocalCache;
@RequestMapping(value = "/get", method = GET)
@ResponseBody
public boolean get() {
return useLocalCache;
}
}
启动服务发现
1. 添加依赖
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-discovery-spring-boot-starter</artifactId>
<version>0.2.8</version>
</dependency>
2. 在 application.properties
中配置 Nacos server 的地址
nacos.config.server-addr=127.0.0.1:8848
3. 服务发现
-
编写测试接口并启动
NacosExampleApplication
@Controller
@RequestMapping("discovery")
public class DiscoveryController {
@NacosInjected
private NamingService namingService;
@RequestMapping(value = "/get", method = GET)
@ResponseBody
public List<Instance> get(@RequestParam String serviceName) throws NacosException {
return namingService.getAllInstances(serviceName);
}
}
-
访问
curl http://localhost:8080/discovery/get?serviceName=example
,返回内容为:[
{
"instanceId": "127.0.0.1#8080#DEFAULT#DEFAULT_GROUP@@example",
"ip": "127.0.0.1",
"port": 8080,
"weight": 1.0,
"healthy": true,
"enabled": true,
"ephemeral": true,
"clusterName": "DEFAULT",
"serviceName": "DEFAULT_GROUP@@example",
"metadata": {},
"instanceHeartBeatInterval": 5000,
"instanceHeartBeatTimeOut": 15000,
"ipDeleteTimeout": 30000,
"instanceIdGenerator": "simple"
}
]
Spring Cloud集成Nacos
-
在pom文件中引入依赖
<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-config</artifactId>
</dependency>
-
在bootstrap.yml中配置Nacos Server地址
spring:
application:
name: nacos_demo
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
group: DEFAULT_GROUP
file-extension: yaml
namespace: public
name: nacos_demo
discovery:
server-addr: 127.0.0.1:8848
namespace: public
group: DEFAULT_GROUP
-
在主启动类上添加@EnableDiscoveryClient注解来开启注册客户端
@SpringBootApplication
@EnableDiscoveryClient
@EnableConfigurationProperties
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
-
启动Nacos Server客户端 创建Data Id 为nacos_demo的配置文件
Q&A
Nacos 和Eureka有什么优势
-
功能差异
模块 | Nacos | Eureka | 说明 |
---|---|---|---|
注册中心 | 是 | 是 | 服务治理基本功能,负责服务中心化注册 |
配置中心 | 是 | 否 |
Eureka需要配合Config实现配置中心,且不提供管理界面 |
动态刷新 | 是 | 否 |
Eureka需要配合MQ实现配置动态刷新,Nacos采用Netty保持TCP长连接实时推送 |
可用区AZ | 是 | 是 | 对服务集群划分不同区域,实现区域隔离,并提供容灾自动切换 |
分组 | 是 | 否 |
Nacos可用根据业务和环境进行分组管理 |
元数据 | 是 | 是 | 提供服务标签数据,例如环境或服务标识 |
权重 | 是 | 否 |
Nacos默认提供权重设置功能,调整承载流量压力 |
健康检查 | 是 | 是 | Nacos支持由客户端或服务端发起的健康检查,Eureka是由客户端发起心跳 |
负载均衡 | 是 | 是 | 均提供负责均衡策略,Eureka采用Ribion |
管理界面 | 是 | 否 |
Nacos支持对服务在线管理,Eureka只是预览服务状态 |
-
部署安装
模块 | Nacos | Eureka | 说明 |
---|---|---|---|
MySql | 是 | 否 |
Nacos需要采用MySql进行数据进行持久化 |
MQ | 否 |
是 | Eureka需要采用MQ进行配置中心刷新 |
配置中心 | 是 | 否 |
Eureka结合Config或者Consul实现配置中心 |
配置文件 | 在线编辑 | 本地文件或者Git远程文件 | Eureka结合Config或者Consul |
集群 | 是 | 是 | Nacos需要配置集群ip再启动 |
大部分不适用Eureka的原因是因为2.x闭源了
Nacos 端口占用说明
集群配置中不要使用连续端口,nacos 2.0之后增加了默认的服务端口供nacos内部使用
对于Nacos2.x客户端来说,默认的9848也是根据当前客户端指定的8848端计算指定的,所以当更改服务端8848端口以后,建议提前计算好对应的GRPC端口。
端口 | 含义 |
---|---|
8848 | Nacos项目核心启动主端口,HTTP服务接口 |
9848 | Nacos中的GRPC SDK Server端的端口,用于客户端GRPC连接,默认为主端口偏移+1000 |
9849 | Nacos中的GRPC Cluster Server端的端口,用于集群机器间,GRPC同步通信,默认为主端口偏移+1001 |
7848 | Nacos中的Raft数据同步端口,用于服务端集群之间数据同步,默认为主端口偏移-1000 |
public static final Integer SDK_GRPC_PORT_DEFAULT_OFFSET = 1000;
public static final Integer CLUSTER_GRPC_PORT_DEFAULT_OFFSET = 1001;
private static final int DEFAULT_RAFT_OFFSET_PORT = 1000;
动态刷新配置
-
通过 Spring Cloud 原生注解
@RefreshScope
实现配置自动更新:@RestController
@RefreshScope
@RequiredArgsConstructor
public class NacosTestController {
@Value("${server.port}")
private String port;
@Value("${user.age}")
private String age;
@RequestMapping("refreshScope")
public Map<String, Object> refreshScope() {
final HashMap<String, Object> map = new HashMap<>(12);
map.put("port", port);
map.put("age", age);
return map;
}
}
-
被
@ConfigurationProperties
注解修饰的配置类:这些配置类生效的原因是触发了EnvironmentChangeEvent
事件@Setter
@ToString
@Configuration
@ConfigurationProperties("user")
public class User {
/**
* 姓名
*/
private String name;
/**
* 昵称
*/
private String nickName;
/**
* 年龄
*/
private Long age;
/**
* 性别
*/
private String sex;
}
-
通过
Environment
获取的配置:例如env.getProperty("book.category")
final private Environment environment;
@RequestMapping("getProperty")
public String getProperty(String property) {
return property + ":" + environment.getProperty(property);
}
版本说明
由于 Spring Boot 3.0,Spring Boot 2.7~2.4 和 2.4 以下版本之间变化较大,目前企业级客户老项目相关 Spring Boot 版本仍停留在 Spring Boot 2.4 以下,为了同时满足存量用户和新用户不同需求,社区以 Spring Boot 3.0 和 2.4 分别为分界线,同时维护 2022.x、2021.x、2.2.x 三个分支迭代。 为了规避相关构建过程中的依赖冲突问题,我们建议可以通过 云原生应用脚手架 进行项目创建。
2022.x 分支
适配 Spring Boot 3.0,Spring Cloud 2022.x 版本及以上的 Spring Cloud Alibaba 版本按从新到旧排列如下表(最新版本用*标记): (注意,该分支 Spring Cloud Alibaba 版本命名方式进行了调整,未来将对应 Spring Cloud 版本,前三位为 Spring Cloud 版本,最后一位为扩展版本,比如适配 Spring Cloud 2022.0.0 版本对应的 Spring Cloud Alibaba 第一个版本为:2022.0.0.0,第个二版本为:2022.0.0.1,依此类推)
Spring Cloud Alibaba Version | Spring Cloud Version | Spring Boot Version |
---|---|---|
2022.0.0.0-RC* | Spring Cloud 2022.0.0 | 3.0.0 |
2021.x 分支
适配 Spring Boot 2.4,Spring Cloud 2021.x 版本及以上的 Spring Cloud Alibaba 版本按从新到旧排列如下表(最新版本用*标记):
Spring Cloud Alibaba Version | Spring Cloud Version | Spring Boot Version |
---|---|---|
2021.0.4.0* | Spring Cloud 2021.0.4 | 2.6.11 |
2021.0.1.0 | Spring Cloud 2021.0.1 | 2.6.3 |
2021.1 | Spring Cloud 2020.0.1 | 2.4.2 |
2.2.x 分支
适配 Spring Boot 为 2.4,Spring Cloud Hoxton 版本及以下的 Spring Cloud Alibaba 版本按从新到旧排列如下表(最新版本用*标记):
Spring Cloud Alibaba Version | Spring Cloud Version | Spring Boot Version |
---|---|---|
2.2.9.RELEASE* | Spring Cloud Hoxton.SR12 | 2.3.12.RELEASE |
2.2.8.RELEASE | Spring Cloud Hoxton.SR12 | 2.3.12.RELEASE |
2.2.7.RELEASE | Spring Cloud Hoxton.SR12 | 2.3.12.RELEASE |
2.2.6.RELEASE | Spring Cloud Hoxton.SR9 | 2.3.2.RELEASE |
2.2.1.RELEASE | Spring Cloud Hoxton.SR3 | 2.2.5.RELEASE |
2.2.0.RELEASE | Spring Cloud Hoxton.RELEASE | 2.2.X.RELEASE |
2.1.4.RELEASE | Spring Cloud Greenwich.SR6 | 2.1.13.RELEASE |
2.1.2.RELEASE | Spring Cloud Greenwich | 2.1.X.RELEASE |
2.0.4.RELEASE(停止维护,建议升级) | Spring Cloud Finchley | 2.0.X.RELEASE |
1.5.1.RELEASE(停止维护,建议升级) | Spring Cloud Edgware | 1.5.X.RELEASE |
组件版本关系
每个 Spring Cloud Alibaba 版本及其自身所适配的各组件对应版本如下表所示(注意,Spring Cloud Dubbo 从 2021.0.1.0 起已被移除出主干,不再随主干演进):
Spring Cloud Alibaba Version | Sentinel Version | Nacos Version | RocketMQ Version | Dubbo Version | Seata Version |
---|---|---|---|---|---|
2022.0.0.0-RC | 1.8.6 | 2.2.1-RC | 4.9.4 | ~ | 1.6.1 |
2.2.9.RELEASE | 1.8.5 | 2.1.0 | 4.9.4 | ~ | 1.5.2 |
2021.0.4.0 | 1.8.5 | 2.0.4 | 4.9.4 | ~ | 1.5.2 |
2.2.8.RELEASE | 1.8.4 | 2.1.0 | 4.9.3 | ~ | 1.5.1 |
2021.0.1.0 | 1.8.3 | 1.4.2 | 4.9.2 | ~ | 1.4.2 |
2.2.7.RELEASE | 1.8.1 | 2.0.3 | 4.6.1 | 2.7.13 | 1.3.0 |
2.2.6.RELEASE | 1.8.1 | 1.4.2 | 4.4.0 | 2.7.8 | 1.3.0 |
2021.1 or 2.2.5.RELEASE or 2.1.4.RELEASE or 2.0.4.RELEASE | 1.8.0 | 1.4.1 | 4.4.0 | 2.7.8 | 1.3.0 |
2.2.3.RELEASE or 2.1.3.RELEASE or 2.0.3.RELEASE | 1.8.0 | 1.3.3 | 4.4.0 | 2.7.8 | 1.3.0 |
2.2.1.RELEASE or 2.1.2.RELEASE or 2.0.2.RELEASE | 1.7.1 | 1.2.1 | 4.4.0 | 2.7.6 | 1.2.0 |
2.2.0.RELEASE | 1.7.1 | 1.1.4 | 4.4.0 | 2.7.4.1 | 1.0.0 |
2.1.1.RELEASE or 2.0.1.RELEASE or 1.5.1.RELEASE | 1.7.0 | 1.1.4 | 4.4.0 | 2.7.3 | 0.9.0 |
2.1.0.RELEASE or 2.0.0.RELEASE or 1.5.0.RELEASE | 1.6.3 | 1.1.1 | 4.4.0 | 2.7.3 | 0.7.1 |
Nacos 版本选择
Nacos 经过 4 年的发展,目前在大版本演进上已经到了第二代 Nacos 架构,即 Nacos 2.x 版本,Nacos 2.x 版本是基于 Nacos 1.x 中用户反馈使用习惯以及产品演进方向而构建的产品能力,中间包含了比如一致性算法升级,对性能的 10 倍提升,以及支持插件化来满足社区的定制诉求。并且保障了很好的兼容性,在服务能力上 Nacos 2.x 是完全兼容 Nacos 1.x 的协议,也就是 Nacos 2.x 服务端是完全兼容 Nacos 1.x 的客户端。
在基本能力上,Nacos 2.x 一致性协议复用了阿里在该领域最佳实践,以长连接为基础,减低通信损耗,基于Distro协议原有协议进行升级,在存储模型、保活模型上进行了重构,并且用推送机制代替了之前的轮训机制,进一步提升了产品的高可用以及稳定性,整体也复用了阿里百万实例的基础模型,在CAP理论基础上,根据场景来去选择最适合的协议,贴合场景来平衡一致性、高可用以及分区容灾,做到服务发现以及配置管理每个场景下,都做到稳定性、高可用、高性能的保障。
在拓展能力上,Nacos 2.x版本开始支持插件化能力,基于插件化是更方便的支持用户各种场景,很多用户公司内部有完善的体系基于Nacos可以简单的改造就可以融合进入,在鉴权、配置加解密场景都可以做到按照用户需求进行定制,并且给出默认的开源实现供用户选择,加解密为例,开源给出的默认实现是基于AES,用户也可以进行自定义。并且目前数据库的插件已经在路上,后续还会在安全等更多方面支持可插拔的插件化能力。
总结版本选择:
- 使用Nacos2.x版本是目前Nacos的最佳选择
- 在1.x版本升级到2.0.4是最默认兼容平滑
Nacos的规划
Nacos 已经经历了两个重要阶段,初创期和高速发展期,目前正处于被大规模使用的 Nacos 的第三阶段是成为基础设施,需要面向于基础设施进行演进,帮助企业数字化转型,深度的拥抱各个领域内的场景,并且更深度的帮助企业解决问题。Nacos 社区目前面向于第三阶段,开始筹备 Nacos 3.0 架构设计进行规划讨论,并且逐步开始进行落地。
目前针对 Nacos 3.0 的建设规划大图主要包含三部分,第一部分是开源品牌和社区的升级,主要是面向于社区建立更紧密的联系。第二部分是面向更多生态进行深度融合,包含 K8s 数据整合、以及多生态数据打通,第三部分是最基础的部分,产品能力升级,基于 Nacos2.x 的协议进行增强,并且支持统一控制面、多数据中心等基础能力,用于支撑 Nacos 3.0 生态建设以及品牌升级。
目前 Nacos 3.0 部分已经随着社区核心贡献者开展中,大多数还在规划阶段,后续会通过 Github issues 进行开放,随之会打上 Nacos 3.0 的标签,欢迎大家进行领取一起参与到 Nacos 3.0 的贡献。
Nacos的一致性算法
1. CAP原则
又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。
CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。
2. Raft算法
Nacos 集群为了保证集群中数据的一致性,其采用了 Raft 算法,是通过对日志进行复制管理来达到一致性的算法。
Raft 算法是强一致性算法。
Nacos 同时支持 AP 与 CP,默认情况下,Nacos 集群是 AP 的。
Raft算法将Server划分为三种角色:
- Leader:负责处理客户端读和写请求的节点,同时负责日志复制工作,一个集群中只有一个Leader。
- Follower:可以处理客户端读请求,负责同步来自于 Leader 的日志,当接收到其它Cadidate 的投票请求后可以进行投票;当发现 Leader 挂了,其会转变为 Candidate 发起Leader 选举。
- Candidate:一种临时的角色,只存在于leader的选举阶段(Leader 选举的候选人),某个节点想要变成leader,那么就发起投票请求,同时自己变成candidate。如果选举成功,则变为candidate,否则退回为follower
3.选举
Raft中使用心跳机制来出发leader选举。当服务器启动的时候,服务器成为follower。只要follower从leader或者candidate收到有效的RPCs就会保持follower状态。如果follower在一段时间内(该段时间被称为election timeout)没有收到消息,则它会假设当前没有可用的leader,然后开启选举新leader的流程。
Term(任期)
任期用连续的数字进行表示。每一个任期的开始都是一次选举(election),在某些情况下,有可能没有选出Leader,那么,将会开始另一个任期,并且立刻开始下一次选举。Raft 算法保证在一个任期内只有一个Leader.
过程
- follower增加当前的term;
- 转变为candidate;
- 向自己投票;
- 向其它节点发出投票请求。
投票
- 发来投票请求 candidate 的 term 和 log 编号不能小于当前 candidate 的 term 和 log 编号;
- 当前 term 内 candidate 的票还没投递给自己(一个 term 内每个节点都只有一票 );
- 接收到多个投票请求时,采取先到先得投递。
结果
当一个 Candidate 发出投票请求后会等待其它节点的响应结果。这个响应结果可能有三种情况:
- 收到过半选票,成为新的 leader。然后会将消息广播给所有其它节点,产生新 Leader 了(其中包含其当前的 term);
- 接收到别的 candidate 发来的新 leader 通知,比较新 leader 的 term 是否不比当前的 term小,则自己转变为 follower;
- 没有收到过半选票,也没有收到新 leader 通知,则重新选举。
- 票数相同时,采取随机选举超时处理:让这些 candidate 的选举在一个给定范围值内,各自随机的 timeout 之后开始,此时先到达 timeout 的 candidate 会先发出投票请求,并优先获取到投票。
4.数据同步/日志复制
主要作用是用于保证节点的一致性,这阶段所做的操作也是为了保证一致性与高可用性。
Raft 把每条日志都附加了 任期号和下标 来保证日志的唯一性.
当Leader选举出来后便开始负责客户端的请求,所有事务(更新操作)请求都必须先经过Leader处理。
- 在Raft中当接收到客户端的日志(事务请求)后先把该日志追加到本地的Log中;
- 然后通过 heartbeat 把该Entry同步给其他 Follower;
- Follower 接收到日志后记录日志然后向 Leader 发送ACK;
- 当 Leader 收到大多数(n/2+1)Follower的ACK信息后将该日志设置为已提交并追加到本地磁盘中;
- 通知客户端并在下个heartbeat中 Leader 将通知所有的Follower将该日志存储在自己的本地磁盘中。
5.脑裂
在一个高可用系统中,当联系着的节点因为网络连接断开联系时,本来为一个整体的系统,分裂成两个独立节点,两个节点开始争抢共享资源造成系统混乱、数据损坏的现象,成为“脑裂”。
列如:FollowerA由于网络问题感知不到Leader存在,FollowerA与FollowerB之间是相连的,此时FollowerA会发起选举,虽然 FollowerB能够感知到 Leader,但由于其接收到了更大 term 的投票请求,所以 FollowerB也就放弃了Leader,参与了新 Leader 的选举。新Leader的写请求并不会同步到原Leader节点上。而之前的Leader由于无法获取过半响应而无法处理写操作请求,不过并没有被Down,其仍为 Leader。所以之前Leader的数据是不会发生变更的。此时就形成了数据的不一致。
解决方案:通过时间续约和term比较最终旧leader被同步为follower。
标签:Spring,nacos,Nacos,详解,RELEASE,2.2,Leader,Cloud From: https://www.cnblogs.com/xiaotian0422/p/17036135.html