zoukankan      html  css  js  c++  java
  • 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所使用的策略就是轮询。 
  • 相关阅读:
    前端性能优化(css动画篇)
    常用的布局及技巧
    一些有用的技能点
    做webApp遇到的一些坑及解决方案
    mysql5.7.30 编译安装
    windows使用Pandoc将Markdown转换为PDF文件
    源码编译安装keepalived
    源码编译php
    源码编译nginx
    源码编译PHP提示zip错误
  • 原文地址:https://www.cnblogs.com/ooo0/p/11183419.html
Copyright © 2011-2022 走看看