欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-28 15:46:01
1. Eureka源码探索(一) 客户端服务端的启动和负载均衡 1.1. 服务端 1.1.1. 找起始点 1. 目前唯一知道的,就是启动Eureka服务需要添加注解 ,但是暂时找不到它被使用的地方 2. 看日志,明显有打印discovery client,服务端同时也用作客户端,因为它可以相互注册, ......

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

1.1. 服务端

1.1.1. 找起始点

  1. 目前唯一知道的,就是启动eureka服务需要添加注解@enableeurekaserver,但是暂时找不到它被使用的地方
  2. 看日志,明显有打印discovery client,服务端同时也用作客户端,因为它可以相互注册,以下是自动配置类
    Eureka源码探索(一)-客户端服务端的启动和负载均衡
  3. 知道了客户端有自动配置类,可以想象服务端也应该有,找到相应的包,发现果然有
    Eureka源码探索(一)-客户端服务端的启动和负载均衡

1.1.2. 服务初始化

  1. 启动初始化
    Eureka源码探索(一)-客户端服务端的启动和负载均衡
  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,则启动配置生效

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

1.2. 客户端

1.2.1. 调用解析过程

  1. resttemplate调用
resttemplate.getforentity("http://eureka-server", string.class);
  1. 在不断深入后,最终处理的是一个拦截器
    Eureka源码探索(一)-客户端服务端的启动和负载均衡
  2. 拦截器进的实际处理类是loadbalancerinterceptor
    Eureka源码探索(一)-客户端服务端的启动和负载均衡
  3. 但里面实际的负载均衡调用loadbalancer又是ribbonloadbalancerclient
    Eureka源码探索(一)-客户端服务端的启动和负载均衡
  4. 这就真真的进了ribbon的负载均衡调用了,至于这个ribbonloadbalancerclient怎么注入进来的,这也简单,这里有两层关系,该loadbalancerinterceptor如何实例化的,和ribbonloadbalancerclient如何实例化并注入的,可以看如下图
    Eureka源码探索(一)-客户端服务端的启动和负载均衡
    Eureka源码探索(一)-客户端服务端的启动和负载均衡
    Eureka源码探索(一)-客户端服务端的启动和负载均衡
  5. 好了,不扯开去了,继续解析服务名,实际上,接下来就是ribbonloadbalancerclient的实现了
    Eureka源码探索(一)-客户端服务端的启动和负载均衡
  6. 继续深入
    Eureka源码探索(一)-客户端服务端的启动和负载均衡
  7. 轮询核心算法
    Eureka源码探索(一)-客户端服务端的启动和负载均衡

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注掉