这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战
前言
我们从上节的Eureka的学习,了解到了服务的发现和注册。在这的基础之上,我们可以来学习服务间的负载均衡。
目前主流的负载方案
- 集中式负载均衡,在消费者和服务提供方中间使用独立的代理方式进行负载,有硬件的(比如 F5),也有软件的(比如 Nginx)。
- 客户端自己做负载均衡,根据自己的请求情况做负载,Ribbon 就属于客户端自己做负载。
服务调用各类技术
| 技术 | 所属 | 介绍 |
|---|---|---|
| Ribbon | Netflix | 基于 HTTP 和 TCP 的客户端负载均衡工具 |
| Feign | Spring Cloud组件 | Feign集成了Ribbon(现在不在维护了) |
| Openfeign | Spring Cloud组件 | Feign的升级版 |
Ribbon的概念
官网上提到:Ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡工具,它基于 Netflix Ribbon 实现。Spring Cloud Ribbon 虽然只是一个工具类框架,它不像服务注册中心、配置中心、API 网关那样需要独立部署,但是它几乎存在于每一个 Spring Cloud 构建的微服务和基础设施中。因为微服务间的调用,API 网关的请求转发等内容,实际上都是通过 Ribbon 来实现的。
Ribbon的使用
首先我们在配置两个服务一个是一个是8083的端口,一个是8081的端口
Maven注入依赖
以下是Maven中引用ribbon
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-core</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-loadbalancer</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxjava</artifactId>
<version>1.0.10</version>
</dependency>
Demo代码
// 服务列表
List<Server> serverList = Lists.newArrayList(new Server("localhost", 8081), new Server("localhost", 8083));
// 构建负载实例
ILoadBalancer loadBalancer = LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(serverList);
// 调用 5 次来测试效果
for (int i = 0; i < 5; i++) {
String result = LoadBalancerCommand.<String>builder().withLoadBalancer(loadBalancer).build()
.submit(new ServerOperation<String>() {
public Observable<String> call(Server server) {
try {
String addr = "http://" + server.getHost() + ":" + server.getPort() + "
/hellow/api";
System.out.println(" 调用地址:" + addr);
URL url = new URL(addr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.connect();
InputStream in = conn.getInputStream();
byte[] data = new byte[in.available()];
in.read(data);
return Observable.just(new String(data));
} catch (Exception e) {
return Observable.error(e);
}
}
}).toBlocking().first();
System.out.println(" 调用结果:" + result);
}
调用的结果:
我们可以看出负载均衡的默认算法是轮询,我们也可以在Ribbon中定义自己的查询算法。
选择负载均衡策略注入
/**
* Ribbon的默认轮询算法重置
*/
@Configuration
public class MySelfRule {
@Bean
public IRule myRule(){
return new RandomRule();//定义为随机
}
}
负载均衡策略扩展:
1)BestAvailabl
选择一个最小的并发请求的 Server,逐个考察 Server,如果 Server 被标记为错误,则跳过,然后再选择 ActiveRequestCount 中最小的 Server。
2)AvailabilityFilteringRule
过滤掉那些一直连接失败的且被标记为 circuit tripped 的后端 Server,并过滤掉那些高并发的后端 Server 或者使用一个 AvailabilityPredicate 来包含过滤 Server 的逻辑。其实就是检查 Status 里记录的各个 Server 的运行状态。
3)ZoneAvoidanceRule
使用 ZoneAvoidancePredicate 和 AvailabilityPredicate 来判断是否选择某个 Server,前一个判断判定一个 Zone 的运行性能是否可用,剔除不可用的 Zone(的所有 Server),AvailabilityPredicate 用于过滤掉连接数过多的 Server。
4)RandomRule
随机选择一个 Server。
5)RoundRobinRule
轮询选择,轮询 index,选择 index 对应位置的 Server。
6)RetryRule
对选定的负载均衡策略机上重试机制,也就是说当选定了某个策略进行请求负载时在一个配置时间段内若选择 Server 不成功,则一直尝试使用 subRule 的方式选择一个可用的 Server。
7)ResponseTimeWeightedRule
作用同 WeightedResponseTimeRule,ResponseTime-Weighted Rule 后来改名为 WeightedResponseTimeRule。
8)WeightedResponseTimeRule
根据响应时间分配一个 Weight(权重),响应时间越长,Weight 越小,被选中的可能性越低。
总结
今天写的内容只是其中的一部分,Ribbon的功能很强大,不过我们在开发的时候还是要更具项目的情况来取舍架构,因为在分布式的项目中,不光只是Ribbon可以作为客户端的负载均衡,我们也可以通过nginx等来进行负载均衡。
手写不易,还需大家多多点赞和专注,喜欢技术的同学们不要心急,此系列文章我将逐步推出,我们大家一起学习。