前言

在源码分析三、四都有提及到EurekaClient启动的一些过程。因为EurekaServer在集群模式下 自己本身就是一个client,所以之前初始化eurekaServerContext就有涉及到eurekaClient的初始化。

我们也看了EurekaClient(DiscoveryClient)初始化的过程,繁杂的启动过程让人眼花缭乱,这篇文章就专门来唠唠 里面经历的一些艰难险阻。这也会是后面client注册的一个前置文章。

如若转载 请标明来源:一枝花算不算浪漫

从ExampleEurekaClient开始说起

在第一讲我们就说过,eureka项目有一个examples模块的,现在看一下其中的EurekaClientExample对象:

public class ExampleEurekaClient {

    private static ApplicationInfoManager applicationInfoManager;
private static EurekaClient eurekaClient; private static synchronized ApplicationInfoManager initializeApplicationInfoManager(EurekaInstanceConfig instanceConfig) {
if (applicationInfoManager == null) {
InstanceInfo instanceInfo = new EurekaConfigBasedInstanceInfoProvider(instanceConfig).get();
applicationInfoManager = new ApplicationInfoManager(instanceConfig, instanceInfo);
} return applicationInfoManager;
} private static synchronized EurekaClient initializeEurekaClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig clientConfig) {
if (eurekaClient == null) {
eurekaClient = new DiscoveryClient(applicationInfoManager, clientConfig);
} return eurekaClient;
} public void sendRequestToServiceUsingEureka(EurekaClient eurekaClient) {
// initialize the client
// this is the vip address for the example service to talk to as defined in conf/sample-eureka-service.properties
String vipAddress = "sampleservice.mydomain.net"; InstanceInfo nextServerInfo = null;
try {
nextServerInfo = eurekaClient.getNextServerFromEureka(vipAddress, false);
} catch (Exception e) {
System.err.println("Cannot get an instance of example service to talk to from eureka");
System.exit(-1);
} System.out.println("Found an instance of example service to talk to from eureka: "
+ nextServerInfo.getVIPAddress() + ":" + nextServerInfo.getPort()); System.out.println("healthCheckUrl: " + nextServerInfo.getHealthCheckUrl());
System.out.println("override: " + nextServerInfo.getOverriddenStatus()); Socket s = new Socket();
int serverPort = nextServerInfo.getPort();
try {
s.connect(new InetSocketAddress(nextServerInfo.getHostName(), serverPort));
} catch (IOException e) {
System.err.println("Could not connect to the server :"
+ nextServerInfo.getHostName() + " at port " + serverPort);
} catch (Exception e) {
System.err.println("Could not connect to the server :"
+ nextServerInfo.getHostName() + " at port " + serverPort + "due to Exception " + e);
}
try {
String request = "FOO " + new Date();
System.out.println("Connected to server. Sending a sample request: " + request); PrintStream out = new PrintStream(s.getOutputStream());
out.println(request); System.out.println("Waiting for server response..");
BufferedReader rd = new BufferedReader(new InputStreamReader(s.getInputStream()));
String str = rd.readLine();
if (str != null) {
System.out.println("Received response from server: " + str);
System.out.println("Exiting the client. Demo over..");
}
rd.close();
} catch (IOException e) {
e.printStackTrace();
}
} public static void main(String[] args) throws Exception{
injectEurekaConfiguration();
ExampleEurekaClient sampleClient = new ExampleEurekaClient(); // MyDataCenterInstanceConfig 就是加载eureka-client.properties配置信息,形成一个服务实例的配置EurekaInstanceConfig
// 基于EurekaClient配置,构造了一个服务实例(InstanceInfo)
// 基于eureka client配置和服务实例,构造了一个服务实例管理器(ApplicationInfoManager)
// 读取eureka-client.properties配置文件,形成了一个eureka client的配置,接口对外提供eureka client的配置项的读取
// 基于eureka client的配置,和服务实例管理器,来构造了一个EurekaClient(DiscoveryClient
// ),保存了一些配置,处理服务的注册和注册表的抓取,启动了几个线程池,启动了网络通信组件,启动了一些调度任务,注册了监控项
ApplicationInfoManager applicationInfoManager = initializeApplicationInfoManager(new MyDataCenterInstanceConfig());
EurekaClient client = initializeEurekaClient(applicationInfoManager, new DefaultEurekaClientConfig()); // use the client
sampleClient.sendRequestToServiceUsingEureka(client); // shutdown the client
eurekaClient.shutdown();
} /**
* This will be read by server internal discovery client. We need to salience it.
*/
private static void injectEurekaConfiguration() throws UnknownHostException {
String myHostName = InetAddress.getLocalHost().getHostName();
String myServiceUrl = "http://" + myHostName + ":8080/v2/"; System.setProperty("eureka.region", "default");
System.setProperty("eureka.name", "eureka");
System.setProperty("eureka.vipAddress", "eureka.mydomain.net");
System.setProperty("eureka.port", "8080");
System.setProperty("eureka.preferSameZone", "false");
System.setProperty("eureka.shouldUseDns", "false");
System.setProperty("eureka.shouldFetchRegistry", "true");
System.setProperty("eureka.serviceUrl.defaultZone", myServiceUrl);
System.setProperty("eureka.serviceUrl.default.defaultZone", myServiceUrl);
System.setProperty("eureka.awsAccessId", "fake_aws_access_id");
System.setProperty("eureka.awsSecretKey", "fake_aws_secret_key");
System.setProperty("eureka.numberRegistrySyncRetries", "0");
}
}

