Nacos,Ribbon,Feign 相关问题收集

Nacos,Ribbon,Feign 相关问题收集

Nacos原理图


Nacos注册中心

Nacos的服务注册表结构是怎样的?

Nacos采用了数据的分级存储模型,最外层是Namespace,用来隔离环境。然后是Group,用来对服务分组。接下来就是服务(Service)了,一个服务包含多个实例,但是可能处于不同机房,因此Service下有多个集群(Cluster),Cluster下是不同的实例(Instance)。

对应到Java代码中,Nacos采用了一个多层的Map来表示。结构为Map<String, Map<String, Service>>,其中最外层Map的key就是namespaceId,值是一个Map。内层Map的key是group拼接serviceName,值是Service对象。Service对象内部又是一个Map,key是集群名称,值是Cluster对象。而Cluster对象内部维护了Instance的集合。

Nacos注册中心原理

Nacos 工作流程

以Java版本的Nacos客户端为例,服务注册基本流程:

  • 服务实例启动将自身注册到Nacos注册中心,随后维持与注册中心的心跳;
  • 心跳维持策略为每5秒向Nacos Server发送一次心跳,并携带实例信息(服务名、实例IP、端口等);
  • Nacos Server也会向Client主动发起健康检查,支持TCP/Http;
  • Nacos Server端,15秒内无心跳且健康检查失败则认为实例不健康,如果30秒内健康检查失败则剔除实例;
  • 服务消费者通过注册中心获取实例,并发起调用;

其中服务发现支持两种场景

  • 服务消费者直接向注册中心发送获取某服务实例的请求,注册中心返回所有可用实例,但一般不推荐此种方式;

  • 服务消费者向注册中心订阅某服务,并提交一个监听器,当注册中心中服务发生变化时,监听器会收到通知,消费者更新本地服务实例列表,以保证所有的服务均可用。

Nacos注册表如何防止多节点读写并发冲突

写时复制(读写分离)

不采用加锁的设计,可以保证高并发。当要更新实例时,先将内存中的注册表实例复制出来,跟要更新的实例对比,如果不一致,则去更新注册表中的实例。

img

源码解析-Nacos注册中心(AP架构)

Nacos如何支撑阿里内部数十万服务注册压力?

Nacos内部接收到注册的请求时,不会立即写数据,而是将服务注册的任务放入一个阻塞队列就立即响应给客户端。然后利用线程池读取阻塞队列中的任务,异步来完成实例更新,从而提高并发写能力。

服务消费者调用提供者

如果消费者订阅了服务,那么会在本地基于内存维护一个服务信息列表,之后进行服务调用是直接从本地列表获取对应的服务实例进行调用,否则去主从中心获取服务实例。

服务提供者与服务消费者之间是通过feign+ribbon进行配合调用的,feign提供http请求的封装以及调用,ribbon提供负载均衡。负载均衡有很多种实现方式,包括轮询法,随机方法法,对请求ip做hash后取模等等。 Nacos的客户端在获取到服务的完整实例列表后,会在客户端进行负载均衡算法来获取一个可用的实例,默认使用的是随机获取的方式.

Nacos配置中心

Nacos配置中心交互模型是push还是pull

客户端通过长轮询的方式拉取的.

客户端、控制台通过发送Http请求将配置数据注册到服务端,服务端持久化数据到Mysql。

客户端拉取配置数据,并批量设置对dataId的监听发起长轮询请求,如服务端配置项变更立即响应请求,如无数据变更则将请求挂起一段时间,直到达到超时时间。为减少对服务端压力以及保证配置中心可用性,拉取到配置数据客户端会保存一份快照在本地文件中,优先读取。

阿里面试这样问:Nacos配置中心交互模型是push还是pull ?(一)-开源基础软件社区

阿里面试这样问:Nacos配置中心交互模型是push还是pull ?(一)

服务消费者怎么获取Nacos配置信息

如果服务端配置与客户端一直没有变化

如果客户端拉取发现客户端与服务端配置是一致的(其实是通过MD5判断的)那么服务端会先拿住这个请求不返回,直到这段时间内配置有变化了才把刚才拿住的请求返回。他的步骤是nacos服务端收到请求后检查配置是否发生变化,如果没有则开启定时任务,延迟29.5s执行。同时把当前客户端的连接请求放入队列。那么此时服务端并没有将结果返回给客户端,当有以下2种情况的时候才触发返回。

  • 就是等待29.5s后触发自动检查
  • 在29.5s内有配置进行了更改

经过这2种情况才完成这次的pull操作。这种的好处就是保证了客户端的配置能及时变化更新,也减少了轮询给服务端带来的压力。

比客户端 30s 的超时时间提前 500ms 返回是为了最大程度上保证客户端不会因为网络延时造成超时。

Nacos服务如何多节点同步配置信息

