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. 工作流引擎Activiti 专题

    https://github.com/Activiti/Activiti Quick Start Guide This quick start assumes: Familiarity with Ma ...

  2. OAuth 2 开发人员指南(Spring security oauth2)

    https://github.com/spring-projects/spring-security-oauth/blob/master/docs/oauth2.md 入门 这是支持OAuth2.0的 ...

  3. 值得注意的CSS属性

    文本TEXT letter-spacing 字符间距 word-spacing 字间距 line-height 行高 text-decoration 修饰(下划线) text-indent 首行缩进 ...

  4. 测试网页时需要添加等待的情形 (Selenium)

    测试网页时需要添加等待的情形: 1. 网页跳转 2. DOM结构发生改变.

  5. 时间戳转换成时间js(年-月-日,例如“2017-04-22”)

    function GetDateByShiJianChuo(timespan) { var date = new Date(parseInt(timespan.replace("/Date( ...

  6. SQL 如何在自增列插入指定数据

    SQL Server  中数据表往往会设置自增列,常见的比如说 首列的ID列. 往数据表插入新数据的时候,自增列是跳过的,无需插入即会按照设置的自增规则进行列增长.那么,如果我们想往自增列插入我们指定 ...

  7. Android代码混淆的问题解决(java.io.FileNotFoundException)

    Android Studio(2.3.3) 在给代码混淆时,提示: Warning:Exception while processing task java.io.FileNotFoundExcept ...

  8. Mysql8.0命令

    1.创建用户 create user 'username'@'localhost' identified by 'pwd' 2.修改访问权限 在mysql数据下修改user表用户host为'%' up ...

  9. C++的代理类

    怎样在一个容器中包含类型不同,但是彼此有关系的对象?众所周知,C++的容器只能存放类型相同的元素,所以直接在一个容器中存储不同类型的对象本身是不可能的,只能通过以下两种方案实现: 1. 提供一个间接层 ...

  10. Arduino入门笔记(6):温度传感器及感温杯实验

    转载请注明:@小五义 http://www.cnblogs.com/xiaowuyi 欢迎加入讨论群 64770604 一.本次实验所需器材 1.Arduino板 :https://item.taob ...