Spring Cloud Eureka 原理详解(一)

Spring Cloud Eureka 详解1). Eureka 的核心类1. InstanceInfopublic class InstanceInfo { .... // 实例ID private volatile String instanceId; // 应用名 private volatile String appNa...
摘要由CSDN通过智能技术生成

Spring Cloud Eureka 详解

1). Eureka 的核心类

1. InstanceInfo

InstanceInfo 封装了服务实例信息

public class InstanceInfo {
   
    ....
       // 实例ID 
      private volatile String instanceId;
       // 应用名 
      private volatile String appName;
       //  应用所属群组
      private volatile String appGroupName;
       // ip地址
      private volatile String ipAddr;
       // 默认端口号  7001 
      public static final int DEFAULT_PORT = 7001;
       // 端口号 
      private volatile int port = DEFAULT_PORT;
       //默认 https  端口号
      public static final int DEFAULT_SECURE_PORT = 7002;
    	//  https  端口号 
      private volatile int securePort = DEFAULT_SECURE_PORT;
        // 应用实例的首页URL 
      private volatile String homePageUrl;
    	//  应用实例状态页URL
      private volatile String statusPageUrl;
        //  应用实例健康页URL
      private volatile String healthCheckUrl;
    	// 应用实例健康页的 HTTPS  URL  
      private volatile String secureHealthCheckUrl;
    	// 虚拟地址
      private volatile String vipAddress;
       //  https 虚拟地址 
      private volatile String secureVipAddress;
    	// Defaults to US  默认为1 
      private volatile int countryId = DEFAULT_COUNTRY_ID; 
      	// dataCenter 信息 ,NetFlix 或者 Amazon 或者 MyOwn 
      private volatile DataCenterInfo dataCenterInfo;
    	// 主机名称  
      private volatile String hostName;
    	//实例状态,UP ,DOWN ,STARTING ,OUT_OF_SERVICE,UNKNOWN
    	// 其中 OUT_OF_SERVICE 标识服务停止,处于这个状态的服务不会被路由到,经常用于升级部署的场景。
      private volatile InstanceStatus status = InstanceStatus.UP;
    	// 外界需要强制覆盖的状态值, 默认为UNKNOWN 
       private volatile InstanceStatus overriddenStatus = InstanceStatus.UNKNOWN;
    	// 租约信息
       private volatile LeaseInfo leaseInfo;
    	// 首先标识是否是discoveryServer ,其实标识该discoveryServer是否是响应你请求的实例
        private volatile Boolean isCoordinatingDiscoveryServer = Boolean.FALSE;
        // 应用实例的元数据信息 
        private volatile Map<String, String> metadata;
        // 状态信息更新的时间
        private volatile Long lastUpdatedTimestamp;
    	// 实例信息最新的过期时间 , 实例信息最新的过期时间
        private volatile Long lastDirtyTimestamp;
        // 标识Eureka Server 对该实例的操作,包括ADDED,MODIFIED,DELETED 这三类 。 
        private volatile ActionType actionType;
        // AWS的autoscaling的名称 
        private volatile String asgName;
} 

可以看到InstanceInfo 里既有metadata ,也有dataCenterInfo ,还有一个比较重要的LeaseInfo ,用来标识应用实例的租约信息。

2. LeaseInfo

Eureka 使用LeaseInfo (com.netflix.appinfo.LeaseInfo.java) 来标识应用实例的租约的信息。

public class LeaseInfo {
   
	
    public static final int DEFAULT_LEASE_RENEWAL_INTERVAL = 30;
    public static final int DEFAULT_LEASE_DURATION = 90;

    // Client settings(客户端配置)续约的时间间隔     
    private int renewalIntervalInSecs=DEFAULT_LEASE_RENEWAL_INTERVAL;
    // 需要设定的租约的有效时长 
    private int durationInSecs = DEFAULT_LEASE_DURATION;
    
    // Server populated (服务端填充)  
    // server 端设置的该租约的第一次注册时间
    private long registrationTimestamp; 
    // server 端设置的该租约的最后一次续约时间
    private long lastRenewalTimestamp;
    // server端设置的该租约被删除的时间
    private long evictionTimestamp;
    //  server端设置的该服务实例标记为UP的时间
    private long serviceUpTimestamp;

}

