SpringCloud进阶-详细介绍客户端负载均衡器Ribbon
就目前来看,比较常用的负载均衡策略有两种方式,一种是集中式的负载均衡策略,也就是在服务消费者和服务提供者之间采用独立的方式进行代理进行负载均衡操作,例如硬件有F5、软件有Nginx这些的。当然,另一种就是今天我们所要说的这种策略,也就是客户端的负载均衡策略。客户端通过自己需要请求的后端来选择对应的请求接口。而Ribbon就是客户端负载均衡的代表。
Ribbon介绍
首先Ribbon是有Netflix开发的一款开源的客户端负载均衡的工具组件。其主要包括如下的一些模块
- ribbon-loadbalancer:负载均衡模块,可以独立使用,也可以协同其他模块使用
- ribbon-eureka:基于Eureka封装的模块,能够方便快速对Eureka进行集成操作
- ribbon-transport:用于实现Netty多协议的支持,例如支持Http协议、TCP协议、UDP协议等等
- ribbon-httpclient:基于Apache HttpClient封装的REST的客户端实现,集成了负载均衡操作,可以在项目中直接使用
- ribbon-example:Ribbon的一些示例代码模块
- ribbon-core:其中包含了很多的通用性的代码,以及客户端的API等操作
后面这三个都是新增的模块,在GitHub的文档上标注的是not used,想必是这些操作就可以被其他的操作所代替了。
- ribbon-archaius: 提供了一些SPI的操作支持
- ribbon-guice: 实现一些扩展操作支持
- ribbon-evcache: 分布式缓存相关内容
Ribbon的使用
接下来我们来用Ribbon实现一个最简单的负载均衡调用功能。而接口我们就使用在上面文章中介绍的user-service提供的接口。还是跟之前的测试效果一样,分别启动两个应用,一个是8081端口,一个是8083端口。
然后我们创建一个项目ribbon-loadbalanced-demo,并且在Maven的POM文件中添加如下的一些依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.nihui</groupId>
<artifactId>ribbon-loadbalanced-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon</artifactId>
<version>2.7.18</version>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-core</artifactId>
<version>2.7.18</version>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-loadbalancer</artifactId>
<version>2.7.18</version>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxjava</artifactId>
<version>1.3.8</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
编写接口调用类
由于这里没有使用到其他的Spring框架,所以可以直接使用main方法调用的方式来进行调用。
第一步、首先需要创建一个服务的列表,也就是说需要进行负载均衡操作的服务有几个,并且将这些服务都添加到这个列表中。
第二步、构建负载均衡的实例。
第三步、设置在整个调用过程中的负载均衡策略,关于复杂均衡策略,我们在后续的分享中会有更多的介绍。
第四步、写一个for循环来调用接口,并且来观察调用结果。
其代码如下。
public class RibbonTest {
public static void main(String[] args) {
// 服务列表
List<Server> serverList = Arrays.asList(new Server("localhost", 8081), new Server("localhost", 8083));
// 构建负载实例
BaseLoadBalancer loadBalancer = LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(serverList);
loadBalancer.setRule(new RoundRobinRule());
//loadBalancer.setRule(new RandomRule());
// 调用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() + "/userInfo";
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);
}
}
}
会看到执行完成之后调用结果如下所示。结果中8081端口和8083端口交替出现。也就是说客户端在调用的过程中轮番地选择了8081端口服务和8083端口的服务进行了调用。而这种选择调用的过程就是上面我们提到的客户端的负载均衡。
当然这个是知道了都有那些服务列表的情况下实现负载均衡调用演示,实际上在我们采用了注册中心之后,我们根本是不知道服务的列表都有哪些,所以我们只能通过服务名称来获取到服务列表进行负载均衡。后续的分享中会给大家分享如何使用RestTemplate如何整合Ribbon实现负载均衡操作,以及@LoadBalanced的负载均衡原理是什么。希望大家多多关注,多多支持。