原文:https://xsxy007.github.io

Spring Cloud环境下,服务提供者和消费者启动后都会将自身注册到Eureka

一、将服务注册到Eureka

一个SpringBoot应用如果要注册到Spring Cloud环境(Greenwich.SR3版本),步骤很简单:

  • pom.xml中添加启动器:spring-cloud-starter-netflix-eureka-client;

  • 增加配置:eureka.client.serviceUrl.defaultZone: http://localhost:8100/eureka/;

  • 启动应用;

  • 如果注册中心正常,此时就能在注册中心发现这个应用了,如下图红框所示:

  • 按照spring.factories中的配置,EurekaClientAutoConfiguration中的配置都会生效,包括下面这段代码返回的bean:

  • @Bean
    public DiscoveryClient discoveryClient(EurekaInstanceConfig config, EurekaClient client) {
    return new EurekaDiscoveryClient(config, client);
    }
  • spring容器初始化时会实例化所有单例bean,就会执行EurekaClientAutoConfiguration的discoveryClient方法获取这个bean实例,于是就构造了一个EurekaDiscoveryClient对象;

  • 注意EurekaDiscoveryClient的构造方法,第二个入参是com.netflix.discovery.EurekaClient类型,此对象同样来自EurekaClientAutoConfiguration类,如下方法:

  • @Bean(destroyMethod = "shutdown")
    @ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
    @org.springframework.cloud.context.config.annotation.RefreshScope
    @Lazy
    public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config, EurekaInstanceConfig instance) {
    manager.getInfo(); // force initialization
    return new CloudEurekaClient(manager, config, this.optionalArgs,this.context);
    }
  • CloudEurekaClient的父类com.netflix.discovery.DiscoveryClient来自netflix发布的eureka-client包中,所以可以这么理解:EurekaDiscoveryClient类是个代理身份,真正的服务注册发现是委托给netflix的开源包来完成的,我们可以专心的使用SpringCloud提供的服务注册发现功能,只需要知道EurekaDiscoveryClient即可,真正的服务是eureka-client来完成的;

  • 接下来需要关注com.netflix.discovery.DiscoveryClient的构造方法,因为这里面有服务注册的逻辑,整个构造方法内容太多,无需都细看,只看关键代码即可;

  • DiscoveryClient的构造方法中,最熟悉的应该是下图红框中这段日志输出的了:

    对应的应用启动日志中就有这段日志输出,如下图红框:

    红框中的”us-east-1”,是默认的region,来自配置类EurekaClientConfigBean,这里面有各种eureka相关的配置信息,以及默认配置,如下图:

  • 继续看DiscoveryClient的构造方法,服务注册相关的initScheduledTasks方法在此被调用,如下图:

  • initScheduledTasks方法的内容如下,请注意中文注释:

        private void initScheduledTasks() {
    //获取服务注册列表信息
    if (clientConfig.shouldFetchRegistry()) {
    //服务注册列表更新的周期时间
    int registryFetchIntervalSeconds = clientConfig.getRegistryFetchIntervalSeconds();
    int expBackOffBound = clientConfig.getCacheRefreshExecutorExponentialBackOffBound();
    //定时更新服务注册列表
    scheduler.schedule(
    new TimedSupervisorTask(
    "cacheRefresh",
    scheduler,
    cacheRefreshExecutor,
    registryFetchIntervalSeconds,
    TimeUnit.SECONDS,
    expBackOffBound,
    new CacheRefreshThread() //该线程执行更新的具体逻辑
    ),
    registryFetchIntervalSeconds, TimeUnit.SECONDS);
    }
    if (clientConfig.shouldRegisterWithEureka()) {
    //服务续约的周期时间
    int renewalIntervalInSecs = instanceInfo.getLeaseInfo().getRenewalIntervalInSecs();
    int expBackOffBound = clientConfig.getHeartbeatExecutorExponentialBackOffBound();
    //应用启动可见此日志,内容是:Starting heartbeat executor: renew interval is: 30
    logger.info("Starting heartbeat executor: " + "renew interval is: " + renewalIntervalInSecs);
    // 定时续约
    scheduler.schedule(
    new TimedSupervisorTask(
    "heartbeat",
    scheduler,
    heartbeatExecutor,
    renewalIntervalInSecs,
    TimeUnit.SECONDS,
    expBackOffBound,
    new HeartbeatThread() //该线程执行续约的具体逻辑
    ),
    renewalIntervalInSecs, TimeUnit.SECONDS); //这个Runable中含有服务注册的逻辑
    instanceInfoReplicator = new InstanceInfoReplicator(
    this,
    instanceInfo,
    clientConfig.getInstanceInfoReplicationIntervalSeconds(),
    2); // burstSize statusChangeListener = new ApplicationInfoManager.StatusChangeListener() {
    @Override
    public String getId() {
    return "statusChangeListener";
    } @Override
    public void notify(StatusChangeEvent statusChangeEvent) {
    if (InstanceStatus.DOWN == statusChangeEvent.getStatus() ||
    InstanceStatus.DOWN == statusChangeEvent.getPreviousStatus()) {
    // log at warn level if DOWN was involved
    logger.warn("Saw local status change event {}", statusChangeEvent);
    } else {
    logger.info("Saw local status change event {}", statusChangeEvent);
    }
    instanceInfoReplicator.onDemandUpdate();
    }
    }; if (clientConfig.shouldOnDemandUpdateStatusChange()) {
    applicationInfoManager.registerStatusChangeListener(statusChangeListener);
    }
    //服务注册
    instanceInfoReplicator.start(clientConfig.getInitialInstanceInfoReplicationIntervalSeconds());
    } else {
    logger.info("Not registering with Eureka server per configuration");
    }
    }

    上述代码中有几处需要注意,这些关键点在后面的章节将继续展开:

    a. 周期性更新服务列表;

    b. 周期性服务续约;

    c. 服务注册逻辑被放入Runnable实现类InstanceInfoReplicator之中,在新线程中执行;

