一致性(Consistency) (所有节点在同一时间具有相同的数据) 可用性(Availability) (保证每个请求不管成功或者失败都有响应) 分隔容忍(Partition tolerance) (系统中任意信息的丢失或失败不会影响系统的继续运作)
1.注册中心: 节点是平等的,通过异步 Replicate 来同步数据,达到最终一致。注册中心拥有两级缓存。 2.客户端: 本地缓存有服务注册的全量信息(即使与注册中心断开也可向服务方请求), 某个注册中节点挂了可自动切换注册中心其它节点。
1、启动注册中心: 集群间定时通过 Replicate 同步注册表,每个 EurekaServer(注册中心) 都有完整的服务注册表信息。
2、客户端向注册中心发起注册: Client 启动时根据配置的 EurekaServer 地址去注册中心注册服务,提供自身的元数据,比如 IP 地址、端口,运行状况指示符 URL,主页等。
3、客户端定时发生心跳检测: Client 会每 30s 向 EurekaServer 发送一次心跳请求,证明客户端服务正常。
4、服务端服务剔除: 当 EurekaServer 90s 内没有收到 Client 的心跳,注册中心则认为该节点失效,会注销该实例。
5、注册中心自我保护: 单位时间内 Eureka Server 统计到有大量的 Client 没有上送心跳,进入自我保护机制,不再剔除没有上送心跳的客户端。
6、注册中心退出自我保护: 当 Eureka Client 心跳请求恢复正常之后,Eureka Server 自动退出自我保护模式。
7、客户端整合服务发现: 定时全量或者增量从注册中心获取服务注册表,并且将获取到的信息缓存到本地。
8、服务调用时: Client 先从本地缓存找寻调取的服务。获取不到,从注册中心刷新注册表,再同步到本地缓存。
9、Client获取到目标服务器信息,发起服务调用。
10、服务端下线: Client 程序关闭(DiscoveryManager.getInstance().shutdownComponent()),向 EurekaServer 发送取消请求,注册中心将实例从注册表中删除。
总结
1、Eureka Server启动时会做两件事:
1.初始化读写缓存(二级缓存),从注册表registry(一级缓存)中实时加载数据,默认180s过期;
2.判定是否使用只读缓存(三级缓存),默认开启;如果使用则开启一个定时任务,默认每30s做一次读写缓存到只读缓存的数据同步;
2、Eureka Server 在接收Client注册的时候,将读写缓存(二级缓存)清空;
3、Eureka Client获取服务信息时,默认先从只读缓存获取;获取不到再从读写缓存中获取,并将数据缓存到只读缓存;获取不到,再触发guava的回调函数从注册表中同步(即从一级缓存 – 注册表registry中取)。
Eureka Server中有三个变量用来保存服务注册信息,分别是:registry、readWriteCacheMap、readOnlyCacheMap
为了尽可能的避免服务注册出现频繁的读写冲突,写阻塞读。提高Eureka Server服务的读写性能。
1.一级缓存: registry, ConcurrentHashMap类型。实时更新,又名注册表,UI界面从这里获取服务注册信息;
2.二级缓存(读写缓存): readWriteCacheMap, GuavaCache类型。实时更新,缓存时间180秒;
3.三级缓存(只读缓存): readOnlyCacheMap, ConcurrentHashMap类型。默认每30s从二级缓存readWriteCacheMap中同步数据更新。Eureka Client默认从这里获取服务注册信息,可配为直接从readWriteCacheMap获取。
通信用gRPC机制,默认为AP模式,可切换为CP模式。
切换为CP模式
curl -X PUT "http://localhost:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP"
切换为AP模式
curl -X PUT "http://localhost:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=AP"
服务注册: NacosClient会通过发送REST请求的方式向NacosServer注册自己的服务,提供自身的元数据,比如ip地址、端口等信息。NacosServer接收到注册请求后,就会把这些元数据信息存储在一个双层的内存Map中。 服务心跳: 在服务注册后,NacosClient会维护一个定时心跳来持续通知NacosServer,说明服务一直处于可用状态,防止被剔除。默认5s发送一次心跳。 服务同步: NacosServer集群之间会互相同步服务实例,用来保证服务信息的一致性。 服务发现: 服务消费者(Nacos Client)在调用服务提供者的服务时,会发送一个REST请求给NacosServer,获取上面注册的服务清单,并且缓存在NacosClient本地,同时会在NacosClient本地开启一个定时任务定时拉取服务端最新的注册表信息更新到本地缓存。 服务健康检查: NacosServer会开启一个定时任务用来检查注册服务实例的健康情况,对于超过15s没有收到客户端心跳的实例会将它的healthy属性置为false(客户端服务发现时不会发现),如果某个实例超过30秒没有收到心跳,直接剔除该实例(被剔除的实例如果恢复发送心跳则会重新注册)。 Nacos注册概括来说有6个步骤: 1、服务容器负责启动,加载,运行服务提供者。 2、服务提供者在启动时,向注册中心注册自己提供的服务。 3、服务消费者在启动时,向注册中心订阅自己所需的服务。 4、注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。 5、服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。 6、服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
Group——>Service——>Cluster——>Instance
// ServiceManager类,Map(namespace, Map(group::serviceName, Service))
private final Map> serviceMap = new ConcurrentHashMap<>();
// Service类,Map(cluster,Cluster)
private Map clusterMap = new HashMap<>();
// Cluster类
private Set persistentInstances = new HashSet<>();
private Set ephemeralInstances = new HashSet<>();
// Instance类
private String instanceId;
private String ip;
private int port;
private double weight = 1.0D;
短连接的操作步骤是: 建立连接——数据传输——关闭连接...建立连接——数据传输——关闭连接 长连接的操作步骤是: 建立连接——数据传输...(保持连接)...数据传输——关闭连接
HTTP的长连接和短连接本质上是TCP长连接和短连接。HTTP/2基于UDP协议的,采用二进制的方式传输(与文本格式的json相比,二进制格式的protobuf在速度上是前者的5倍)
两台服务器上进程间通过网络调用函数、传递信息。
RPC 是一种流行的进程间通信技术,用于构建客户端-服务器应用程序。建立在长连接方式的TCP通信协议上。HTTP也是RPC实现的一种方式,与HTTP不同的是在协议层面RPC定义了每个消息的唯一id,可以更容易的复用连接。
RPC 的组件
1.RpcServer
负责导出(export)远程接口
2.RpcClient
负责导入(import)远程接口的代理实现
3.RpcProxy
远程接口的代理实现
4.RpcInvoker
客户方实现:负责编码调用信息和发送调用请求到服务方并等待调用结果返回
服务方实现:负责调用服务端接口的具体实现并返回调用结果
5.RpcProtocol
负责协议编/解码
6.RpcConnector
负责维持客户方和服务方的连接通道和发送数据到服务方
7.RpcAcceptor
负责接收客户方请求并返回请求结果
8.RpcProcessor
负责在服务方控制调用过程,包括管理调用线程池、超时时间等
9.RpcChannel
数据传输通道
Google 发起的开源远程过程调用系统。
基于 HTTP/2 协议传输,HTTP/2基于UDP协议的,采用二进制的方式传输(与文本格式的json相比,二进制格式的protobuf在速度上是前者的5倍)。通过算法保证可靠性传输,天然支持并行传输,性能有大幅提升。
为了减少网络流量的对消息进行头部压缩。多路复用,支持通过同一个连接发送多个并发的请求。
gRPC的开发核心是*.proto文件,它定义了gRPC服务和消息的约定。根据这个文件,gRP框架将生成服务基类,消息和完整的客户端代码。
gRPC大致请求流程
1.客户端(gRPC Stub)调用A方法,发起RPC调用
2.对请求信息使用Protobuf进行对象序列化压缩(IDL)
3.服务端(gPRC Server)接收到请求后,解码请求体,进行业务逻辑处理并返回。
4.对响应结果使用Protobuf进行对象序列化压缩(IDL)
5.客户端接受到服务端响应,解码请求体。回调被调用的A方法,唤醒正在等待响应(阻塞)的客户端调用并返回响应结果