【注册中心】
注册中心
分布式开发过程中要管理众多的服务也就是服务治理,管理服务与服务之间的依赖关系,实现服务调用、负载均衡、服务容错、以及服务的注册与发现。如果微服务之间存在调用依赖,就需要得到目标服务的服务地址,也就是微服务治理的服务发现。要完成服务发现,就需要将服务信息存储到某个载体,载体本身即是微服务治理的服务注册中心,而存储到载体的动作即是服务注册。
在 RPC/HTTP 远程调用过程中,服务与服务之间依赖关系非常大,服务 URL 地址管理非常复杂,所以这时候需要对我们服务的 URL 实现治理。通过服务治理可以实现服务注册与发现、负载均衡、容错等。每次调用该服务如果地址直接写死的话,一旦接口发生变化的情况下,这时候需要重新发布版本才可以接口调用地址,所以需要一个注册中心统一管理我们的服务注册与发现。
常见注册中心对比
CAP 理论
CAP 理论是分布式系统的三个指标。指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。这三个要素最多只能同时实现两点,不可能三者兼顾。而由于网络硬件肯定会出现延迟丢包等问题,所以分区容错性是我们必须需要实现的。所以我们只能在一致性和可用性之间进行权衡。
- 一致性(C): 在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
- 可用性(A): 在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
- 分区容忍性(P): 以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在 C 和 A 之间做出选择。
CAP 理论不能同时满足的原因
- CP 满足的情况下,A 不能满足的原因: 若要满足一致性(C)就需要在多个分布式节点之间进行数据同步,在数据同步完成之前整个系统都将不可用。节点数量越多分区容错性(P)越好,同时数据同步所耗费的时间自然也就越长,从而无法在有限的时间内完成请求响应,导致可用性(A)不能满足。
- CA 满足的情况下,P 不能满足的原因: 若要满足一致性(C)就需要在多个分布式节点之间进行数据同步,在数据同步完成之前整个系统都将不可用。需同步的节点数量越多,数据同步所需耗费的时间越长,可用性(A)也越差。若要同时保证可用性(A),那么需同步的节点数量就需要尽量减少,从而导致分区容错性(P)无法满足。
- AP 满足的情况下,C 不能满足的原因: 节点的数量越多,分区容错性(P)越好,节点间数据同步所需耗费的时间越长,若要在有限的时间内完成请求响应即保证可用性(A),那么数据就可能不能及时地同步到其他节点,从而无法保证节点间的数据一致性(C)。
CAP 理论满足情况
在分布式系统中分区容错性(P)肯定要满足,所以只能在 CA 中二选一, 没有最好的选择,只有更适合的,我们需要根据自己的业务场景来进行架构设计。
- Zookeeper: CP 设计,保证了一致性,集群搭建的时候,某个节点失效,则会进行选举新的 Leader,或者半数以上节点不可用,则无法提供服务,因此可用性(A)没法满足。
- Eureka: AP 设计,无主从节点,一个节点挂了,自动切换其他节点继续使用,去中心化,但数据一致性(C)不满足。
Nacos
Nacos 是一个更易于构件云原生应用的动态服务发现、服务管理、配置管理和消息驱动平台。即注册中心 + 配置中心 + 消息驱动。代替 Eureka + Config + Bus(Netflix 已经进入维护模式)
官方文档:https://sca.aliyun.com/
面试题:https://blog.csdn.net/golove666/article/details/137534990
【Nacos 注册中心】
SpringBoot 集成 Nacos 注册中心
只需要引入 Nacos 相关的包,并且启动类上加@EnableDiscoveryClient 注解即可,默认请求 Nacos 地址为本机的 8848 端口。而且@EnableDiscoveryClient 在 Nacos 某版本后是不需要写了,但是写上也无妨。
<!-- ============================ pom.xml ============================ -->
<!-- Nacos注册中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
# ============================ application.yml ============================
spring:
application:
# 服务名
name: server-a
cloud:
nacos:
discovery:
# Nacos服务端地址
server-addr: http://127.0.0.1:8848/
Nacos 页面信息
- 命名空间: 常用于区分不同的环境(开发、测试、生产)。
- 服务名: 就是各个客户端注册到注册中心的服务名称。
- 分组: 命名空间下更细粒度的分类。
- 元数据: 就是任意的 key-value 键值对。
- 保护阈值: 可以配置成 0-1 之间的小数,当(所有实例/健康实例<保护阈值)的时候,服务也会被分发到不健康的实例上,防止健康的实例压力过大。【基本不用,后续使用 Sentinal 进行服务保护】
Nacos 客户端其他配置
基本上 Nacos 在注册中心上的内容都体现在配置上,所以详细内容请查看下方代码块即可。
spring:
cloud:
nacos:
discovery:
# Nacos注册中心地址【默认127.0.0.1:8848】
server-addr: 127.0.0.1:8848
# Nacos账号【默认nacos】
username: nacos
# Nacos密码【默认nacos】
password: nacos
# 命名空间【默认public】
namespace: dev
# Nacos分组名【默认DEFAULT_GROUP】
group: imomei_group
# 网卡名。【当IP未配置时,注册的IP为网卡对应的IP地址。】
# 一般都使用spring.application.cloud.inetutils.preferred-networks=172.18.40进行配置注册IP选择前缀
network-interface: xxx
# 本服务注册到Nacos的IP地址【默认自动识别】
ip: xxx
# 本服务注册到Nacos的端口【默认自动识别】
port: xxx
# 是否临时实例。设置为永久实例,即使宕机也不会从列表中删除该服务【默认为true不永久】
ephemeral: false
# 权重,仅当Ribbon负载均衡策略配置为根据权重才生效。【默认为1】
weight: 2
# Nacos集群名称,仅当Nacos是集群部署这个配置才有用且必须。
cluster-name: xxx
【Nacos 服务端部署】
Linux 部署 Nacos 服务端(单机)
- 新建一个实例名为 nacos 的数据库,并执行 nacos/conf 下的 nacos-mysql.sql 文件创建表。
- 打开 conf 下的 application.properties 文件,修改数据库连接(如果不修改数据库的连接,默认存在内存中)
- 如果不是部署 nacos 集群,则将模式修改为单机模式。打开 bin/startup.cmd 或者 startup.sh 文件,将 MODE 从 cluster 改为 standalone
- 双击 bin/startup.cmd 文件,启动成功。打开浏览器访问:http://localhost:8848/nacos/index.html
- 默认账号密码:nacos/nacos
# ==================================== 修改application.properties ====================================
# 数据库类型
spring.datasource.platform=mysql
# 连接地址(要把.0去掉)
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos...
# 账号(要把.0去掉)
db.user=root
# 密码(要把.0去掉)
db.password=root
# ==================================== 修改startup.cmd/sh ====================================
set MODE="standalone"
Docker 部署 Nacos 服务端(单机)
docker run -d \
-e MODE=standalone \
--privileged=true \
-e JVM_XMS=128m \
-e MODE=standalone \
-e JVM_XMX=128m \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=182.92.158.133 \
-e NACOS_CORE_AUTH_ENABLED=false \
-e MODE=standalone \
-e MYSQL_SERVICE_PORT=3306 \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=cqz19960117 \
-e MYSQL_SERVICE_DB_NAME=nacos \
-e TIME_ZONE='Asia/Shanghai' \
-p 8848:8848 -p 9848:9848 -p 9849:9849 \
--name nacos --restart=always f151dab7a111
Nacos 服务端集群搭建
- 如同单机版一样,修改数据库相关配置,端口区分开即可。startup 启动脚本需要改成是 cluster,并且建议修改下脚本,降低启动内存占用。
- conf/cluster.conf.exmple 文件修改为 cluster.conf 并且内部配置上所有 Nacos 节点的 IP 端口。
- 使用 Nginx 对 Nacos 进行负载均衡。
- NacosClient 的配置文件修改为 nginx 暴露的端口,我这里服务是 8843、8846、8849,nginx 开放端口还是保持为 8848。(端口不能离太近,要不会占用下一个,所以离远点)
# ---------------------------------------------- cluster.conf -------------------------------------
# 集群各个IP和端口
127.0.0.1:8843
127.0.0.1:8846
127.0.0.1:8849
# ---------------------------------------------- nginx.conf -------------------------------------
# 通过Nginx对Nacos多个服务器进行负载均衡
upstream nacoscluster{
server 127.0.0.1:8843;
server 127.0.0.1:8846;
server 127.0.0.1:8849;
}
server {
listen 8848;
server_name 127.0.0.1;
location /nacos/ {
proxy_pass http://nacoscluster/nacos/;
}
}
# ---------------------------------------------- 客户端yml -------------------------------------
spring:
cloud:
nacos:
# Nacos注册中心地址(集群情况写Nginx的IP端口就可以)
server-addr: 127.0.0.1:8848
【Nacos 源码分析】
Nacos 客户端注册源码分析
AbstractAutoServiceRegistration类实现了ApplicationListener<WebServerInitializedEvent>,会在SpringBoot项目启动成功之后调用onApplicationEvent()方法。onApplicationEvent()中调用了start()方法。start()中间有一行是调用了register()方法。register()最终执行的就是NacosServiceRegistry类中的register()方法
@Override
public void register(Registration registration) {
NamingService namingService = namingService();
String serviceId = registration.getServiceId();
String group = nacosDiscoveryProperties.getGroup();
// 设置参数(从配置中获取)
Instance instance = getNacosInstanceFromRegistration(registration);
// 初始化注册
namingService.registerInstance(serviceId, group, instance);
}
register()中初始化了一些配置的参数,然后初始化注册器。- 注册器中调用
registerService()向 Nacos Server 端发送请求。具体请求方法为reqApi()
public String callServer(String api, Map<String, String> params, Map<String, String> body, String curServer, String method) throws NacosException {
// 这里就是请求注册
HttpRestResult<String> restResult = nacosRestTemplate.exchangeForm(url, header, Query.newInstance().initParams(params), body, method, String.class);
end = System.currentTimeMillis();
MetricsMonitor.getNamingRequestMonitor(method, url, String.valueOf(restResult.getCode())).observe(end - start);
if (restResult.ok()) {
return restResult.getData();
}
if (HttpStatus.SC_NOT_MODIFIED == restResult.getCode()) {
return StringUtils.EMPTY;
}
}
注册中心 - Nacos&spm=1001.2101.3001.5002&articleId=146235705&d=1&t=3&u=192006f7c4704b5a80400daf90529ced)
4万+

被折叠的 条评论
为什么被折叠?



