Eureka的InstanceInfoReplicator类(服务注册辅助工具)
关于服务注册
以下图片来自Netflix官方,图中显示Eureka Client会向注册中心发起Get Registry请求来获取服务列表:
以Spring Cloud的Edgware.RELEASE版本为例,Eureka client的注册动作是在com.netflix.discovery.DiscoveryClient类的initScheduledTasks方法中执行的,相关代码片段如下所示,请注意中文注释:
//略去不相关代码
...
//实例化InstanceInfoReplicator对象
instanceInfoReplicator = new InstanceInfoReplicator(this,instanceInfo,clientConfig.getInstanceInfoReplicationIntervalSeconds(),2); // burstSize//监听器,用来监听作为Eureka client的自身的状态变化statusChangeListener = new ApplicationInfoManager.StatusChangeListener() {@Overridepublic String getId() {return "statusChangeListener";}@Overridepublic void notify(StatusChangeEvent statusChangeEvent) {if (InstanceStatus.DOWN == statusChangeEvent.getStatus() ||InstanceStatus.DOWN == statusChangeEvent.getPreviousStatus()) {// log at warn level if DOWN was involvedlogger.warn("Saw local status change event {}", statusChangeEvent);} else {logger.info("Saw local status change event {}", statusChangeEvent);}//状态变化时notify方法会被执行,此时上报最新状态到Eureka serverinstanceInfoReplicator.onDemandUpdate();}};if (clientConfig.shouldOnDemandUpdateStatusChange()) {//注册监听器applicationInfoManager.registerStatusChangeListener(statusChangeListener);}//服务注册instanceInfoReplicator.start(clientConfig.getInitialInstanceInfoReplicationIntervalSeconds());
上述代码表明,将自身信息上报到Eureka server的工作是通过调用instanceInfoReplicator的api完成的;
InstanceInfoReplicator的作用
先看InstanceInfoReplicator源码的注释:
/*** A task for updating and replicating the local instanceinfo to the remote server. Properties of this task are:* - configured with a single update thread to guarantee sequential update to the remote server* - update tasks can be scheduled on-demand via onDemandUpdate()* - task processing is rate limited by burstSize* - a new update task is always scheduled automatically after an earlier update task. However if an on-demand task* is started, the scheduled automatic update task is discarded (and a new one will be scheduled after the new* on-demand update).** @author dliu*/
我的理解:
- InstanceInfoReplicator是个任务类,负责将自身的信息周期性的上报到Eureka server;
- 有两个场景触发上报:周期性任务、服务状态变化(onDemandUpdate被调用),因此,在同一时刻有可能有两个上报的任务同时出现;
- 单线程执行上报的操作,如果有多个上报任务,也能确保是串行的;
- 有频率限制,通过burstSize参数来控制;
- 先创建的任务总是先执行,但是onDemandUpdate方法中创建的任务会将周期性任务给丢弃掉;
源码分析
以前面对注释的理解作为主线,去看源码:
- 先看构造方法,如下,中文注释位置需要注意:
InstanceInfoReplicator(DiscoveryClient discoveryClient, InstanceInfo instanceInfo, int replicationIntervalSeconds, int burstSize) {this.discoveryClient = discoveryClient;this.instanceInfo = instanceInfo;//线程池,core size为1,使用DelayedWorkQueue队列this.scheduler = Executors.newScheduledThreadPool(1,new ThreadFactoryBuilder().setNameFormat("DiscoveryClient-InstanceInfoReplicator-%d").setDaemon(true).build());this.scheduledPeriodicRef = new AtomicReference<Future>();this.started = new AtomicBoolean(false);//RateLimiter是个限制频率的工具类,用来限制单位时间内的任务次数this.rateLimiter = new RateLimiter(TimeUnit.MINUTES);this.replicationIntervalSeconds = replicationIntervalSeconds;this.burstSize = burstSize;//通过周期间隔,和burstSize参数,计算每分钟允许的任务数this.allowedRatePerMinute = 60 * this.burstSize / this.replicationIntervalSeconds;logger.info("InstanceInfoReplicator onDemand update allowed rate per min is {}", allowedRatePerMinute);}
从以上代码可见,构造方法中准备好了线程池和频率限制工具,再算好了每分钟允许的任务数;
2. 在com.netflix.discovery.DiscoveryClient类的initScheduledTasks方法中,通过调用instanceInfoReplicator.start方法启动了周期性任务,现在来看此方法:
public void start(int initialDelayMs) {//CAS操作,不但保证了只执行一次,多线程场景也能保证if (started.compareAndSet(false, true)) {instanceInfo.setIsDirty(); // for initial register//提交一个任务,延时执行,注意第一个参数是this,因此延时结束时,InstanceInfoReplicator的run方法会被执行Future next = scheduler.schedule(this, initialDelayMs, TimeUnit.SECONDS);//这个任务的Feature对象放在成员变量scheduledPeriodicRef中scheduledPeriodicRef.set(next);}
}
- 延时时间到达时,会执行run方法:
public void run() {try {//更新信息,用于稍后的上报discoveryClient.refreshInstanceInfo();Long dirtyTimestamp = instanceInfo.isDirtyWithTime();if (dirtyTimestamp != null) {//上报discoveryClient.register();instanceInfo.unsetIsDirty(dirtyTimestamp);}} catch (Throwable t) {logger.warn("There was a problem with the instance info replicator", t);} finally {//每次执行完毕都会创建一个延时执行的任务,就这样实现了周期性执行的逻辑Future next = scheduler.schedule(this, replicationIntervalSeconds, TimeUnit.SECONDS);//每次创建的周期性任务,都要放入scheduledPeriodicRef,//如果外部调用了onDemandUpdate,就能通过onDemandUpdate取得当前要执行的任务scheduledPeriodicRef.set(next);}}
- 以上代码汇总起来,就完成了周期性任务的逻辑,接下来看看被外部调用的onDemandUpdate方法:
public boolean onDemandUpdate() {//没有达到频率限制才会执行if (rateLimiter.acquire(burstSize, allowedRatePerMinute)) {//提交一个任务scheduler.submit(new Runnable() {@Overridepublic void run() {logger.debug("Executing on-demand update of local InstanceInfo");//取出之前已经提交的任务Future latestPeriodic = scheduledPeriodicRef.get();//如果此任务未完成,就立即取消if (latestPeriodic != null && !latestPeriodic.isDone()) {logger.debug("Canceling the latest scheduled update, it will be rescheduled at the end of on demand update");latestPeriodic.cancel(false);}//通过调用run方法,令任务在延时后执行,相当于周期性任务中的一次InstanceInfoReplicator.this.run();}});return true;} else {//如果超过了设置的频率限制,本次onDemandUpdate方法就提交任务了logger.warn("Ignoring onDemand update due to rate limiter");return false;}}
如上述代码所示,可见之前注释中提到的功能都已实现;
至此,InstanceInfoReplicator已分析完毕,可见这是个功能强大的辅助类,在应用信息上报到Eureka server时发挥了重要的作用,业务逻辑可以放心的提交上报请求,并发、频率超限等情况都被InstanceInfoReplicator处理好了;
Eureka的InstanceInfoReplicator类(服务注册辅助工具)相关推荐
- Vue UI组件 开发框架 服务端 辅助工具 应用实例 Demo示例
2019独角兽企业重金招聘Python工程师标准>>> element ★11612 - 饿了么出品的Vue2的web UI工具套件 Vux ★7503 - 基于Vue和WeUI的组 ...
- 前端开发全家桶:UI组件 开发框架 服务端 辅助工具 应用实例 Demo示例
element ★11612 - 饿了么出品的Vue2的web UI工具套件 Vux ★7503 - 基于Vue和WeUI的组件库 iview ★5801 - 基于 Vuejs 的开源 UI 组件库 ...
- Python (百万答题类节目)辅助工具代码(实测有效)
前段时间很火的百万答题,现在编写了一个脚本辅助工具,思路如下: ①adb连接手机获取截屏,保存到本地 ②pytesseract获取图片指定位置的文字 ③网页查找答案 附代码如下:(亲测通过,执行时间6 ...
- Windows 服务(附服务开发辅助工具)
引子 近来在 Windows 下摆弄了一阵子的服务程序,有在 C++ 下弄服务的,也在 C# 下弄服务的, 感觉在 C# 下弄服务蛮简单的の,C/C++ 的麻烦蛮多の(当然我的服务所要求的功能也是很简 ...
- Tom邮箱注册机|注册辅助工具!!!
.net开发的Tom邮箱注册机,请下载微软的.net framework 3.5运行库.软件启动的时候就点慢,这个是因为第一次要从tom网站读取数据. 下载:http://files.cnblogs. ...
- 如何恢复类视图中突然消失的类已经编程辅助工具VISUAL ASIST
关闭工程 删除工程下.clw .ncb文件和debug目录 开启工程 rebuild all 需要再把.clw添加进来,这是个类向导(不知道可不可以之前不删这个,我没试,后来添加类向导时候发现 ...
- SpringCloud系列之Eureka服务注册及发现
Eureka 1. Eureka简介 1.1 什么是Eureka 2. Eureka实例 2.1 编写Eureka Server 2.2 编写Eureka Client 3. Eureka源码解析 3 ...
- Spring Cloud构建微服务架构:服务注册与发现(Eureka、Consul)【Dalston版】
Spring Cloud简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中涉及的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全 ...
- Spring Boot(2.1.2.RELEASE) + Spring Cloud (Finchley.RELEASE)搭建服务注册和发现组件Eureka
前言:由于版本原因,部分关于Spring Cloud的书中使用的是Spring Boot 1.x 版本,很多配置或名称在新版本中已经发生了改变.此篇文章记录的是使用较新的Spring Boot 2.x ...
最新文章
- python 解决最佳方案_python使用列表的最佳方案
- 02_计算机科学和软件工程的区别
- Measuring Similarity between Clusters (Clusters 之间相似度的测量)【未完待续】
- 项目交付为什么失败?-记我在某个项目中的迷思
- poj 3304 Segments (几何 : 线段 直线相交)
- Spring Boot——[Spring Boot Configuration Annotation Processor not found in classpath]解决方案
- Django从理论到实战(part10)--URL命名与反转
- 程序员技术练级攻略(转载)
- 您应该对什么进行单元测试? –测试技术3
- infopath转换html,Microsoft Tools to Save InfoPath Forms as HTML
- 朱晔和你聊Spring系列S1E9:聊聊Spring的那些注解
- 将含有自定义代码的Infopath模板发布到Sharepoint表单库中
- CSAPP-C1-计算机系统漫游
- GB35114—⑤、附 录C
- java 设置压缩文件大小不变_为什么把文件压缩后,文件大小却不变呢?
- linux的XDG(X Desktop Group)基本目录规范
- 二年级计算机学什么礼物,二年级的小朋友喜欢什么礼物(最美好的礼物二年级)...
- 【python逻辑算法题】一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法
- 使用java的方式配置Spring---JavaConfig
- 方队 - 启发式合并 - 主席树