• 负载均衡-ribbon源码解析


    负载均衡-ribbon源码解析

    1 @LoadBalanced注解

    /**
     * 基于ribbon调用服务及负载均衡
     * @return
     */
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    image-20230108140627021

    image-20230108140840917

    image-20230108141148123

    @Bean
    @ConditionalOnMissingBean
    public RestTemplateCustomizer restTemplateCustomizer(final LoadBalancerInterceptor loadBalancerInterceptor) {
        return (restTemplate) -> {
            // 获取拦截器
            List<ClientHttpRequestInterceptor> list = new ArrayList(restTemplate.getInterceptors());
            // 添加一个新的拦截器(负载均衡的拦截器,该拦截器就是在restTemplate发送请求之前执行)
            list.add(loadBalancerInterceptor);
            // 将拦截器设置到restTemplate中  该restTemplate就是在OrderApplication中添加了@LoadBalanced的注解
            restTemplate.setInterceptors(list);
        };
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    总上所属:@LoadBalanced就是对template起到标识作用,加了@LoadBalanced注解的template开启负载均衡

    2 源码解析

    1)通过restTemplate发起请求

    Result result = restTemplate.getForObject("http://product-server/product/" + id, Result.class);
    
    • 1

    2)执行拦截器的intercept方法

    public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
        URI originalUri = request.getURI();
        String serviceName = originalUri.getHost();
        Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
        // 调用loadBalancer的execute方法  loadBalancer:负载均衡器
        // serviceName:就是product-server
        return (ClientHttpResponse)this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3)查看RibbonLoadBalancerClient中的execute方法

    public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException {
        // 通过负载均衡器 
        ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);
        // 通过负载均衡器 接 负载均衡算法 获取服务实例
        Server server = this.getServer(loadBalancer, hint);
        if (server == null) {
            throw new IllegalStateException("No instances available for " + serviceId);
        } else {
            RibbonLoadBalancerClient.RibbonServer ribbonServer = new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));
            return this.execute(serviceId, (ServiceInstance)ribbonServer, (LoadBalancerRequest)request);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4)根据负载均衡算法获取服务实例

    protected Server getServer(ILoadBalancer loadBalancer, Object hint) {
        return loadBalancer == null ? null : loadBalancer.chooseServer(hint != null ? hint : "default");
    }
    
    • 1
    • 2
    • 3
    public Server chooseServer(Object key) {
        if (this.counter == null) {
            this.counter = this.createCounter();
        }
        this.counter.increment();
        if (this.rule == null) {
            return null;
        } else {
            try {
                // rule就是配置的负载均衡算法
                // choose就是根据指定的负载均衡算法获取服务实例
                return this.rule.choose(key);
            } catch (Exception var3) {
                logger.warn("LoadBalancer [{}]:  Error choosing server for key {}", new Object[]{this.name, key, var3});
                return null;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    // 默认的负载均衡器
    private static final IRule DEFAULT_RULE = new RoundRobinRule();
    
    • 1
    • 2

    }
    }
    }

    
    ```java
    // 默认的负载均衡器
    private static final IRule DEFAULT_RULE = new RoundRobinRule();
    
    • 1
    • 2
    • 3
    • 4
  • 相关阅读:
    flask创建步骤
    CV科研知识点总结(个人研究所有相关知识点)
    PAT 1137 Final Grading
    文件或目录损坏且无法读取
    一行代码第五章
    用于大规模 MIMO 检测的近似消息传递 (AMP)(Matlab代码实现)
    CNN学习笔记
    window环境下安装node.js8+angular6
    android 中Handle弱引用使用
    Linux | 1.Linux环境与版本
  • 原文地址:https://blog.csdn.net/SurepMan/article/details/132828245