负载均衡
目前主流的负载方案分为以下两种:
• 集中式负载均衡:在消费者和服务提供方中间使用独立的代理方式进行负载,有硬件的(比如 F5),也有软件的(比如 Nginx)。
也就是服务器端负载均衡,请求到达后端服务器之后由这些负载均衡器根据⼀定的算法将请求路由到⽬标服务器处理。
• 客户端负载均衡,根据自己的请求情况做负载,Ribbon 就属于客户端自己做负载。服务消费者客户端会有⼀个服务器地址列表,调⽤⽅在请求前通过⼀定的负载均衡算法选择⼀个服务器进⾏访问,负载均衡算法的执⾏是在请求客户端进⾏。
一、SpringCloud Ribbon简介
Spring Cloud Ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡工具,它基于 Netflix Ribbon 实现。
通过 Spring Cloud 的封装,可以让我们轻松地将面向服务的 REST 模版请求自动转换成客户端负载均衡的服务调用。
二、Ribbon在Spring Cloud中的使用
1.使用 RestTemplate 与整合 Ribbon
Spring 提供了一种简单便捷的模板类来进行 API 的调用,那就是 RestTemplate。(在SpringCloud入门 —— Eureka服务注册与发现已经使用过restTemplate)
新建一个同之前一样的服务(端口不同),作为服务提供者(可看做是一个“小集群”)
测试代码:
@Value("${server.port}")
private String port;
@GetMapping("/ribbonTest")
public String ribbonTest() {
return "我是服务提供者 -- 我的端口是:" + port;
服务消费者
在服务消费者中已经引入了eureka-client依赖,这里就不用加入其他的依赖了,因为 Eureka 中已经引用了 Ribbon。
RestTemplate配置,加上LoadBalanced注解实现负载均衡
package com.local.springboot.client.clientcustomer.config;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
测试代码:
/**
* 访问服务
*/
private static final String REST_URL_PREFIX = "http://CLIENT-PROVIDER-SERVER";
/**
* restTemplate负载均衡测试
*
* @return
*/
@RequestMapping("/restTemplate/testRibbon")
public String testRibbon2() {
// 使用restTemplate发起请求
String result = restTemplate.getForEntity(REST_URL_PREFIX + "/api/ribbonTest", String.class).getBody();
return result;
}
启动服务注册中心,访问Eureka(localhost:8080),三个服务已经注册
测试接口,消费者调用http://localhost:8082/restTemplate/testRibbon,Ribbon会从注册中心的服务列表拉取实例集合进行负载均衡调用背后的服务提供者,如下图所示:
2.使用 Feign客户端
Feign客户端实际是对Ribbon进行了一个封装;spring-cloud-starter-feign 里面已经包含了 spring-cloud-starter-ribbon
不熟悉Feign调用,请戳SpringCloud入门 —— Feign服务调用
测试代码:
服务消费者
/**
* feign负载均衡测试
*
* @return
*/
@RequestMapping("/feign/testRibbon")
public String testRibbon1() {
return myFeign.ribbonTest();
}
@FeignClient(value = "client-provider-server", path = "/api", fallback = MyFeignFallback.class
, fallbackFactory = MyFeignFallbackFactory.class)
public interface MyFeign {
@GetMapping("/ribbonTest")
String ribbonTest();
}
效果如下:
三、Ribbon负载均衡策略
Ribbon 作为一款客户端负载均衡框架,默认的负载策略是轮询,同时也提供了很多其他的策略,能够让用户根据自身的业务需求进行选择。
负载均衡策略 | 描述 |
---|---|
RoundRobinRule | 轮询选择,轮询 index,选择 index 对应位置的 Server。 |
BestAvailabl | 选择一个最小的并发请求的 Server,逐个考察 Server,如果 Server 被标记为错误,则跳过,然后再选择 ActiveRequestCount 中最小的 Server。 |
AvailabilityFilteringRule | 过滤掉那些一直连接失败的且被标记为 circuit tripped 的后端 Server,并过滤掉那些高并发的后端 Server 或者使用一个 AvailabilityPredicate 来包含过滤 Server 的逻辑。其实就是检查 Status 里记录的各个 Server 的运行状态。 |
ZoneAvoidanceRule | 使用 ZoneAvoidancePredicate 和 AvailabilityPredicate 来判断是否选择某个 Server,前一个判断判定一个 Zone 的运行性能是否可用,剔除不可用的 Zone(的所有 Server),AvailabilityPredicate 用于过滤掉连接数过多的 Server。 |
RandomRule | 随机选择一个 Server。 |
RetryRule | 对选定的负载均衡策略机上重试机制,也就是说当选定了某个策略进行请求负载时在一个配置时间段内若选择 Server 不成功,则一直尝试使用 subRule 的方式选择一个可用的 Server。 |
ResponseTimeWeightedRule | 作用同 WeightedResponseTimeRule,ResponseTime-Weighted Rule 后来改名为 WeightedResponseTimeRule。 |
WeightedResponseTimeRule | 根据响应时间分配一个 Weight(权重),响应时间越长,Weight 越小,被选中的可能性越低。 |
代码配置Ribbon
@Configuration
public class RibbonConfig {
@Bean
public IRule ribbonRule(){
return new RandomRule(); //分配策略:随机选择一个server
// return new BestAvailableRule(); //分配策略:选择一个最小的并发请求的server,逐个考察Server,如果Server被tripped了,则忽略
// return new RoundRobinRule(); //分配策略:轮询选择,轮询index,选择index对应位置的server
// return new WeightedResponseTimeRule(); //分配策略:根据响应时间分配一个weight(权重),响应时间越长,weight越小,被选中的可能性越低
// return new ZoneAvoidanceRule(); //分配策略:复合判断server所在区域的性能和server的可用性选择server
// return new RetryRule(); //分配策略:对选定的负载均衡策略机上重试机制,在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server
}
@Bean
public IPing ribbonPing() {
return new PingUrl();
}
@Bean
public ServerListSubsetFilter serverListFilter() {
ServerListSubsetFilter filter = new ServerListSubsetFilter();
return filter;
}
}
启动类上加上@RibbonClient(name = "client-provider-server", configuration = RibbonConfig.class)
,关联 RibbonConfig ,用 name 来指定调用的服务名称。
配置文件配置 Ribbon
<clientName>.ribbon.NFLoadBalancerClassName: Should implement ILoadBalancer(负载均衡器操作接口)
<clientName>.ribbon.NFLoadBalancerRuleClassName: Should implement IRule(负载均衡算法)
<clientName>.ribbon.NFLoadBalancerPingClassName: Should implement IPing(服务可用性检查)
<clientName>.ribbon.NIWSServerListClassName: Should implement ServerList(服务列表获取)
<clientName>.ribbon.NIWSServerListFilterClassName: Should implement ServerListFilter(服务列表的过滤)
更多配置请查看官方文档
创作不易,关注、点赞就是对作者最大的鼓励,欢迎在下方评论留言
求关注,定期分享Java知识,一起学习,共同成长。
« 上一章:SpringCloud入门 —— Feign服务调用
» 下一章:SpringCloud入门 —— Zuul路由配置
网友评论