1. Eureka源码探索(一)-客户端服务端的启动和负载均衡

1.1. 服务端

1.1.1. 找起始点

  1. 目前唯一知道的,就是启动Eureka服务需要添加注解@EnableEurekaServer,但是暂时找不到它被使用的地方
  2. 看日志,明显有打印discovery client,服务端同时也用作客户端,因为它可以相互注册,以下是自动配置类

  3. 知道了客户端有自动配置类,可以想象服务端也应该有,找到相应的包,发现果然有

1.1.2. 服务初始化

  1. 启动初始化

  2. 接下来是个发布订阅方法,发布对象继承了Spring的ApplicationEvent,可以看出肯定会有订阅者接收该配置,配置内容就是我们application.properties里配置的属性,不配则是默认属性

1.1.3. @EnableEurekaServer起作用的原理

  1. 进入该注解,可以看到注解中还有个注解@Import它的作用就是将之后的类对象所对应的实例,实例化并加入spring容器管理
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EurekaServerMarkerConfiguration.class)
public @interface EnableEurekaServer { }
  1. 进入EurekaServerMarkerConfiguration类,可以看到如下,该类的作用仅仅用来标记下,为启动类判断是否需要启动EurekaServer
@Configuration
public class EurekaServerMarkerConfiguration { @Bean
public Marker eurekaServerMarkerBean() {
return new Marker();
} class Marker { } }
  1. 它具体被使用的地方如下,用一个@ConditionalOnBean表示,若存在该类Bean,则启动配置生效

1.2. 客户端

1.2.1. 调用解析过程

  1. restTemplate调用
restTemplate.getForEntity("http://eureka-server", String.class);
  1. 在不断深入后,最终处理的是一个拦截器

  2. 拦截器进的实际处理类是LoadBalancerInterceptor

  3. 但里面实际的负载均衡调用loadBalancer又是RibbonLoadBalancerClient

  4. 这就真真的进了Ribbon的负载均衡调用了,至于这个RibbonLoadBalancerClient怎么注入进来的,这也简单,这里有两层关系,该LoadBalancerInterceptor如何实例化的,和RibbonLoadBalancerClient如何实例化并注入的,可以看如下图





  5. 好了,不扯开去了,继续解析服务名,实际上,接下来就是RibbonLoadBalancerClient的实现了

  6. 继续深入

  7. 轮询核心算法

1.3. 模拟负载均衡调用

1.3.1. 代码直接上