SpringCloud-Eureka-服务注册是如何发起的的更多相关文章

  1. 将SpringCloud Eureka 服务注册与发现部署到docker

    一.前言 最近在学习docker,顺便把之前学习的spring cloud 部署到Docker 中.至于什么是SpringCloud的服务注册与发现,什么是docker,我这里就不作赘述了.可以先去学 ...

  2. SpringCloud Eureka服务注册及发现——服务端/客户端/消费者搭建

    Eureka 是 Netflix 出品的用于实现服务注册和发现的工具. Spring Cloud 集成了 Eureka,并提供了开箱即用的支持.其中, Eureka 又可细分为 Eureka Serv ...

  3. springcloud(第三篇)springcloud eureka 服务注册与发现 *****

    http://blog.csdn.net/liaokailin/article/details/51314001 ******************************************* ...

  4. SpringCloud——Eureka服务注册和发现

    一.SpringCloud和Dubbo SpringCloud整合了一套较为完整的微服务解决方案框架,而Dubbo只是解决了微服务的几个方面的问题. content Dubbo SpringCloud ...

  5. SpringCloud Eureka 服务注册与服务发现

    一.Eureka简介 spring Cloud Netflix技术栈中,Eureka作为服务注册中心对整个微服务架构起着最核心的整合作用.有了服务发现与注册,你就不需要整天改服务调用的配置文件了,你只 ...

  6. SpringCloud(3)---Eureka服务注册与发现

    Eureka服务注册与发现 一.Eureka概述 1.Eureka特点 (1) Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移. (2) Eureka 主管服务 ...

  7. java框架之SpringCloud(3)-Eureka服务注册与发现

    在上一章节完成了一个简单的微服务案例,下面就通过在这个案例的基础上集成 Eureka 来学习 Eureka. 介绍 概述 Eureka 是 Netflix 的一个子模块,也是核心模块之一.Eureka ...

  8. SpringCloud之服务注册-eureka

    类似于DUBBO 的zookeeper, SpringCloud本身提供一套服务注册中心--eureka 与zookeeper的区别在于 1:zookeeper本身就是一个应用,安装即可用:eurek ...

  9. 微服务框架SpringCloud(Dalston版)学习 (一):Eureka服务注册与发现

    eureka-server eureka服务端,提供服务的注册与发现,类似于zookeeper 新建spring-boot工程,pom依赖: <dependency> <groupI ...

  10. SpringCloud 进阶之Eureka(服务注册和发现)

    1. Eureka 服务注册与发现 Eureka 是一个基于REST的服务,用于服务的的注册与发现; Eureka采用C-S的设计架构,Eureka Server作为服务注册功能的服务器,它是服务注册 ...

随机推荐

  1. apache重写规则简单理解

    1.前提:开启apache重写,并把httpd.conf里的相关的AllowOverride denied改为AllowOverride all 2.重写规则可写在项目根目录的.htaccess文件或 ...

  2. 漫谈五种IO模型

    阅读目录 1 基础知识回顾 2 I/O模式 3 事件驱动编程模型 网络编程里常听到阻塞IO.非阻塞IO.同步IO.异步IO等概念,搞清楚这些概念之前,还得先回顾一些基础的概念. 1 基础知识回顾 注意 ...

  3. AWD

    扫描对方IP:ifconfig (先获取自己的IP)netdiscover -r 192.168.0.1/24   (扫描1~124的IP) 获取IP后:nmap -sV 192.168.0.104 ...

  4. Codeforces 892E Envy

    问题描述 小Q正在玩一个叠塔的游戏,游戏的目标是叠出尽可能高的塔.在游戏中,一共有n张矩形卡片,其中第i张卡片的 长度为a_i,宽度为b_i.小Q需要把所有卡片按一定顺序叠成一座塔,要求对于任意一个矩 ...

  5. u盘被占用,无法弹出解决办法

    方法1.把鼠标放到电脑屏幕最底部的中央,点击右键,点击 任务管理器 方法2.按:CTRL+ALT+ENTER(回车)   打开任务管理器,点击   进入性能后点击下方的:资源管理器   回到桌面,查看 ...

  6. [CF1166C]A Tale of Two Lands题解

    比赛的时候lowerbound用错了 现场WA on test4(好吧我承认我那份代码确实有除了lowerbound以外的问题) 于是只能手动二分 (我好菜啊QAQ 经过一波数学推算,我们发现,设序列 ...

  7. 解决webpack打包vue项目后,部署完成后,刷新页面页面404

    1.url不动式url完全不动,即你的页面怎么改变,怎么跳转url都不会改变.这种情况的原理 就是纯ajax拿到页面后替换原页面中的元素,刷新页面就是首页 2.带hash(#)式这种相对于第一种的话刷 ...

  8. python之_init_()方法浅析

    在python的类中,我们会经常看到一个类中的一个方法_init_(self) ,比如下面的一个例子: class Student(object): def __init__(self,name,we ...

  9. womenzijide_jiafenxiang

    <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Conten ...

  10. loj#2333 「JOI 2017 Final」准高速电车

    分析 我们发现到达一个点一定是先快车再准快车再慢车 于是快车将1-n分为多个区间 每次取出每个区间当前能到达的点的数量 选剩余时间贡献最大的的一个取得贡献并且再能到达的最远点建立准快车 代码 #inc ...