Eureka 学习笔记5:InstanceRegistry
版本 awsVersion = ‘1.11.277’

LeaseManager 接口管理实例的租约信息,提供以下功能:
- 注册实例
- 取消注册实例
- 实例续约
- 剔除过期实例
public interface LeaseManager<T> {/** 注册实例并续约*/void register(T r, int leaseDuration, boolean isReplication);/*** 取消注册实例*/boolean cancel(String appName, String id, boolean isReplication);/*** 续约*/boolean renew(String appName, String id, boolean isReplication);/*** 剔除过期实例*/void evict();
}
InstanceRegistry 接口即注册表服务,继承 LeaseManager 接口,提供以下功能:
- 启动和关闭注册表服务
- 更新注册表中实例的状态
- 从注册表中获取应用信息和实例信息
- 初始化和获取注册表缓存
- 租约过期机制和自我保护机制(和 LeaseManager 的 evict() 方法相关)
public interface InstanceRegistry extends LeaseManager<InstanceInfo>, LookupService<String> {// ========================// 启动和关闭注册表服务// ========================/*** 在PeerAwareInstanceRegistry接口的init()和syncUp()方法调用后被调用* 1.更新expectedNumberOfClientsSendingRenews* 更新numberOfRenewsPerMinThreshold* 2.如果从其他Eureka节点拉取注册表成功并且实例数量大于0* 设置peerInstancesTransferEmptyOnStartup为false* 和PeerAwareInstanceRegistry接口的shouldAllowAccess()方法相关* 3.设置startupTime为当前时间* 4.设置自身实例状态为InstanceStatus.UP* 5.调用postInit()方法* 创建EvictionTask并通过Timer调度定时剔除过期实例* 配置evictionIntervalTimerInMs指定剔除过期实例的时间间隔,默认60s*/void openForTraffic(ApplicationInfoManager applicationInfoManager, int count);void shutdown();// ========================// 更新注册表中实例的状态// ========================@Deprecatedvoid storeOverriddenStatusIfRequired(String id, InstanceStatus overriddenStatus);/*** 更新注册表中实例的overriddenStatus*/void storeOverriddenStatusIfRequired(String appName, String id, InstanceStatus overriddenStatus);/*** 更新注册表中实例的overriddenStatus和status*/boolean statusUpdate(String appName,String id,InstanceStatus newStatus,String lastDirtyTimestamp,boolean isReplication);/*** 删除注册表中实例的overriddenStatus并设置status*/boolean deleteStatusOverride(String appName,String id,InstanceStatus newStatus,String lastDirtyTimestamp,boolean isReplication);/*** 获取注册表中overriddenStatus集合的快照*/Map<String, InstanceStatus> overriddenInstanceStatusesSnapshot();// ========================// 注册表 CRUD// ========================/*** 获取本地注册表*/Applications getApplicationsFromLocalRegionOnly();/*** 根据应用名称从本地注册表或其他region的注册表中获取应用信息*/Application getApplication(String appName, boolean includeRemoteRegion);/*** 根据应用名称和实例id从本地注册表或其他region的注册表中获取实例信息*/InstanceInfo getInstanceByAppAndId(String appName, String id);/*** 根据应用名称和实例id从本地注册表或其他region的注册表中获取实例信息*/InstanceInfo getInstanceByAppAndId(String appName, String id, boolean includeRemoteRegions);/*** 清空注册表*/void clearRegistry();// ========================// 注册表缓存// ========================/*** 初始化注册表缓存ResponseCacheImpl*/void initializedResponseCache();/*** 获取注册表缓存ResponseCacheImpl*/ResponseCache getResponseCache();// ========================// 租约过期机制&自我保护机制// ========================/*** 获取上一分钟收到的续约(renew)请求数*/long getNumOfRenewsInLastMin();/*** 获取每一分钟续约(renew)请求数的阈值* 如果上一分钟收到的续约请求数小于阈值,开启自我保护机制* 计算方式:实例数量 * (60 / 续约间隔时间)* 续约百分比阈值0.85* this.expectedNumberOfClientsSendingRenews * * (60.0 / serverConfig.getExpectedClientRenewalIntervalSeconds()) ** serverConfig.getRenewalPercentThreshold())*/int getNumOfRenewsPerMinThreshold();/*** 是否启用租约过期机制*/boolean isLeaseExpirationEnabled();/*** 是否启用自我保护机制*/boolean isSelfPreservationModeEnabled();
}
Map<String, RemoteRegionRegistry> regionNameVSRemoteRegistry 是 AbstractInstanceRegistry 抽象类的成员变量,key 是 remoteRegionUrlsWithName 配置中的 regionName,value 则是 initRemoteRegionRegistry() 方法中创建的RemoteRegionRegistry 对象。
// 配置remoteRegionUrlsWithName
regionName1;regionUrl1,regionName2;regionUrl2...
RemoteRegionRegistry 类表示其他区域的注册表信息,配置 remoteRegion.registryFetchIntervalInSeconds 指定从其他区域拉取注册表信息的间隔时间,默认 30s。
拉取成功后,将 readyForServingData 设置为 true,表示该区域的注册表已经可以提供服务。
Runnable remoteRegionFetchTask = new Runnable() {@Overridepublic void run() {try {if (fetchRegistry()) {readyForServingData = true;} else {logger.warn("Failed to fetch remote registry. " +"This means this eureka server " + "is not ready for serving traffic.");}}}
};scheduler.schedule(new TimedSupervisorTask("RemoteRegionFetch_" + regionName,scheduler,remoteRegionFetchExecutor,// 配置remoteRegion.registryFetchIntervalInSecondsserverConfig.getRemoteRegionRegistryFetchInterval(),TimeUnit.SECONDS,5, // exponential backoff boundremoteRegionFetchTask),serverConfig.getRemoteRegionRegistryFetchInterval(),TimeUnit.SECONDS);
remoteRegion.global.appWhiteList 和 remoteRegion.{regionName}.appWhiteList 配置全局和 regionName 指定区域的拉取白名单,appName 不在白名单中的应用信息是无法拉取的。
PeerAwareInstanceRegistry 接口继承 InstanceRegistry 接口,提供以下功能:
public interface PeerAwareInstanceRegistry extends InstanceRegistry {/*** 初始化PeerAwareInstanceRegistryImpl,包括:* 1.实例化注册表缓存ResponseCacheImpl* 2.创建定时任务,定时更新numberOfRenewsPerMinThreshold* 配置renewalThresholdUpdateIntervalMs* 指定更新numberOfRenewsPerMinThreshold的时间间隔,默认15min* 3.初始化其他区域注册表regionNameVSRemoteRegistry*/void init(PeerEurekaNodes peerEurekaNodes) throws Exception;/*** 是否可以对外提供注册表服务* 1.如果在调用openForTraffic方法时* 从其他Eureka节点拉取注册表失败则返回false* 2.如果remoteRegionRequired为true* 还需要等待其他区域注册表全部拉取成功后才返回true*/boolean shouldAllowAccess(boolean remoteRegionRequired);/*** 从其他Eureka节点拉取注册表信息*/int syncUp();/*** 注册实例信息*/void register(InstanceInfo info, boolean isReplication);void statusUpdate(final String asgName,final ASGResource.ASGStatus newStatus,final boolean isReplication);
}
注:在 LeaseManager 接口中已经声明了 register(T r, int leaseDuration, boolean isReplication) 方法的前提下,为什么在 PeerAwareInstanceRegistry 接口中再次声明 register(InstanceInfo info, boolean isReplication) 方法呢?原来 register(InstanceInfo info, boolean isReplication) 方法是在 syncUp() 方法中被调用,是将从其他 Eureka 节点拉取过来的注册表中的实例信息注册到本地注册表中。
// com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl
public int syncUp() {// 统计从其他Eureka节点同步过来的实例信息数量int count = 0;// ...// 从其他Eureka节点拉取注册表信息Applications apps = eurekaClient.getApplications();for (Application app : apps.getRegisteredApplications()) {for (InstanceInfo instance : app.getInstances()) {// ...// 判断该实例的availabilityZone是否和当前Eureka节点属于同一个region// 如果是,则将该实例注册到本地注册表if (isRegisterable(instance)) {register(instance,instance.getLeaseInfo().getDurationInSecs(),true);count++;}} }// ...return count;
}
PeerAwareInstanceRegistryImpl 类构造方法和 init 方法代码如下:
@Singleton
public class PeerAwareInstanceRegistryImplextends AbstractInstanceRegistryimplements PeerAwareInstanceRegistry {// startupTime、peerInstancesTransferEmptyOnStartup// 在openForTraffic方法被调用时赋值private long startupTime = 0;private boolean peerInstancesTransferEmptyOnStartup = true;// peerEurekaNodes在init方法被调用时赋值protected volatile PeerEurekaNodes peerEurekaNodes;// eurekaClient在构造方法被调用时赋值protected final EurekaClient eurekaClient;// instanceStatusOverrideRule在构造方法被调用时赋值private final InstanceStatusOverrideRule instanceStatusOverrideRule;// 定时调用updateRenewalThreshold方法private Timer timer = new Timer("ReplicaAwareInstanceRegistry - RenewalThresholdUpdater", true);@Injectpublic PeerAwareInstanceRegistryImpl(EurekaServerConfig serverConfig,EurekaClientConfig clientConfig,ServerCodecs serverCodecs,EurekaClient eurekaClient) {super(serverConfig, clientConfig, serverCodecs);this.eurekaClient = eurekaClient;this.numberOfReplicationsLastMin = new MeasuredRate(1000 * 60 * 1);// We first check if the instance is STARTING or DOWN,// then we check explicit overrides,// then we check the status of a potentially existing lease.this.instanceStatusOverrideRule =new FirstMatchWinsCompositeRule(new DownOrStartingRule(),new OverrideExistsRule(overriddenInstanceStatusMap),new LeaseExistsRule());}@Overridepublic void init(PeerEurekaNodes peerEurekaNodes) throws Exception {// 1.统计每分钟和其他Eureka节点的同步频率this.numberOfReplicationsLastMin.start();// 2.赋值peerEurekaNodes属性,保存Eureka集群节点信息this.peerEurekaNodes = peerEurekaNodes;// 3.创建本地注册表缓存ResponseCacheImplinitializedResponseCache();// 4.创建TimerTask,通过Timer调度updateRenewalThreshold方法// 定时更新numberOfRenewsPerMinThresholdscheduleRenewalThresholdUpdateTask();// 5.创建其他区域的注册表RemoteRegionRegistryinitRemoteRegionRegistry();// ...}
}
-
实现了
PeerAwareInstanceRegistry接口,通过eurekaClient 属性获得了从其他 Eureka 节点拉取注册表(PeerAwareInstanceRegistry#syncUp()方法)的能力, -
通过
peerEurekaNodes 属性获得了将本地注册表的更新同步给其他 Eureka 节点(PeerAwareInstanceRegistryImpl#replicateToPeers()方法)的能力
注:为什么不将 Eureka 节点之间同步更新数据的操作和拉取注册表的操作一起声明在 PeerAwareInstanceRegistry 接口中,而是另外通过 PeerEurekaNode 类去实现呢?
既然 numberOfRenewsPerMinThreshold 是通过实例数量实时计算为什么不将 numberOfRenewsPerMinThreshold 属性声明在 PeerAwareInstanceRegistryImpl 类中,而是声明在父类 AbstractInstanceRegistry 中?
instanceStatusOverrideRule 根据规则计算实例的
相关文章:
Eureka 学习笔记5:InstanceRegistry
版本 awsVersion ‘1.11.277’ LeaseManager 接口管理实例的租约信息,提供以下功能: 注册实例取消注册实例实例续约剔除过期实例 public interface LeaseManager<T> {/** 注册实例并续约*/void register(T r, int leaseDuration, boolean isRep…...
System Verilog——虚方法的使用
1、使用虚方法目的 通过在父类里定义虚方法(task or function),可以在当父类句柄调用一个方法时候,前提是若是这个句柄指向了子类对象,则调用的方法为子类的方法而不是父类的方法。 1.1、实例理解:将子类句柄赋值成父类句柄 mod…...
线性规划和单纯形法-原理篇
文章目录 引言线性规划标准型问题特点单纯形法 引言 很多运筹学的教材都是从线性规划开始的,我平时做算法策略的落地应用时也研发了一部分基于线性规划的技术方案。可以说,如果搞不懂线性规划,很难成为一名优秀的运筹优化算法工程师。 但是…...
FBX SDK开发快速上手指南
一段时间以来,我一直想制作一个 FBX Exporter 将 FBX 文件转换为我自己的格式。 整个过程不是很顺利,主要是FBX的官方文档不是很清楚。 另外,由于 FBX 格式被许多应用程序使用,而不仅仅是游戏引擎,因此提供的示例代码没…...
探讨|使用或不使用机器学习
动动发财的小手,点个赞吧! 机器学习擅长解决某些复杂问题,通常涉及特征和结果之间的困难关系,这些关系不能轻易地硬编码为启发式或 if-else 语句。然而,在决定 ML 是否是当前给定问题的良好解决方案时,有一…...
Git笔记--Ubuntu上传本地项目到github
目录 1--基本配置 2--本地上传 1--基本配置 ① 创建ssh-key cd ~/.sshssh-keygen -t rsa -C "邮箱地址"② 查看并关联ssh-key gedit id_rsa.pub 复制内容,在 GitHub 中依次点击 Settings -> SSH and GPG keys -> New SSH key,将 id…...
基于Go编写一个可视化Navicat本地密码解析器
前提 开发小组在测试环境基于docker构建和迁移一个MySQL8.x实例,过程中大意没有记录对应的用户密码,然后发现某开发同事本地Navicat记录了根用户,于是搜索是否能够反解析Navicat中的密码掩码(这里可以基本断定Navicat对密码是采用…...
Maven【入门笔记】
Maven 解决版本依赖的问题 https://www.liaoxuefeng.com/wiki/1252599548343744/1309301146648610 如果没有项目管理工具,在开发项目的时候,我们需要手动管理依赖包,需要管理依赖包的版本、去找到并下载依赖包、还有依赖包所依赖的包 等等。…...
Android Studio中使用cmake开发JNI实战
JNI学习大纲 一、JNI编程入门 二、Android Studio中使用cmake开发JNI实战 第一章节我们介绍了JNI的开发步骤,那这一章节我们就开始在Android Studio中实战一下吧,Lets Start。 1. Android Studio中安装CMake插件 AS中菜单栏选择Tools>SDK Manager在…...
第七章 图论
第七章 图论 一、数据结构定义 图的邻接矩阵存储法#define MaxVertexNum 100 // 节点数目的最大值// 无边权,只用0或1表示边是否存在 bool graph[MaxVertexNum][MaxVertexNum];// 有边权 int graph[MaxVertexNum][MaxVertexNum];图的邻接表存储法 把所有节点存储为…...
IEEE SystemVerilog Chapter13 : Tasks and functions (subroutines)
13.2 Overview 任务和函数提供了从描述中的几个不同位置执行通用过程的能力。它们还提供了一种将大型过程分解为小型过程的方法,以便更容易地阅读和调试源代码描述。本小节讨论了任务和函数之间的区别,描述了如何定义和调用任务和函数,并给出…...
day39反转字符串总结
反转字符串原理其实就是交换位置,以中间为分隔点; 基本套路:遍历前一般字符,互换位置; for循环模板 void reverseString(char* s, int sSize){char temp;for (int i 0, j sSize - 1; i < sSize/2; i, j--) {temp…...
使用Socket实现TCP版的回显服务器
文章目录 1. Socket简介2. ServerSocket3. Socket4. 服务器端代码5. 客户端代码 1. Socket简介 Socket(Java套接字)是Java编程语言提供的一组类和接口,用于实现网络通信。它基于Socket编程接口,提供了一种简单而强大的方式来实现…...
【Nacos篇】Nacos基本操作及配置
官方文档:https://nacos.io/zh-cn/docs/v2/ecology/use-nacos-with-spring-cloud.html 前置条件:SpringCloud脚手架 单机模式下的Nacos控制台: <dependencies><!-- Registry 注册中心相关 --><dependency><groupId>…...
Dockerfile构建Tomcat镜像
准备apache包和jdk并解压 [rootlocalhost tomcat]# ll 总用量 196728 -rw-r--r--. 1 root root 9690027 7月 17 2020 apache-tomcat-8.5.40.tar.gz -rw-r--r--. 1 root root 674 8月 2 20:19 Dockerfile -rw-r--r--. 1 root root 191753373 7月 17 2020 jdk-8u191-…...
k8s的介绍
简介 Kubernetes,简称K8s,是用8代替名字中间的8个字符“ubernete”而成的缩写。是一个开源的,用于管理云平台中多个主机上的容器化的应用, K8s的目标是让部署容器化的应用简单并且高效,K8s提供了应用部署,规划,更新,维护的一种机制。 K8s是Google开源的一个容器编排引…...
mysql sql语句 需要使用like 场景,解决方案
mysql 多重like 解决方案 方案一、使用like 方案二、使用REGEXP 正则匹配 方案三、使用group_concat多重模糊匹配 方案一、使用like 查询user包含小李并且小王的相关数据 SELECT * FROM user WHERE name LIKE %小王% or name like %小王% 方案二、使用REGEXP 正则匹配 查询use…...
通过C语言设计的贪吃蛇游戏(控制台终端)
一、项目介绍 当前通过控制台终端实现一个贪吃蛇小游戏,实现游戏的绘制、更新、控制等功能。 二、实现效果 三、完整代码 下面贴出的代码在Windows系统上编译运行,需要使用conio.h头文件中的getch()函数来获取键盘输入,用于控制蛇的移动。…...
c++实现Qt信号和槽机制
文章目录 简介信号槽信号与槽的连接 特点观察者模式定义观察者模式结构图 实现简单的信号和槽 简介 信号槽机制与Windows下消息机制类似,消息机制是基于回调函数,Qt中用信号与槽来代替函数指针,使程序更安全简洁。 信号和槽机制是 Qt 的核心…...
【Linux】五、进程
一、冯诺依曼体系结构 存储器:指的是内存; 输入设备:键盘、摄像头、话筒,磁盘,网卡; 输出设备:显示器、音响、磁盘、网卡; 中央处理器(CPU):运算器…...
手把手教你用HuggingFace+BGE模型搭建本地向量检索系统(附FAISS实战代码)
从零构建基于BGE模型的本地语义搜索系统:代码级实践指南 在信息爆炸的时代,如何快速从海量文本中精准找到相关内容?语义搜索技术正成为解决这一痛点的利器。不同于传统的关键词匹配,语义搜索能理解查询背后的意图,找到…...
PETRV2-BEV模型训练实战:基于星图AI算力平台的完整流程解析
PETRV2-BEV模型训练实战:基于星图AI算力平台的完整流程解析 1. 环境准备与基础配置 1.1 创建并激活conda环境 首先我们需要创建一个专用的conda环境来管理项目依赖。推荐使用Python 3.8版本: conda create -n paddle3d_env python3.8 conda activate…...
C语言宏定义:嵌入式开发中的高效利器与避坑指南
1. C语言宏定义的基础与陷阱在嵌入式开发中,宏定义是C语言最强大的特性之一,但也是最容易踩坑的特性。让我们从一个简单的需求开始:如何用宏实现两个数的比较并返回较小值?初学者最常见的写法是这样的:#define MIN(a,b…...
仅剩127天!Python 3.14+原生AOT将成标准解释器默认后端:企业级迁移路线图与兼容性断点预警
第一章:Python 原生 AOT 编译方案 2026 生产环境部署全景概览Python 原生 AOT(Ahead-of-Time)编译在 2026 年已进入成熟商用阶段,核心由 CPython 官方主导的 cpython-aot 工具链与 PEP 718 所定义的字节码预优化规范共同支撑。该方…...
终端设置显示项目的分支名
function parse_git_branch() {git branch 2> /dev/null | sed -n -e s/^\* \(.*\)/[\1]/p}setopt PROMPT_SUBSTexport PROMPT%F{grey}%n%f %F{green}$(parse_git_branch)%f %F{normal}$%f 在.zshrc中设置以上即可...
人工智能应用快速原型开发:基于PyTorch 2.8和Gradio构建交互式Demo
人工智能应用快速原型开发:基于PyTorch 2.8和Gradio构建交互式Demo 1. 为什么需要快速原型开发工具 在人工智能领域,一个好想法从诞生到落地往往需要经历漫长的验证过程。传统方式下,即使训练出了一个效果不错的模型,想要展示给…...
ISOLAR-B系统配置实战:如何将DBC文件信号正确映射到SWC Port(CAN网络示例)
ISOLAR-B系统配置实战:DBC信号与SWC Port的精准映射指南 当你在AUTOSAR开发中完成应用层SWC设计后,最令人头疼的莫过于如何让这些精心设计的组件与真实的ECU网络信号"对话"。ISOLAR-B作为BSW配置的核心工具,其系统级配置能力直接决…...
ECDH算法避坑指南:OpenSSL和Node.js中的椭圆曲线参数选择
ECDH算法实战避坑指南:跨平台椭圆曲线参数选择与性能优化 在构建现代加密通信系统时,ECDH(椭圆曲线迪菲-赫尔曼密钥交换)算法因其高效性和安全性已成为TLS协议栈的核心组件。然而,当开发者需要在OpenSSL和Node.js等不同…...
PDF-Parser-1.0效果实测:中文识别超99%,表格公式完美提取
PDF-Parser-1.0效果实测:中文识别超99%,表格公式完美提取 1. 开篇实测体验 当我第一次使用PDF-Parser-1.0处理一份15页的技术文档时,结果让我感到惊讶。这份文档包含复杂的中英文混排内容、3个跨页表格和5个数学公式,传统OCR工具…...
MySQL高频面试题(2026最新版):覆盖90%考点,小白也能直接背
很多开发者备考时,要么盲目刷题、记不住重点,要么只背答案、不懂原理,面试时被面试官追问一句就卡壳。其实MySQL面试没有那么复杂,核心考点就那么多,只要吃透高频题、理解底层逻辑,就能从容应对。本文整理了…...