这里我们从main函数开始看起:

  1. 注入eureka配置信息:injectEurekaConfiguration();
  2. 读取eureka-client.properties配置文件,形成一个服务器实例的配置,基于接口对外提供实例的配置项读取

    这里就是涉及到我么你之前讲解的DynamicPropertyFactoryConfigurationManager,这里可以查看new MyDataCenterInstanceConfig()然后一步步往后跟。
  3. 基于服务实例的配置,构造了一个服务实例(InstanceInfo)。initializeApplicationInfoManager中会构建InstanceInfo信息
  4. 基于服务实例的配置和服务实例,初始化服务实例管理器(ApplicationInfoManager)
  5. 基于eureka client配置,和服务实例管理器,来构造了一个EurekaClient(DiscoveryClient),保存了一些配置,处理服务的注册和注册表的抓取,启动了几个线程池,启动了网络通信组件,启动了一些调度任务,注册了监控项

    具体可查看 EurekaClient client = initializeEurekaClient(applicationInfoManager, new DefaultEurekaClientConfig());

流程图

申明

本文章首发自本人博客:https://www.cnblogs.com/wang-meng 和公众号:壹枝花算不算浪漫,如若转载请标明来源!

感兴趣的小伙伴可关注个人公众号:壹枝花算不算浪漫

