Spring Cloud的负载均衡是通过Ribbon组件完成的。Ribbon主要提供客户侧的软件负载均衡算法。Spring Cloud中的RestTemplate和Feign客户端底层的负载均衡都是通过Ribbon实现的。

背景信息

Spring Cloud AliCloud Ans集成了Ribbon的功能,AnsServerList实现了Ribbon提供的com.netflix.loadbalancer.ServerList接口。

这个接口是通用的,其它类似的服务发现组件例如Nacos、Eureka、Consul、ZooKeeper也都实现了对应的ServerList接口,例如NacosServerList、DomainExtractingServerList、ConsulServerList、ZookeeperServerList等。

实现该接口相当于接入了Spring Cloud负载均衡规范,这个规范是共用的。这也意味着,从Eureka、Consul、ZooKeeper等服务发现方案切换到Spring Cloud Alibaba方案,在负载均衡这个层面,无需修改任何代码,RestTemplate、FeignClient,包括已过时的AsyncRestTemplate,都是如此。

说明 EDAS兼容Hystrix,但是前提是客户端需要用户自己引入Hystrix的依赖。支持fallback属性,也可以通过Sentinel实现。

在本地开发应用时,可以使用 Alibaba Cloud Toolkit 插件实现本地应用和部署在 EDAS 中的应用的相互调用,即端云互联,而无需搭建 VPN,帮助您提升开发效率。详情请参见端云互联简介

本地开发中主要描述开发中涉及的关键信息,如果您想了解完整的Spring Cloud程序,可下载service-providerservice-consumer

RestTemplate和Feign的实现方式有所不同,下面将分别介绍如何在您的应用中实现RestTemplate和Feign的负载均衡用法。

RestTemplate

RestTemplate是Spring提供的用于访问REST服务的客户端,提供了多种便捷访问远程HTTP服务的方法,能够大大提高客户端的编写效率。

您需要在您的应用中按照下面的示例修改代码,以便使用RestTemplate的负载均衡。

public class MyApp {
    // 注入刚刚使用 @LoadBalanced注解修饰构造的RestTemplate
    // 该注解相当于给RestTemplate加上了一个拦截器:LoadBalancerInterceptor
    // LoadBalancerInterceptor内部会使用LoadBalancerClient接口的实现类RibbonLoadBalancerClient完成负载均衡
    @Autowired
    private RestTemplate restTemplate;

    @LoadBalanced // 使用 @LoadBalanced注解修改构造的RestTemplate,使其拥有一个负载均衡功能
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    // 使用RestTemplate调用服务,内部会使用负载均衡调用服务public void doSomething() {
        Foo foo = restTemplate.getForObject("http://service-provider/query", Foo.class);
        doWithFoo(foo);
    }

    ...
}            

Feign

Feign是一个Java实现的HTTP客户端,用于简化RESTful调用。

配合 @EnableFeignClients和 @FeignClient完成负载均衡请求。

  1. 使用 @EnableFeignClients开启Feign功能。
    @SpringBootApplication
    @EnableFeignClients // 开启Feign功能public class MyApplication {
      ...
    }                        
  2. 使用 @FeignClient构造FeignClient。
    @FeignClient(name = "service-provider")
    public interface EchoService {
            @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
            String echo(@PathVariable("str") String str);
    }                        
  3. 注入EchoService并完成echo方法的调用。
    调用echo方法相当于发起了一个HTTP请求。
    public class MyService {
    @Autowired // 注入刚刚使用 @FeignClient注解修饰构造的EchoService
        private EchoService echoService;
    
        public void doSomething() {
        // 相当于发起了一个http://service-provider/echo/test请求echoService.echo("test");
            }
        ...
    }                        

结果验证

service-consumer和多个serveice-provider启动后,访问service-consumer提供的URL确认是否实现了负载均衡。

  • RestTemplate

    多次访问/echo-rest/rest-test查看是否转发到不同的实例。

  • Feign

    多次访问/echo-feign/feign-test查看是否转发到不同的实例。