RestTemplate和Ribbon实现客户端负载均衡原理

前言

  在SpringCloud的微服务场景中,服务之间调用,我们通常使用Feign来实现。不过通过RestTemplate也能实现对服务请求的负载均衡,本文对RestTemplate的负载均很实现方式做一下简单的分析说明。
  关于RestTemplate的原理 RestTemplate源码分析一文中已做说明,本文不再细说。

RestTemplate实现负载均

  1. 定义微服务注册中心
      本文以consul作为注册中心,注册中心的配置启动,这里不做细说。在这里插入图片描述
  2. 服务提供方多个实例,并且都注册到了注册中心
      如上图所示,服务提供方service-provider注册了两个实例,都已注册到注册中心,端口分别为9090,9099
  3. 调用方使用RestTemplate的条件
    I、服务发现: 客户端在使用之前需要知道服务提供方的接口请求地址。
      	<--项目中需要引入ribbon-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

II、声明RestTemplate

    @LoadBalanced
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

III、在代码中使用

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("rest/test")
    public Response<UserDto>  getUserInfoByRestTemplate(@RequestParam("userId") String userId) {
        ParameterizedTypeReference<Response<UserDto>> responseBodyType = new ParameterizedTypeReference<Response<UserDto>>() {};

        ResponseEntity<Response<UserDto>> result = restTemplate.exchange("http://service-provider/inner/entities?userId={userId}", HttpMethod.GET,
                new HttpEntity<>(null),responseBodyType,userId);
        log.info("get service provider result:{}",result.getBody());
        return result.getBody();
    }
//执行两次请求后,打印日志如下。
2021-10-30 21:00:47.050  INFO 77602 --- [nio-8080-exec-1] c.z.d.interfaces.SomeController          : get service provider result:Response{code=200, message='null', data=UserDto(id=2, userName=name2,port:9090)}
2021-10-30 21:00:58.806  INFO 77602 --- [nio-8080-exec-5] c.z.d.interfaces.SomeController          : get service provider result:Response{code=200, message='null', data=UserDto(id=2, userName=name2,port:9099)}

  可以发现,通过以上步骤,RestTemplate已经实现了负载均很

RestTemplate实现负载均原理

LoadBalanced注解

在这里插入图片描述
  LoadBalanced是一个注解,在其申明中包含了@Qualifier注解。我们可以简单理解LoadBalanced注解是一个标记,在我们需要使用必需带有这个标记注解的时候,只需要再次引用LoadBalanced注解即可。

    @LoadBalanced
    @Bean
    public RestTemplate restTemplate1(){
        return new RestTemplate();
    }
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate2(){
        return new RestTemplate();
    }
 	@Bean
    public RestTemplate restTemplate3(){
        return new RestTemplate();
    }
.......
	@LoadBalanced
	@Autowired(required = false)
	private List<RestTemplate> restTemplates = Collections.emptyList();
	//这里的restTemplates包含了restTemplate1,restTemplate2,不包含restTemplate3

RestTemplateCustomizer

  RestTemplateCustomizer是一个接口,定义了对RestTemplate的扩展。RestTemplate源码分析一文中介绍了RestTemplate各个组件,都是可以被我们自定义扩展的。
在这里插入图片描述
  我们可以在RestTemplateCustomizer的实现类中修改RestTemplate的HttpMessageConverter、ClientHttpRequestFactory、ClientHttpRequestInterceptor等等。

LoadBalancerAutoConfiguration

  LoadBalancerAutoConfiguration这是一个自动配置类。下图中红色1部分,表示收集了所有被LoadBalanced标记过的RestTemplate对象,红色2部分,表示如果RestTemplateCustomizer对象有具体的实现bean,则用他们对所有收集到的RestTemplate对象执行了自定义修改RestTemplate的操作。
在这里插入图片描述
  通过以上两部分我们基本可以猜测,ribbon中必然实现了自定义的RestTemplateCustomizer对象,这个对象会扩展RestTemplate的拦截器接口ClientHttpRequestInterceptor,只有这样我们才可以在请求前将服务名替换为具体的ip地址和端口号。
在这里插入图片描述
  如上图,在LoadBalancerInterceptorConfig中(它是LoadBalancerAutoConfiguration的内部类),声明了LoadBalancerInterceptor的bean对象,LoadBalancerInterceptor实现了接口ClientHttpRequestInterceptor。并且LoadBalancerInterceptor通过一个匿名RestTemplateCustomizer对象,最终添加到RestTemplate的interceptors中。

LoadBalancerInterceptor

  通过以上分析,我们已经知道RestTemplate的最终负载均很扩展需要靠LoadBalancerInterceptor的实现。
在这里插入图片描述
  在LoadBalancerInterceptor的intercept的拦截器方法中,具体的服务名如何与ip:port进行替换,委托给了LoadBalancerClient对象。LoadBalancerClient是Ribbon的核心类,本文不做特别分析,后续文章会对次做详细讲解。

总结

  至此,我们已经明白RestTemplate是如何通过@LoadBalanced注解实现负载均很的。

  1. 声明一个带@LoadBalanced注解的RestTemplate对象
  2. Ribbon的自动配置类LoadBalancerAutoConfiguration会收集所有被@LoadBalanced标记过的RestTemplate
  3. Ribbon中的类LoadBalancerInterceptor实现RestTemplate的扩展接口ClientHttpRequestInterceptor,LoadBalancerInterceptor类将负载均衡委托给Ribbon的底层类。
  4. Ribbon将LoadBalancerInterceptor类通过RestTemplateCustomizer最终注册到收集的RestTemplate的intercepts中。
  5. 这样,RestTemplate通过加载ClientHttpRequestInterceptor的扩展,就实现了负载均衡
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值