一、概述
前面一节已经通过 RestTemplate 实现了服务消费者对服务提供者的调用,这只是实现了最基本的需求,如果在某个具体的业务场景下,对于某服务的调用需求激增,这时候我们就需要为该服务实现负载均衡以满足高并发访问,在一个大型的分布式应用系统中,负载均衡(Load Balancing)是必备的。
二、Spring Cloud Ribbon
Spring Cloud 提供了实现负载均衡的解决方案:Spring Cloud Ribbon,Ribbon 是 Netflix 发布的负载均衡器,而 Spring Cloud Ribbon 则是基于 Netflix Ribbon 实现的,是一个用于对 HTTP 请求进行控制的负载均衡客户端。
Ribbon 的使用同样需要结合 Eureka Server,即需要将 Ribbon 在 Eureka Server 进行注册,注册完成之后,就可以通过 Ribbon 结合某种负载均衡算法,如轮询、随机、加权轮询、加权随机等帮助服务消费者去调用接口。除了 Ribbon 默认提供的这些负载均衡算法外,开发者也可以根据具体需求来设计自定义的 Ribbon 负载均衡算法。实际开发中,Spring Cloud Ribbon 需要结合 Spring Cloud Eureka 来使用,Eureka Server 提供所有可调用的服务提供者列表,Ribbon 基于特定的负载均衡算法从这些服务提供者中挑选出要调用的实例,如下图所示。
Ribbon 常用的负载均衡策略有以下几种:
- 随机:访问服务时,随机从注册中心的服务列表中选择一个。
- 轮询:当同时启动两个服务提供者时,客户端请求会由这两个服务提供者交替处理。
- 加权轮询:对服务列表中的所有微服务响应时间做加权处理,并以轮询的方式来访问这些服务。
- 最大可用:从服务列表中选择并发访问量最小的那个微服务。
三、 代码实现
要实现简单的Ribbon 负载均衡实际上在前面服务消费者工程中修改以下配置:
在RestTemplate 实例上添加注解@LoadBalanced声明一个基于 Ribbon 的负载均衡,如下所示:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
@Bean
@LoadBalanced //@LoadBalanced:声明一个基于 Ribbon 的负载均衡。
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
相关业务方法使用RestTemplate 调用provider 服务调用时,通过RestTemplate 访问的 URL 不需要指定 IP 和 端口,直接访问 Provider 在 Eureka Server 注册的 application name 即可,比如:http://localhost:8010/ 可替换为 http://provider/。
@RestController
@RequestMapping("/consumer")
public class StudentHandler {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/index")
public String index(){
/**
*
* 在 RestTemplate 配置上添加注解:@LoadBalanced
* 基于 Ribbon 的负载均衡
* 通过 RestTemplate 调用 Provider 相关接口,
* RestTemplate 访问的 URL 不需要指定 IP 和 端口,直接访问 Provider 在 Eureka Server 注册的 application name 即可,
* 比如:http://localhost:8010/ 必须替换为 http://provider/。
*/
return restTemplate.getForObject("http://provider/student/index",String.class);
}
@GetMapping("/findAll")
public Collection<Student> findAll(){
// return restTemplate.getForObject("http://localhost:8010/student/findAll",Collection.class);
return restTemplate.getForObject("http://provider/student/findAll",Collection.class);
}
// .....完整实现参考https://gitee.com/zhengj/myspringcloud.git......
}
依次启动注册中心、
服务提供者 provider, 修改provider端口再启动一次(模拟2台服务器上同一服务提供者)
并运行 ConsumerApplication。
此时访问provider 服务则会交替访问8011 和8012端。
四、总结
使用 Ribbon 来实现服务调用负载均衡的具体操作,Ribbon 是 Netflix 发布的负载均衡器,Ribbon 的功能是结合某种负载均衡算法,如轮询、随机、加权轮询、加权随机等帮助服务消费者去调用接口,同时也可以自定义 Ribbon 的负载均衡算法。
完整demo下载地址: