Spring Cloud Ribbon 客户端负载均衡 4.3

   在分布式架构中,服务器端负载均衡通常是由Nginx实现分发请求的,而客户端的同一个实例部署在多个应用上时,也需要实现负载均衡。那么Spring Cloud中是否提供了这种负载均衡的功能呢?答案是肯定的。我们可以通过Spring Cloud中的Ribbon来实现此功能。本节将对Spring Cloud中的Ribbon进行详细讲解。

Ribbon介绍

  Ribbon是Netflix发布的开源项目,其主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon的客户端组件提供了一系列完善的配置项,例如连接超时、重试等。
  在Eureka的自动配置依赖模块spring-cloud-starter-eureka中,已经集成了Ribbon,我们可以直接使用Ribbon来实现客户端的负载均衡。二者同时使用时,Ribbon会利用从Eureka读取到的服务信息列表,在调用服务实例时,以合理的方式进行负载。

Ribbon的使用

  在Eureka中使用Ribbon十分简单,只需要在实例化Rest-Template的方法上添加@LoadBalanced注解,并在其执行方法中使用服务实例的名称即可。具体实现过程如下:
  (1)添加@LoadBalanced注解。在xcservice-eureka-user工程引导类中的restTemplate()方法上添加@LoadBalanced注解,其代码如下:
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
    return new RestTemplate();
}

  (2)使用服务实例名称。在用户服务实例的查询方法中,使用服务提供者(订单服务)的实例名称来执行已注册服务列表中实例的方法,具体如下:

@GetMapping("/findOrdersByUser/{id}")
public String findOrdersByUser(@PathVariable String id) {
    // 假设用户只有一个订单,并且订单id为123
    int oid = 123;
    // return restTemplate.getForObject("http://localhost:7900/order/" + oid, String.class);
    return restTemplate.getForObject("http://xcservice-eureka-order/" + id, String.class);
}

  从上述代码中可以看出,getForObject()方法的URI中使用的已经不是“主机地址+端口号”的形式,而使用的是注册中心中的订单服务实例名称。


  (3)创建服务监听类。为了演示负载均衡的实现效果,这里在xcservice-eureka-order工程中创建一个用于监听服务实例端口的工具类ServiceInfoUtil,其实现代码如下。
package com.xc.xcserviceeurekaorder.util;

import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;

@Configuration//注册组件
public class ServiceInfoUtil implements ApplicationListener<EmbeddedServletContainerInitializedEvent> {
    /**
     * 声明event对象,该对象用于获取运行服务器的本地端口
     */
    private static EmbeddedServletContainerInitializedEvent event;

    @Override
    public void onApplicationEvent(EmbeddedServletContainerInitializedEvent event) {
        ServiceInfoUtil.event = event;
    }

    /**
     * 获取端口号
     */
    public static int getPort() {
        int port = event.getEmbeddedServletContainer().getPort();
        return port;
    }
}

  上述工具类实现了ApplicationListener接口,该接口在Spring3.0中添加了泛型来声明所需要监听的事件类型,其中EmbeddedServletContainerInitializedEvent主要用于获取运行服务器的本地端口号。


  (4)添加输出语句。在订单控制器类OrderController的查询订单方法中,增加一行执行输出当前实例端口号的语句。具体如下:
  
System.out.println(ServiceInfoUtil.getPort());
  (5)启动服务,测试应用。分别启动注册中心、用户服务和订单服务,然后修改订单服务的端口号(如7901),再次启动一个订单服务后,Eureka信息页面的注册信息如图4-10所示。

  从图4-10中可以看到,名称为xcservice-eureka-order的实例名称下包含两个不同端口号(7900和7901)的实例应用。
  当通过浏览器连续4次访问地址http://localhost:8000/findOrdersByUser/1后,用户服务实例通过Ribbon分别调用了端口为7900和7901的订单服务实例,这说明已成功通过Ribbon实现了客户端的负载均衡。
  其实Ribbon在工作时主要分为两步:第1步先选择EurekaServer,它会优先选择在同一个区域且负载较少的Server;第2步会根据用户指定的策略(如轮询、随机等)从Server取到的服务注册列表中选择一个地址。本案例中,Ribbon所使用的策略就是轮询。 
原文地址:https://www.cnblogs.com/ooo0/p/11183419.html