• 负载均衡-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
  • 相关阅读:
    【PowerShell代码】清除掉文件中的非英文字母
    栈与队列2——用栈实现队列
    XSD 初学
    提高生产力和降低成本:CISO的网络安全绩效指标
    项目整个管理论文之2
    GPT-4 来了!这些开源的 GPT 应用又要变强了
    百度校园招聘历年经典面试题汇总:开发测试岗
    go 定时清理函数 --chatGPT
    IOS OpenGL ES GPUImage 图像阈值边缘检测GPUImageThresholdEdgeDetectionFilter
    2023如何做谷歌收录?
  • 原文地址:https://blog.csdn.net/SurepMan/article/details/132828245