@SpringBootApplication
@EnableDiscoveryClient
@RestController
@Slf4j
public class EurekaClientApplication { public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args);
}
@Autowired
private RestTemplate restTemplate; @Autowired
private DiscoveryClient discoveryClient; /**
* 使用Ribbon的负载均衡
* @return
*/
@GetMapping("/")
public ResponseEntity<String> getTime(){
return restTemplate.getForEntity("http://eureka-server", String.class);
} /**
* 模拟轮询负载的调用
* @return
*/
@GetMapping("/discovery")
public ResponseEntity<String> discovery(){
List<ServiceInstance> instances = discoveryClient.getInstances("eureka-server");
int i = incrementAndGetModule(instances.size());
return restTemplate.getForEntity(((EurekaDiscoveryClient.EurekaServiceInstance) instances.get(i)).getInstanceInfo().getHomePageUrl(), String.class);
} private AtomicInteger nextIndex = new AtomicInteger();
private int incrementAndGetModule(int module) {
for (; ; ) {
int current = nextIndex.get();
int next = (current + 1) % module;
if (nextIndex.compareAndSet(current,next) && current < module) {
return current;
}
}
} /**
* 加上@LoadBalanced该注解使用的Ribbon的负载均衡算法
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
  1. 这里用了Ribbon的负载均衡轮询算法和直接调用discoveryClient实现最简单的模拟轮询算法
  2. 注意,测试discovery的时候可以需要把@LoadBalanced注掉

Eureka源码探索(一)-客户端服务端的启动和负载均衡的更多相关文章

  1. Spring Cloud系列(三):Eureka源码解析之服务端

    一.自动装配 1.根据自动装配原理(详见:Spring Boot系列(二):Spring Boot自动装配原理解析),找到spring-cloud-starter-netflix-eureka-ser ...

  2. Ribbon源码分析(一)-- RestTemplate 以及自定义负载均衡算法

    如果只是想看ribbon的自定义负载均衡配置,请查看: https://www.cnblogs.com/yangxiaohui227/p/13186004.html 注意: 1.RestTemplat ...

  3. sofa-bolt源码阅读(1)-服务端的启动

    Bolt服务器的核心类是RpcServer,启动的时候调用父类AbstractRemotingServer的startup方法. com.alipay.remoting.AbstractRemotin ...

  4. Spring Cloud系列(四):Eureka源码解析之客户端

    一.自动装配 1.根据自动装配原理(详见:Spring Boot系列(二):Spring Boot自动装配原理解析),找到spring-cloud-netflix-eureka-client.jar的 ...

  5. Golang源码探索(二) 协程的实现原理(转)

    Golang最大的特色可以说是协程(goroutine)了, 协程让本来很复杂的异步编程变得简单, 让程序员不再需要面对回调地狱,虽然现在引入了协程的语言越来越多, 但go中的协程仍然是实现的是最彻底 ...

  6. 微服务之SpringCloud实战(四):SpringCloud Eureka源码分析

    Eureka源码解析: 搭建Eureka服务的时候,我们会再SpringBoot启动类加上@EnableEurekaServer的注解,这个注解做了一些什么,我们一起来看. 点进@EnableEure ...

  7. 4. 源码分析---SOFARPC服务端暴露

    服务端的示例 我们首先贴上我们的服务端的示例: public static void main(String[] args) { ServerConfig serverConfig = new Ser ...

  8. 【一起学源码-微服务】Nexflix Eureka 源码十:服务下线及实例摘除,一个client下线到底多久才会被其他实例感知?

    前言 前情回顾 上一讲我们讲了 client端向server端发送心跳检查,也是默认每30钟发送一次,server端接收后会更新注册表的一个时间戳属性,然后一次心跳(续约)也就完成了. 本讲目录 这一 ...

  9. 【一起学源码-微服务】Nexflix Eureka 源码十二:EurekaServer集群模式源码分析

    前言 前情回顾 上一讲看了Eureka 注册中心的自我保护机制,以及里面提到的bug问题. 哈哈 转眼间都2020年了,这个系列的文章从12.17 一直写到现在,也是不容易哈,每天持续不断学习,输出博 ...

随机推荐

  1. c# Socket通信异步TCP

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.N ...

  2. LeetCode Javascript实现 344. Reverse String 292. Nim Game 371. Sum of Two Integers

    344. Reverse String /** * @param {string} s * @return {string} */ var reverseString = function(s) { ...

  3. box-shadow 详解及示例

    box-shadow  [bɑks] - [ˈʃædoʊ]   英文示意: box:盒,包厢 shadow:阴影,渐变   定义: box-shadow: none | <shadow> ...

  4. 在腾讯云(windows)上搭建node.js服务器

    1:安装Node.js 使用MSI文件,并按照提示安装node.js,默认情况下,安装程序将 Node.js 发行到 C:\Program Files\nodejs. 但这里我们需要修改安装路径到:D ...

  5. (一)Servlet简介

    相关名词解释 HTML:Hyper Text Markup Language,超文本标记语言 HTTP:Hyper Text Transfer Protocol,超文本传输协议 URL:Uniform ...

  6. 【转】一则使用WinDbg工具调试iis进程调查内存占用过高的案例

    最近遇到一个奇葩内存问题,跟了三四天,把Windbg玩熟了,所以打算分享下. 症状简介 我们团队的DEV开发环境只有一台4核16G的win2012r2.这台服务器上装了SqlServer.TFS(项目 ...

  7. BZOJ_3238_[Ahoi2013]差异_后缀自动机

    BZOJ_3238_[Ahoi2013]差异_后缀自动机 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sam ...

  8. laravel 请求request 接收参数

    获取请求输入 获取所有输入值 你可以使用 all 方法以数组格式获取所有输入值: $input = $request->all(); 获取单个输入值 使用一些简单的方法,就可以从 Illumin ...

  9. 前端学习笔记之HTML body内常用标签

    阅读目录 一 HTML语义化 二 字符实体 三 h系列标签 四 p标签 五 img标签 六 a标签 七 列表标签 八 table标签 九 form标签 一 HTML语义化 body中的标签是会显示到浏 ...

  10. OSI七层协议与TCP连接

    概述 为了追求效率,我们写代码,不可能去关注底层知识,但往往到出了问题,或者性能调优.我们就会速手无策,仔细为自己查缺补漏,总结知识点. 网络协议 互联网的本质就是一系列的网络协议,让不同计算机能够互 ...