服务端一般是多节点部署的集群,因此请求一开始只会打到一台机器,这台机器将配置插入 MySQL 中进行持久化.

因为服务端并不是针对每次配置查询都去访问 MySQL 的,而是会依赖 dump 功能在本地文件中将配置缓存起来。因此当单台机器保存完毕配置之后,需要通知其他机器刷新内存和本地磁盘中的文件内容,因此它会发布一个名为 ConfigDataChangeEvent 的事件,这个事件会通过 HTTP 调用通知所有集群节点(包括自身),触发本地文件和内存的刷新。

Nacos服务如何处理消费者获取配置信息的长轮询请求

客户端会有一个长轮询任务,拉取服务端的配置变更,那么服务端是如何处理这个长轮询任务的呢?源码逻辑位于 LongPollingService 类,其中有一个 Runnable 任务名为 ClientLongPolling,服务端会将受到的轮询请求包装成一个 ClientLongPolling 任务,该任务持有一个 AsyncContext 响应对象(Servlet 3.0 的新机制),通过定时线程池延后 29.5s 执行。

为什么比客户端 30s 的超时时间提前 500ms 返回是为了最大程度上保证客户端不会因为网络延时造成超时

undefined

这里需要注意的是,在 ClientLongPolling 任务被提交进入线程池待执行的同时,服务端也通过一个队列 allSubs 保存了所有正在被夯住的轮询请求,这是因为在配置项被夯住的期间内,如果用户通过管理平台操作了配置项变更、或者服务端该节点收到了来自其他节点的 dump 刷新通知,那么都应立即取消夯住的任务,及时通知客户端数据发生了变更。

Eureka、ZooKeeper、Nacos 区别

Eureka 不能支撑大量服务实例,因为 Eureka 的每个节点数据都一致,会产生大量的心跳检查等等导致并发性能低下,ZooKeeper 的频繁上下线通知会导致性能下降,而 Nacos 可以支持大量服务实例又不丢性能,据说服务数量能达到 10 万以上。

Eureka、ZooKeeper、Nacos、Consul 对比

  • Eureka 适用于服务实例数量不大的服务注册中心;
  • ZooKeeper 相对服务注册中心来说更适用于分布式协调服务;
  • Nacos 既适用于大量服务实例的服务注册中心,也可以作为配置中心;
  • Consul 更适用于 Service Mesh 架构,使用 Go 语言开发,不方便排查 Bug。

Ribbon-常见的负载均衡算法

  • 随机,通过随机选择服务进行执行,一般这种方式使用较少;
  • 轮训,负载均衡默认实现方式,请求来之后排队处理;
  • 加权轮训,通过对服务器性能的分型,给高配置,低负载的服务器分配更高的权重,均衡各个服务器的压力;
  • 地址Hash,通过客户端请求的地址的HASH值取模映射进行服务器调度;
  • 最小链接数,即使请求均衡了,压力不一定会均衡,最小连接数法就是根据服务器的情况,比如请求积压数等参数,将请求分配到当前压力最小的服务器上;

Ribbon原理图

img

Ribbon-饥饿加载

在进行服务调用的时候,如果网络情况不好,第一次调用会超时。Ribbon默认懒加载,初始化负载均衡器,意味着只有在发起调用的时候才会创建客户端。

开启饥饿加载,解决第一次调用慢的问题

# 开启ribbon饥饿加载
ribbon.eager-load.enabled=true
# 指定需要饥饿加载的客户端名称、服务名,多个使用逗号分隔
ribbon.eager-load.clients=server-order

nacos中的ribbon,以及2021版

nacos-discovery依赖了ribbon,可以不用再引入ribbon依赖。

在服务中添加配置,添加 @LoadBalanced 注解。

五、Spring Cloud Alibaba项目,Ribbon

Feign使用的一些配置

http配置

#feign 关闭 httpclient
feign.httpclient.enabled=false
#feign 使用 okhttp
feign.okhttp.enabled=true

压缩配置

# 开启配置
feign.compression.request.enabled=true
feign.compression.response.enabled=true
# 配置压缩类型
feign.compression.request.mime-types=text/xml,application/xml,application/json
# 最小压缩值
feign.compression.request.min-request-size=2048

注意:只有当 Feign 的 Http Client 不是 okhttp3 的时候,压缩才会生效,配置源码在FeignAcceptGzipEncodingAutoConfiguration

编解码配置:

# 对应的微服务"service-order"配置编解码器
feign.client.config.service-order.encoder=feign.jackson.JacksonEncoder
feign.client.config.service-order.decoder=feign.jackson.JacksonEncoder

六、Spring Cloud Alibaba项目,Feign

参考

图文解析 Nacos 配置中心的实现

SpringCloud-Nacos配置中心实现原理

Nacos 服务注册的原理

posted @ 2022-10-25 20:47  hongdada  阅读(381)  评论(0编辑  收藏  举报