【一起学源码-微服务】Nexflix Eureka 源码五:EurekaClient启动要经历哪些艰难险阻?的更多相关文章

  1. 【一起学源码-微服务】Eureka+Ribbon+Feign阶段性总结

    前言 想说的话 这里已经梳理完Eureka.Ribbon.Feign三大组件的基本原理了,今天做一个总结,里面会有一个比较详细的调用关系流程图. 说明 原创不易,如若转载 请标明来源! 博客地址:一枝 ...

  2. 【一起学源码-微服务】Ribbon源码五:Ribbon源码解读汇总篇~

    前言 想说的话 [一起学源码-微服务-Ribbon]专栏到这里就已经全部结束了,共更新四篇文章. Ribbon比较小巧,这里是直接 读的spring cloud 内嵌封装的版本,里面的各种config ...

  3. 【一起学源码-微服务】Ribbon 源码三:Ribbon与Eureka整合原理分析

    前言 前情回顾 上一篇讲了Ribbon的初始化过程,从LoadBalancerAutoConfiguration 到RibbonAutoConfiguration 再到RibbonClientConf ...

  4. 【一起学源码-微服务】Feign 源码一:源码初探,通过Demo Debug Feign源码

    前言 前情回顾 上一讲深入的讲解了Ribbon的初始化过程及Ribbon与Eureka的整合代码,与Eureka整合的类就是DiscoveryEnableNIWSServerList,同时在Dynam ...

  5. 【一起学源码-微服务】Ribbon 源码一:Ribbon概念理解及Demo调试

    前言 前情回顾 前面文章已经梳理清楚了Eureka相关的概念及源码,接下来开始研究下Ribbon的实现原理. 我们都知道Ribbon在spring cloud中担当负载均衡的角色, 当两个Eureka ...

  6. 【一起学源码-微服务】Ribbon 源码二:通过Debug找出Ribbon初始化流程及ILoadBalancer原理分析

    前言 前情回顾 上一讲讲了Ribbon的基础知识,通过一个简单的demo看了下Ribbon的负载均衡,我们在RestTemplate上加了@LoadBalanced注解后,就能够自动的负载均衡了. 本 ...

  7. 【一起学源码-微服务】Ribbon 源码四:进一步探究Ribbon的IRule和IPing

    前言 前情回顾 上一讲深入的讲解了Ribbon的初始化过程及Ribbon与Eureka的整合代码,与Eureka整合的类就是DiscoveryEnableNIWSServerList,同时在Dynam ...

  8. 【一起学源码-微服务】Feign 源码三:Feign结合Ribbon实现负载均衡的原理分析

    前言 前情回顾 上一讲我们已经知道了Feign的工作原理其实是在项目启动的时候,通过JDK动态代理为每个FeignClinent生成一个动态代理. 动态代理的数据结构是:ReflectiveFeign ...

  9. 【一起学源码-微服务】Feign 源码二:Feign动态代理构造过程

    前言 前情回顾 上一讲主要看了@EnableFeignClients中的registerBeanDefinitions()方法,这里面主要是 将EnableFeignClients注解对应的配置属性注 ...

随机推荐

  1. Hbase数据模型 时间戳

  2. Part17—触摸屏显身手—Part17.1—原理简介

  3. Android ListView批量选择(全选、反选、全不选)

    APP的开发中,会常遇到这样的需求:批量取消(删除)List中的数据.这就要求ListVIew支持批量选择.全选.单选等等功能,做一个比较强大的ListView批量选择功能是很有必要的,那如何做呢? ...

  4. Shell echo 命令

    Shell 的echo 指令与PHP的echo指令类似,都是用于字符串的输出.命令格式: echo string 您可以使用echo实现更复杂的输出格式控制. 1.显示普通字符串: echo &quo ...

  5. Android Animation动画实战(二):从屏幕底部弹出PopupWindow

    在这篇文章之前,我已经陆陆续续写了几篇博客,介绍了Android Animation是如何使用的,有还不明白的,可以点击查看: 1. Android Animation动画详解(一): 补间动画 2. ...

  6. oracle用UNION替换OR (适用于索引列)

    通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果. 对索引列使用OR将造成全表扫描. 注意, 以上规则只针对多个索引列有效. 如果有column没有被索引, 查询效率可能会因为你 ...

  7. 什么是HOOK技术

    https://zhidao.baidu.com/question/50557962.html HOOK技术是Windows消息处理机制的一个平台,应用程序可以在上面设置子程序以监视指定窗口的某种消息 ...

  8. 洛谷P2258 子矩阵 题解 状态压缩/枚举/动态规划

    作者:zifeiy 标签:状态压缩.枚举.动态规划 题目链接:https://www.luogu.org/problem/P2258 这道题目状态压缩是肯定的,我们需要用二进制来枚举状态. 江湖上有一 ...

  9. 2009年NOIP普及组复赛题解

    题目涉及算法: 多项式输出:模拟: 分数线划定:模拟.排序: 细胞分裂:质因数分解: 道路游戏:动态规划. 多项式输出 题目链接:https://www.luogu.org/problem/P1067 ...

  10. 程序中打开IE浏览器并访问指定地址

    最简单的方法 Process.Start("iexplore.exe");  //直接打开IE浏览器(打开默认首页)            Process.Start(" ...