枣庄市庄里水库建设管理处网站,展示设计网站有哪些,公司简介20 50字,网站域名管理Eureka学习笔记
服务端
模块设计 Resources #xff1a;这部分对外暴露了一系列的 Restful 接口。Eureka Client 的注册、心跳、获取服务列表等操作都需要调用这些接口。另外#xff0c;其他的 Server 在同步 Registry 时也需要调用这些接口。Controller #xff1a;这里提…Eureka学习笔记
服务端
模块设计 Resources 这部分对外暴露了一系列的 Restful 接口。Eureka Client 的注册、心跳、获取服务列表等操作都需要调用这些接口。另外其他的 Server 在同步 Registry 时也需要调用这些接口。Controller 这里提供了几个 web 接口主要用在 Eureka Server 本身的 Dashboard 页面 从页面上可以查看到当前注册了的服务以及每个服务下各个实例的状态。PeerAwareInstanceRegistry 这里面记录了当前所以注册了的服务实例。当这些注册信息发生变化时PeerAwareInstanceRegistry 还要负责把这些变化同步到其他的 Server。PeerEurekaNodes 这里维护了集群里所有 Eureka Server 节点的信息PeerAwareInstanceRegistry 在同步时需要从这里获取其他 Server 的信息。同时它还负责定时检查配置来发现是否有 Eureka Server 节点新增或删除。HttpReplicationClient 这是 PeerAwareInstanceRegistry 向其他 Server 同步时发送请求的 http client。
Resources
Eureka Service 的 Resource 是指处理 Eureka Server 提供的各类 RESTful API 的类主要负责与客户端和其他 Eureka Server 节点交互。包含以下几个重要的重要组成
ApplicationsResource提供全量或增量注册表的获取接口用于服务发现。ApplicationResource管理特定应用的操作如实例注册和删除。InstanceResource处理单个实例的操作如续约、状态更新和详细信息获取。PeerReplicationResource处理 Eureka Server 节点之间的数据复制请求保证注册表一致性。HealthCheckHandler定义实例健康检查逻辑决定实例的状态更新。EurekaServerResource提供当前 Eureka Server 的状态和配置信息。ClustersResource管理和查看 Eureka 集群的整体状态和节点信息。ServerCodecs定义注册表数据的编码和解码规则支持 JSON 和 XML 格式。
AbstractInstanceRegistry
register
其内部维护了一个如下的Map结构key为应用标识value同样是一个Map后者的key为单个应用实例的标识value为单个实例的详细信息被Lease包装了实例的租期信息
private final ConcurrentHashMapString, MapString, LeaseInstanceInfo registry new ConcurrentHashMapString, MapString, LeaseInstanceInfo();InstanceInfo
维护了引用实例的详细信息主要包含
instanceId实例的唯一标识符用于区分不同的服务实例。appName服务的逻辑名称便于服务分组和发现。vipAddress虚拟 IP 地址用于逻辑路由和客户端服务发现。status实例的当前运行状态如 UP、DOWN。lastDirtyTimestamp实例信息最后一次被修改的时间戳用于数据冲突判断。lastUpdatedTimestamp实例信息在服务端最后更新的时间戳用于跟踪本地状态。metadata实例的元数据存储额外的键值对信息供路由或分组使用。hostName实例的主机名用于标识和访问实例。ipAddr实例的 IP 地址用于实例的物理定位。leaseInfo与服务租约相关的信息如续约间隔和过期时间。isDirty标识实例信息是否处于“脏”状态用于触发更新。actionType标记实例操作类型添加、修改、删除以便同步。
其中lastDirtyTimestamp和lastUpdatedTimestamp看起来很相似实际上二者并不相同
二者对比如下
属性定义用途设置时机lastUpdatedTimestamp服务端记录实例信息最后更新时间服务端内部维护用于跟踪当前实例的更新情况由 Eureka Server 自动设置lastDirtyTimestamp客户端记录实例信息最后一次被修改时间戳数据冲突判断与同步传播表示数据的新旧状态由 Eureka Client 或服务端同步时设置
Lease
public class LeaseT {// 注册、下线、续期enum Action {Register, Cancel, Renew};// 默认驱逐时间public static final int DEFAULT_DURATION_IN_SECS 90;// 持有的应用实例的引用private T holder;// 被驱逐时间private long evictionTimestamp;// 服务注册时间private long registrationTimestamp;// 服务完全可用时间private long serviceUpTimestamp;// 最后续租时间private volatile long lastUpdateTimestamp;
}驱逐机制
我们可以看到每个实例都被Lease包装其中就记录着实例的注册时间registrationTimestamp以及最后续租时间lastUpdateTimestamp当实例没有在驱逐超时时间内完成续租将会被驱逐后者由定时任务EvictionTask来来完成
class EvictionTask extends TimerTask {private final AtomicLong lastExecutionNanosRef new AtomicLong(0l);Overridepublic void run() {try {long compensationTimeMs getCompensationTimeMs();logger.info(Running the evict task with compensationTime {}ms, compensationTimeMs);evict(compensationTimeMs);} catch (Throwable e) {logger.error(Could not run the evict task, e);}}
}PeerEurekaNodes
PeerEurekaNodes 是一个整体管理类内部包含多个 PeerEurekaNode 实例每个实例代表一个集群节点。
其中一个重要的功能便是定时同步集群的节点信息,这个任务由其start()法方法中的定时器完成
public void start() {...updatePeerEurekaNodes(resolvePeerUrls());...taskExecutor.scheduleWithFixedDelay(peersUpdateTask,serverConfig.getPeerEurekaNodesUpdateIntervalMs(),serverConfig.getPeerEurekaNodesUpdateIntervalMs(),TimeUnit.MILLISECONDS);...
}一致性设计
Eureka 是一个AP系统本身没有采用任何一种强一致性协议来保证系统整体的强一致性根据CAP定理一致性、可以用、分区可容忍性三者不可兼得Eureka选择放弃强注一致性来保证即使出现网络分区的情况下只要客户端可连接上任意一个客户端就可以正常运行。
不同的注册中心产品在一致性的选择上各有千秋常见的几款产品特性如下
EurekaAP系统 牺牲一致性没有使用严格的一致性协议。 最终一致性Eureka并不要求所有副本在每个时刻都保持一致。在分区恢复时Eureka会通过心跳和租约机制确保数据最终一致。 适用场景当系统需要高可用性并且可以容忍短时间的一致性问题时Eureka非常合适。 ConsulCP系统 提供强一致性并使用Raft协议来保证分布式系统的一致性。 强一致性Consul会确保在发生故障或网络分区时系统的一致性优先。它会牺牲系统的可用性确保所有的节点看到一致的数据。 适用场景当你需要确保服务注册中心中的数据在所有节点之间保持强一致性时Consul是一个较好的选择。
ZookeeperCP系统 提供强一致性并使用ZAB协议Zookeeper Atomic Broadcast来保证一致性。 强一致性Zookeeper通过分布式共识协议确保数据一致性因此它在面对网络分区时会牺牲部分可用性。它适用于需要强一致性和协调的应用。 适用场景在需要强一致性的分布式系统中例如分布式锁、配置管理等Zookeeper是一个合适的选项。 NacosAP/CP系统灵活配置 灵活的可选一致性策略Nacos可以根据配置调整一致性级别支持AP模式和CP模式。 最终一致性或强一致性可以通过配置Raft协议来实现一致性保障。默认情况下Nacos更多的是追求可用性和分区容忍性但它也支持强一致性模式。 适用场景Nacos适用于需要灵活选择一致性策略的场景既支持最终一致性也能在特定场景下实现强一致性。
EtcdCP系统
提供强一致性并使用Raft协议保证数据一致性。强一致性Etcd优先考虑一致性在网络分区或节点故障时它会保持一致性并且牺牲部分可用性。适用场景当分布式系统对一致性要求非常高时Etcd是非常合适的。它常用于服务发现、配置管理和分布式协调等场景。
同步数据设计
数据同步的关键技术要点
REST APIEureka集群通过HTTP REST API进行节点间的通信与数据同步。每个Eureka节点向其他节点推送自己更新的服务信息。PeerAwareReplication该机制是Eureka集群的核心负责将服务注册信息在节点之间进行复制。每个节点知道其他节点的存在并能够主动或被动地同步服务数据。心跳和租约机制服务实例通过发送心跳请求来续约租约确保服务实例不会因未能及时续约而被误删。租约过期的信息也会在节点间同步。最终一致性Eureka采用最终一致性模型而不是强一致性。在网络分区或节点故障时系统可以继续运行但在恢复后系统会进行数据同步直到一致性最终达成。
主动同步
触发条件
Eureka节点会在服务注册、续约、注销等事件发生时主动将变化的信息推送到其他节点。
PeerAwareInstanceRegistryImpl#replicateToPeers()
private void replicateToPeers(Action action, String appName, String id,InstanceInfo info /* optional */,InstanceStatus newStatus /* optional */, boolean isReplication) {Stopwatch tracer action.getTimer().start();try {// 是否是一个复制请求if (isReplication) {numberOfReplicationsLastMin.increment();}...for (final PeerEurekaNode node : peerEurekaNodes.getPeerEurekaNodes()) {// 是否来自自身如何是则跳过if (peerEurekaNodes.isThisMyUrl(node.getServiceUrl())) {continue;}// 复制同步到对等节点replicateInstanceActionsToPeers(action, appName, id, info, newStatus, node);}} finally {tracer.stop();}
}private void replicateInstanceActionsToPeers(Action action, String appName,String id, InstanceInfo info, InstanceStatus newStatus,PeerEurekaNode node) {...switch (action) {case Cancel:node.cancel(appName, id);break;case Heartbeat:InstanceStatus overriddenStatus overriddenInstanceStatusMap.get(id);infoFromRegistry getInstanceByAppAndId(appName, id, false);node.heartbeat(appName, id, infoFromRegistry, overriddenStatus, false);break;case Register:node.register(info);break;...
}工作流程 被动同步
触发条件
被动同步机制通常在以下情况下触发
节点启动时Eureka节点启动后需要与其他节点同步当前服务注册表。节点恢复时节点在网络分区、宕机等故障恢复后为确保数据完整性会从其他节点拉取最新数据。
工作流程 DiscoveryClient#getAndStoreFullRegistry()
private void getAndStoreFullRegistry() throws Throwable {long currentUpdateGeneration fetchRegistryGeneration.get();logger.info(Getting all instance registry info from the eureka server);// 从其他Eureka Service 获取ApplicationsApplications apps null;EurekaHttpResponseApplications httpResponse clientConfig.getRegistryRefreshSingleVipAddress() null? eurekaTransport.queryClient.getApplications(remoteRegionsRef.get()): eurekaTransport.queryClient.getVip(clientConfig.getRegistryRefreshSingleVipAddress(), remoteRegionsRef.get());if (httpResponse.getStatusCode() Status.OK.getStatusCode()) {apps httpResponse.getEntity();}...localRegionApps.set(this.filterAndShuffle(apps));
}private Applications filterAndShuffle(Applications apps) {if (apps ! null) {...if (isFetchingRemoteRegionRegistries()) {MapString, Applications remoteRegionVsApps new ConcurrentHashMapString, Applications();apps.shuffleAndIndexInstances(remoteRegionVsApps, clientConfig, instanceRegionChecker);for (Applications applications : remoteRegionVsApps.values()) {applications.shuffleInstances(clientConfig.shouldFilterOnlyUpInstances());}}...}
}我们可以看到之类有一个shuffle的操作即对应用服务的实例做一个随机的打算主要是为了使得每个服务接收的流量更为均匀同时也是避免新服务启动时出现雪崩现象。