Eureka 学习笔记5:InstanceRegistry

版本 awsVersion = ‘1.11.277’

InstanceRegistry


LeaseManager 接口管理实例的租约信息,提供以下功能:

  1. 注册实例
  2. 取消注册实例
  3. 实例续约
  4. 剔除过期实例
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 接口,提供以下功能:

  1. 启动和关闭注册表服务
  2. 更新注册表中实例的状态
  3. 从注册表中获取应用信息和实例信息
  4. 初始化和获取注册表缓存
  5. 租约过期机制和自我保护机制(和 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();

    // ========================
    // 更新注册表中实例的状态
    // ========================

    @Deprecated
    void 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() {
    @Override
    public 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.registryFetchIntervalInSeconds
        serverConfig.getRemoteRegionRegistryFetchInterval(),
        TimeUnit.SECONDS,
        5,  // exponential backoff bound
        remoteRegionFetchTask
    ),
    serverConfig.getRemoteRegionRegistryFetchInterval(),
    TimeUnit.SECONDS);

remoteRegion.global.appWhiteListremoteRegion.{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 PeerAwareInstanceRegistryImpl
                extends AbstractInstanceRegistry
                implements 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);

    @Inject
    public 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());
    }

    @Override
    public void init(PeerEurekaNodes peerEurekaNodes) throws Exception {
        // 1.统计每分钟和其他Eureka节点的同步频率
        this.numberOfReplicationsLastMin.start();
        // 2.赋值peerEurekaNodes属性,保存Eureka集群节点信息
        this.peerEurekaNodes = peerEurekaNodes;
        // 3.创建本地注册表缓存ResponseCacheImpl
        initializedResponseCache();
        // 4.创建TimerTask,通过Timer调度updateRenewalThreshold方法
        // 定时更新numberOfRenewsPerMinThreshold
        scheduleRenewalThresholdUpdateTask();
        // 5.创建其他区域的注册表RemoteRegionRegistry
        initRemoteRegionRegistry();
        // ...
    }
}
  1. 实现了 PeerAwareInstanceRegistry 接口,通过 eurekaClient 属性获得了从其他 Eureka 节点拉取注册表(PeerAwareInstanceRegistry#syncUp()方法)的能力,

  2. 通过 peerEurekaNodes 属性获得了将本地注册表的更新同步给其他 Eureka 节点(PeerAwareInstanceRegistryImpl#replicateToPeers()方法)的能力

:为什么不将 Eureka 节点之间同步更新数据的操作和拉取注册表的操作一起声明在 PeerAwareInstanceRegistry 接口中,而是另外通过 PeerEurekaNode 类去实现呢?

既然 numberOfRenewsPerMinThreshold 是通过实例数量实时计算为什么不将 numberOfRenewsPerMinThreshold 属性声明在 PeerAwareInstanceRegistryImpl 类中,而是声明在父类 AbstractInstanceRegistry 中?

instanceStatusOverrideRule 根据规则计算实例的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/57206.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【排序算法】python之冒泡,选择,插入,快速,归并

参考资料&#xff1a; 《Python实现5大排序算法》《六大排序算法&#xff1a;插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序》 --代码似乎是C语言 ———————— 本文介绍5种常见的排序算法和基于Python实现&#xff1a; 冒泡排序&#xff08;Bubble Sort&am…

Python web实战之 Django 的 ORM 框架详解

本文关键词&#xff1a;Python、Django、ORM。 概要 在 Python Web 开发中&#xff0c;ORM&#xff08;Object-Relational Mapping&#xff0c;对象关系映射&#xff09;是一个非常重要的概念。ORM 框架可以让我们不用编写 SQL 语句&#xff0c;就能够使用对象的方式来操作数据…

vue3+uniapp自定义tabbar

首先把tabbar中的元素写在一个list中用v-for进行渲染 用一个interface进行定义接口&#xff0c;这样别人在review你的代码就可以清晰知道你的tabbar包含什么元素。 利用typescript特性进行类型定义&#xff0c;可以省去很多麻烦 import { reactive } from "vue" imp…

Android kotlin系列讲解之最佳的UI体验 - Material Design 实战

目录 一、什么是Material Design二、Toolbar三、滑动菜单1、DrawerLayout2、NavigationView 四、悬浮按钮和可交互提示1、FloatingActionButton2、Snackbar3、CoordinatorLayout 五、卡片式布局1、MaterialCardView2、AppBarLayout 六、可折叠式标题栏1、CollapsingToolbarLayo…

无脑入门pytorch系列(一)—— nn.embedding

本系列教程适用于没有任何pytorch的同学&#xff08;简单的python语法还是要的&#xff09;&#xff0c;从代码的表层出发挖掘代码的深层含义&#xff0c;理解具体的意思和内涵。pytorch的很多函数看着非常简单&#xff0c;但是其中包含了很多内容&#xff0c;不了解其中的意思…

线扫激光算法原理

一:线扫激光算法原理 激光器发出的激光束经准直聚焦后垂直入射到物体表面上,表面的散射光由接收透镜成像于探测器的阵列上。光敏面于接收透镜的光轴垂直。如图: 当被测物体表面移动x,反应到光敏面上像点位移为x’。a为接收透镜到物体的距离(物距),b为接收后主面到成像…

SQL-每日一题【1174. 即时食物配送 II】

题目 配送表: Delivery 如果顾客期望的配送日期和下单日期相同&#xff0c;则该订单称为 「即时订单」&#xff0c;否则称为「计划订单」。 「首次订单」是顾客最早创建的订单。我们保证一个顾客只会有一个「首次订单」。 写一条 SQL 查询语句获取即时订单在所有用户的首次订…

无人驾驶实战-第一课(自动驾驶概述)

在七月算法上报了《无人驾驶实战》课程&#xff0c;老师讲的真好。好记性不如烂笔头&#xff0c;记录一下学习内容。 课程入口&#xff0c;感兴趣的也可以跟着学一下。 ————————————————————————————————————————— 无人驾驶汽车的定义…

HTTP——五、与HTTP协作的Web服务器

HTTP 一、用单台虚拟主机实现多个域名二、通信数据转发程序 &#xff1a;代理、网关、隧道1、代理2、网关3、隧道 三、保存资源的缓存1、缓存的有效期限2、客户端的缓存 一台 Web 服务器可搭建多个独立域名的 Web 网站&#xff0c;也可作为通信路径上的中转服务器提升传输效率。…

windows服务器iis PHP套件出现FastCGI等错误解决方法汇总

如果您的服务器安装了PHP套件&#xff0c;出现了无法打开的情况&#xff0c;请参照如下办法解决&#xff1a; 首先&#xff0c;需要设置IIS允许输出详细的错误信息到浏览器&#xff0c;才好具体分析 错误一&#xff1a; 处理程序“FastCGI”在其模块列表中有一个错误模块“Fast…

应用案例|基于3D视觉的高反光金属管件识别系统解决方案

Part.1 项目背景 在现代制造业中&#xff0c;高反光金属管件的生产以及质量的把控是一个重要的挑战。传统的2D视觉系统常常难以准确地检测和识别高反光金属管件&#xff0c;因为它们的表面特征不够明显&#xff0c;容易受到光照和阴影的干扰。为了应对这个问题&#xff0c;基于…

UE5 c++ 的文件操作(记录备忘)

函数库.h // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include "Kismet/BlueprintFunctionLibrary.h" #include "Microsoft/AllowMicrosoftPlatformTypes.h" #incl…

windows编译ncnn

官方代码https://github.com/Tencent/ncnn/wiki/how-to-build#build-for-windows-x64-using-visual-studio-community-2017 编译工具 visual studio 2017 一、编译protobuf 1、下载protobuf protobuf-3.11.2&#xff1a;https://github.com/google/protobuf/archive/v3.11…

基于SpringBoot+Vue的在线考试系统设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

HarmonyOS学习路之方舟开发框架—学习ArkTS语言(状态管理 三)

Link装饰器&#xff1a;父子双向同步 子组件中被Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。 概述 Link装饰的变量与其父组件中的数据源共享相同的值。 装饰器使用规则说明 Link变量装饰器 说明 装饰器参数 无 同步类型 双向同步。 父组件中State, Stor…

Linux常用命令——dpkg-deb命令

在线Linux命令查询工具 dpkg-deb Debian Linux下的软件包管理工具 补充说明 dpkg-deb命令是Debian Linux下的软件包管理工具&#xff0c;它可以对软件包执行打包和解包操作以及提供软件包信息。 语法 dpkg-deb(选项)(参数)选项 -c&#xff1a;显示软件包中的文件列表&am…

springBoot项目导入外部jar包

一、将外部的jar包复制到指定文件夹 二、修改pom文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocati…

专家论道: 唐贤香云纱塑造中国非遗国际品牌

自“香云纱染整技艺”入选第二批国家级非物质文化遗产以来&#xff0c;被誉为纺织界“软黄金”的香云纱&#xff0c;重新焕发青春&#xff0c;频频登上时尚舞台&#xff0c;以不一样的面貌展示在世人面前&#xff0c;成为服装设计师、消费者青睐的材质。而随着北京卫视播出的《…

Win10查询硬盘序列号

添加wmic命令 winR cmd命令 wmic diskdrive get model, serialnumber

java -jar指定外部配置文件

场景 spingboot项目部署jar时,需要时常修改配置,为了方便,将配置文件放到jar包外 操作步骤 在jar包同级目录下创建config文件夹(位置没有强制要求,为了方便而已) 在jar包同级目录下创建start.bat文件,并编辑内容 echo off :: 命令窗口标题 title yudibei_performance_tes…