Spring Cloud Ribbon源码详解

本文详细探讨了Spring Cloud Ribbon的源码实现,包括负载均衡RestTemplate的原理,LoadBalancerClient的工作方式,Ribbon的负载均衡策略定制,以及如何通过Eureka获取服务地址。通过分析RibbonAutoConfiguration和LoadBalancerAutoConfiguration,揭示了RestTemplate在负载均衡中的作用,同时讲解了RibbonLoadBalancerClient如何选择服务器节点。此外,还讨论了修改LB策略的两种方法,并梳理了服务地址获取的优先级顺序。
摘要由CSDN通过智能技术生成

目录

代码示例

LB实现原理

负载均衡RestTemplate实现原理

LoadBalancerClient实现原理

Ribbon修改LB策略

Ribbon如何获取服务地址

Ribbon如何通过Eureka获取服务地址


Java版本:1.8

Spring版本:5.1.8.RELEASE

Spring Boot版本:2.1.6.RELEASE

Spring Cloud版本:Greenwich.SR1

代码示例

通过服务发现,客户端可以获取某个服务的所有可用服务地址,此时我们需要客户端负载均衡,以便将客户端请求按照特定方式分摊到各个服务地址上

稍微改造一下之前的Test-Client(代码参考https://blog.csdn.net/a19881029/article/details/100585120),由于spring-cloud-starter-netflix-eureka-client中包含Ribbon相关依赖(见如下pom依赖)

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
	<groupId>com.netflix.ribbon</groupId>
	<artifactId>ribbon-eureka</artifactId>
</dependency>

因此不需要修改pom文件

修改RestTemplateConfig在普通RestTemplate的基础上增加负载均衡RestTemplate 

package com.sean;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

/**
 * Created by seanzou on 2019/9/10.
 */
@Configuration
public class RestTemplateConfig {

    @Bean(name = "normalTemplate")
    public RestTemplate normalTemplate(ClientHttpRequestFactory clientHttpRequestFactory){
        return new RestTemplate(clientHttpRequestFactory);
    }

    @Bean(name = "loadBalanceTemplate")
    @LoadBalanced
    public RestTemplate restTemplate(ClientHttpRequestFactory clientHttpRequestFactory){
        return new RestTemplate(clientHttpRequestFactory);
    }

    @Bean
    public ClientHttpRequestFactory clientHttpRequestFactory() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setReadTimeout(5000);//ms
        factory.setConnectTimeout(5000);//ms
        return factory;
    }
}

修改TestService并使用LoadBalancerClient替换之前的DiscoveryClient,通过LoadBalancerClient+普通RestTemplate或者负载均衡RestTemplate两种方式请求服务

package com.sean;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

/**
 * Created by seanzou on 2019/9/24.
 */
public class TestLoadBalancerRequest implements LoadBalancerRequest<String> {

    private String path;
    private RestTemplate restTemplate;

    @Override
    public String apply(ServiceInstance instance) throws Exception {
        String host = instance.getHost();
        Integer port = instance.getPort();

        ResponseEntity responseEntity = restTemplate.getForEntity("http://" + host + ":" + port + path, String.class);
        if(responseEntity != null && responseEntity.getStatusCode() != null &&
                responseEntity.getStatusCode().is2xxSuccessful()){
            String resp = (String)responseEntity.getBody();
            return resp;
        }
        return null;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public RestTemplate getRestTemplate() {
        return restTemplate;
    }

    public void setRestTemplate(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }
}
package com.sean;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;

/**
 * Created by seanzou on 2019/7/10.
 */
@Component
public class TestService {

    @Autowired
    private RestTemplate normalTemplate;

    @Autowired
    private RestTemplate loadBalanceTemplate;

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    public void test() {
        System.out.println("start loadBalancerClient querying");
        TestLoadBalancerRequest req = new TestLoadBalancerRequest();
        req.setPath("/name");
        req.setRestTemplate(normalTemplate);
        for(int i = 0 ; i < 10 ; i++){
            try {
                String resp = loadBalancerClient.execute("test-service", req);
                System.out.println(resp);
            } catch (IOException e) {
                System.out.println(e.getMessage());
            }
        }

        System.out.println("start restTemplate querying");
        for(int i = 0 ; i < 10 ; i++){
            ResponseEntity responseEntity = loadBalanceTemplate.getForEntity("http://test-service/name", String.class);
            if(responseEntity != null && responseEntity.getStatusCode() != null &&
                    responseEntity.getStatusCode().is2xxSuccessful()){
                String resp = (String)responseEntity.getBody();
                System.out.println(resp);
            }
        }
    }
}

启动Test-Client后访问http://localhost:8090/test以调用测试代码,后端日志输出如下

start loadBalancerClient querying
sean
sean two
sean
sean two
sean
sean two
sean
sean two
sean
sean two
start restTemplate querying
sean
sean two
sean
sean two
sean
sean two
sean
sean two
sean
sean two

LB实现原理

我们从pom文件开始

spring-cloud-starter-netflix-eureka-client依赖spring-cloud-starter-netflix-ribbon

spring-cloud-starter-netflix-ribbon依赖spring-cloud-netflix-ribbon

spring-cloud-netflix-ribbon的代码结构如下

spring.factories配置中指定了AutoConfiguration类 

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration

RibbonAutoConfiguration类十分关键,Ribbon自动创建对象以及自动加载配置的逻辑都在这个类中

在上面的示例中我们使用了两种调用方式,分别是LoadBalancerClient+普通RestTemplate或者负载均衡RestTemplate两种方式请求服务,下面我们兵分两路

负载均衡RestTemplate实现原理

RibbonAutoConfiguration类中有如下注解

@AutoConfigureBefore({ LoadBalancerAutoConfiguration.class,
		AsyncLoadBalancerAutoConf
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值