目前主流的负载方案分为以下两种:

  • 集中式负载均衡,在消费者和服务提供方中间使用独立的代理方式进行负载,有硬件的(比如 F5),也有软件的(比如 Nginx)。
  • 客户端自己做负载均衡,根据自己的请求情况做负载,Ribbon 就属于客户端自己做负载。


Spring Cloud Ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡工具,它基于 Netflix Ribbon 实现。通过 Spring Cloud 的封装,可以让我们轻松地将面向服务的 REST 模版请求自动转换成客户端负载均衡的服务调用。

Spring Cloud Ribbon 虽然只是一个工具类框架,它不像服务注册中心、配置中心、API 网关那样需要独立部署,但是它几乎存在于每一个 Spring Cloud 构建的微服务和基础设施中。因为微服务间的调用,API 网关的请求转发等内容,实际上都是通过 Ribbon 来实现的(https://github.com/Netflix/ribbon)。

Ribbon 模块

Ribbon 模块介绍如下表 1 所示。
image.png

Ribbon 使用

我们使用 Ribbon 来实现一个最简单的负载均衡调用功能,接口就用《使用Eureka编写服务提供者》提供的 /user/hello 接口,需要启动两个服务,一个是 8081 的端口,一个是 8083 的端口。

然后创建一个新的 Maven 项目 ribbon-native-demo,在项目中集成 Ribbon,在 pom.xml 中添加如下代码所示的依赖。

  1. <dependency>
  2. <groupId>com.netflix.ribbon</groupId>
  3. <artifactId>ribbon</artifactId>
  4. <version>2.2.2</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.netflix.ribbon</groupId>
  8. <artifactId>ribbon-core</artifactId>
  9. <version>2.2.2</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>com.netflix.ribbon</groupId>
  13. <artifactId>ribbon-loadbalancer</artifactId>
  14. <version>2.2.2</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>io.reactivex</groupId>
  18. <artifactId>rxjava</artifactId>
  19. <version>1.0.10</version>
  20. </dependency>

接下来我们编写一个客户端来调用接口,代码如下所示。

  1. // 服务列表
  2. List<Server> serverList = Lists.newArrayList(new Server("localhost", 8081), new Server("localhost", 8083));
  3. // 构建负载实例
  4. ILoadBalancer loadBalancer = LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(serverList);
  5. // 调用 5 次来测试效果
  6. for (int i = 0; i < 5; i++) {
  7. String result = LoadBalancerCommand.<String>builder().withLoadBalancer(loadBalancer).build()
  8. .submit(new ServerOperation<String>() {
  9. public Observable<String> call(Server server) {
  10. try {
  11. String addr = "http://" + server.getHost() + ":" + server.getPort() + "/user/hello";
  12. System.out.println(" 调用地址:" + addr);
  13. URL url = new URL(addr);
  14. HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  15. conn.setRequestMethod("GET");
  16. conn.connect();
  17. InputStream in = conn.getInputStream();
  18. byte[] data = new byte[in.available()];
  19. in.read(data);
  20. return Observable.just(new String(data));
  21. } catch (Exception e) {
  22. return Observable.error(e);
  23. }
  24. }
  25. }).toBlocking().first();
  26. System.out.println(" 调用结果:" + result);
  27. }

上述这个例子主要演示了 Ribbon 如何去做负载操作,调用接口用的最底层的 HttpURLConnection。当然你也可以用别的客户端,或者直接用 RibbonClient 执行程序,可以看到控制台输出的结果如下:
image.png
从输出的结果中可以看到,负载起作用了,8083 调用了 3 次,8081 调用了 2 次。