这些参数主要用于标识应用实例的心跳情况,比如约定的心跳周期,租约有效期,最近一次续约时间。

3. ServieceInstance

ServiceInstance 是Spring Cloud 对 service discovery 的实例信息的抽象接口,约定了服务发现的实例有哪些通用的信息。

public interface ServiceInstance {
   

   /**
    * 获取服务ID
    */
   String getServiceId();

   /**
    *  服务实例的 host 
    */
   String getHost();

   /**
    *  服务实例的端口
    */
   int getPort();

   /**
    * 服务是否开启 https 
    */
   boolean isSecure();

   /**
    *实例的uri地址
    */
   URI getUri();

   /**
    * 服务实例的元数据
    */
   Map<String, String> getMetadata();

   /**
    * 实例的 scheme 
    */
   default String getScheme() {
   
      return null;
   }
}

2). 服务的核心操作

对于服务发现来说,关于服务实例的主要操作又几个重要的操作:

  • 服务注册(register)

  • 服务下线(cancel)

  • 服务租约(renew)

  • 服务剔除(evict)

    围绕这几个功能,Eureka 设计了几个核心操作类:

    com.netflix.eureka.lease.LeaseManager

    com.netflix.discovery.shared.LookupService

    com.netflix.eureka.registry.InstanceRegistry

    com.netflix.eureka.registry.AbstractInstanceRegistry

    com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl

    Spring Cloud Eureka 在netflix 的基础上,抽象和定义了如下几个核心类:

    org.springframework.cloud.netflix.eureka.server.InstanceRegistry

    org.springframework.cloud.client.serviceregistry.ServiceRegistry

    org.springframework.cloud.netflix.eureka.serviceregistry.EurekaServiceRegistry

    org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration

    org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration

    org.springframework.cloud.netflix.eureka.EurekaClientConfigBean

    org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean

    LeaseManager 以及LookupService 是eureka关于服务发现操作相关的接口类,Leasemanager 定义了服务写操作相关的方法,LookupService定义了查询的操作方法。

1. LeaseManager

public interface LeaseManager<T> {
   

    /*
    	注册服务实例	
     */
    void register(T r, int leaseDuration, boolean isReplication);

    /*
    	删除服务实例
     */
    boolean cancel(String appName, String id, boolean isReplication);

    /*
    	与Eureka server 进行心跳检测  , 维持租约
     */
    boolean renew(String appName, String id, boolean isReplication);

    /**
       去除租约过期的服务实例
     */
    void evict();
}

具体实现在: AbstractInstanceRegistry

public void register(InstanceInfo registrant, int leaseDuration, boolean isReplication) {
   
        try {
   
            // 上读锁 
            read.lock();
            // 判断实例是否已经注册
            Map<String, Lease<InstanceInfo>> gMap = registry.get(registrant.getAppName());
            REGISTER.increment(isReplication);
            if (gMap == null) {
   
                final ConcurrentHashMap<String, Lease<InstanceInfo>> gNewMap = new ConcurrentHashMap<String, Lease<InstanceInfo>>();
                gMap = registry.putIfAbsent(registrant.getAppName(), gNewMap);
                if (gMap == null) {
   
                    gMap = gNewMap;
                }
            }
            Lease<InstanceInfo> existingLease = gMap.get(registrant.getId());
            // 如果已经存在租约 , 保存最后的过期时间
            if (existingLease != null && (existingLease.getHolder() != null)) {
   
                Long existingLastDirtyTimestamp = existingLease.getHolder().getLastDirtyTimestamp();
                Long registrationLastDirtyTimestamp = registrant.getLastDirtyTimestamp();
                logger.debug("Existing lease found (existing={}, provided={}", existingLastDirtyTimestamp, registrationLastDirtyTimestamp);

                //  已存在的实例过期时间 大于 注册的过期时间 ,将用本地的副本
                if (existingLastDirtyTimestamp > registrationLastDirtyTimestamp) {
   
                    logger.warn("There is an existing lease and the existing lease's dirty time
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值