SpringCloud(六)Ribbon负载均衡

Ribbon

 

何为负载均衡?
负载均衡在系统架构中是一个非常重要,并且是不得不去实施的内容。因为负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。我们通常所说的负载均衡都指的是服务端负载均衡,其中分为硬件负载均衡和软件负载均衡。硬件负载均衡主要通过在服务器节点之间按照专门用于负载均衡的设备,比如F5等;而软件负载均衡则是通过在服务器上安装一些用于负载均衡功能或模块等软件来完成请求分发工作,比如Nginx等。不论采用硬件负载均衡还是软件负载均衡,只要是服务端都能以类似下图的架构方式构建起来:

 

 硬件负载均衡的设备或是软件负载均衡的软件模块都会维护一个下挂可用的服务端清单,通过心跳检测来剔除故障的服务端节点以保证清单中都是可以正常访问的服务端节点。当客户端发送请求到负载均衡设备的时候,该设备按某种算法(比如线性轮询、按权重负载、按流量负载等)从维护的可用服务端清单中取出一台服务端端地址,然后进行转发。

        而客户端负载均衡和服务端负载均衡最大的不同点在于上面所提到服务清单所存储的位置。在客户端负载均衡中,所有客户端节点都维护着自己要访问的服务端清单,而这些服务端端清单来自于服务注册中心,比如上一章我们介绍的Eureka服务端。同服务端负载均衡的架构类似,在客户端负载均衡中也需要心跳去维护服务端清单的健康性,默认会创建针对各个服务治理框架的Ribbon自动化整合配置,比如Eureka中的org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration,Consul中的org.springframework.cloud.consul.discovery.RibbonConsulAutoConfiguration。在实际使用的时候,我们可以通过查看这两个类的实现,以找到它们的配置详情来帮助我们更好地使用它。

什么是Ribbon

ribbon是netflixfa发布的一个负载均衡器,有助于控制Http和TCP客户端行为,在SprIngCloud中,Eureka一般配合Ribbon进行使用,Ribbon提供了客户端负载均衡功能,Ribbon利用从Eureka中读取到的服务信息,在调用服务节点提供的服务时,会合理的进行负载

在SpringCloud中可以将注册中心和Ribbon配合使用,Ribbon会自动的从注册中心中获取服务提供者的列表信息,并基于内置的负载均衡算法,请求服务。

Ribbon的主要作用

1 服务调用

基于Ribbon实现服务调用,是通过拉取到的所有服务列表组成(服务名-请求路径的)映射关系,借助RestTemplate最终进行调用

2 负载均衡

当有多个服务提供者时,Ribbon可以根据负载均衡算法自动的选择需要调用的服务地址

使用

1 在创建RestTemplate的时候,声明@LoadBalanced(rbbion提供的负载均衡的注解)注解

2 使用RestTemplate调用远程微服务,不需要拼接微服务的URL,以待请求的服务名替代IP地址

服务端负载均衡 nignx F5

客户端负载均衡

Ribbon是典型的客户端负载均衡服务器,Ribbon会获取服务的所有地址,根据内部的负载均衡的算法获取本次请求的有效地址

实例:

准备两个商品微服务(9001,9011)

在订单系统中远程以负载均衡的形式调用商品服务

``

 server:
  port: 9001
 spring:
  application:
    name: service-product #服务名称
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/shops?useUnicode=true&characterEncoding=utf8
    username: root
    password: 123456
  jpa:
    database: mysql
    show-sql: true
    open-in-view: true
 #配置Eureka
 eureka:
  client:
    service-url:
      defaultZone: http://localhost:9000/eureka/,http://localhost:8000/eureka/ #多个EurekaServer之间用逗号分隔
  instance:
    prefer-ip-address: true #使用IP地址进行注册
    instance-id: ${spring.cloud.client.ip-address}:${server.port} #向注册中心注册服务ID
    lease-renewal-interval-in-seconds: 5 #发送心跳的间隔默认30s(单位为s)
    lease-expiration-duration-in-seconds: 60  #续约到期时间,默认90s(单位为s)

``

 server:
  port: 9011
 spring:
  application:
    name: service-product #服务名称
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/shops?useUnicode=true&characterEncoding=utf8
    username: root
    password: 123456
  jpa:
    database: mysql
    show-sql: true
    open-in-view: true
 #配置Eureka
 eureka:
  client:
    service-url:
      defaultZone: http://localhost:9000/eureka/,http://localhost:8000/eureka/ #多个EurekaServer之间用逗号分隔
  instance:
    prefer-ip-address: true #使用IP地址进行注册
    instance-id: ${spring.cloud.client.ip-address}:${server.port} #向注册中心注册服务ID
    lease-renewal-interval-in-seconds: 5 #发送心跳的间隔默认30s(单位为s)
    lease-expiration-duration-in-seconds: 60  #续约到期时间,默认90s(单位为s)

在服务消费者里添加@LoadBalanced注解开启Ribbon自带的负载均衡功能

``

 @SpringBootApplication
 @EntityScan("com.qqq.entity")
 public class OrderApplication {
     public static void main(String[] args) {
         SpringApplication.run(OrderApplication.class,args);
    }
     /**
      * 使用spring提供的RestTemplate发送http请求到商品服务
      * 1 将RestTemplate对象交给容器管理
      * 2 使用其方法完成操作
      */
     @LoadBalanced //Ribbon自带的负载均衡的注解
     @Bean
     public RestTemplate restTemplate()
    {
         return new RestTemplate();
    }
 
 
 }

``

 package com.qqq.controller;
 
 import com.qqq.entity.Product;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cloud.client.ServiceInstance;
 import org.springframework.cloud.client.discovery.DiscoveryClient;
 import org.springframework.cloud.client.loadbalancer.LoadBalanced;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.client.RestTemplate;
 
 import java.util.List;
 
 @RestController
 @RequestMapping("/order")
 public class OrderController {
     //注入RestTemplate对象
     @Autowired
     private RestTemplate restTemplate;
     /**
      * 注入DiscoveryClient
      * SpringCloud提供的获取元数据的工具类
      * 调用方法获取服务的元数据信息
      */
     @Autowired
     private DiscoveryClient discoveryClient;
     /**
      * 参数:商品ID
      * 通过订单系统,调用商品服务根据id查询商品信息
      * 1 需要配置一个商品对象
      * 2 需要调用商品服务
      * 使用java中的urlConnection完成,或使用httpClient,okHttp
      * RestTemplate
      */
 //   @RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
 //   public Product findById(@PathVariable("id") Long id)
 //   {
 //       //调用DiscoveryClient的getInstances方法根据服务名获取元数据
 //       List<ServiceInstance> instances = discoveryClient.getInstances("SERVICE-PRODUCT");
 //       //获取唯一的元数据
 //       ServiceInstance instance = instances.get(0);
 //       Product product=null;
 //       //如何调用商品服务
 //       //根据元数据和端口号拼接请求的url
 //       product=restTemplate.getForObject("http://"+instance.getHost()+":"+instance.getPort()+"/product/"+id,Product.class);
 //       return product;
 //   }
 
     /**
      * 基于Ribbon的形式调用远程微服务
      * @param id
      * @return
      */
     @RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
     public Product findById(@PathVariable("id") Long id)
    {
         Product product=null;
         product=restTemplate.getForObject("http://service-product/product/"+id,Product.class);
         return product;
    }
 }

Ribbon默认的负载均衡就是轮询策略

Ribbon内置了多种负载均衡策略

 

 

可在服务消费者的application.yml配置文件中修改负载均衡策略

``

 #修改ribbon的负载均衡策略 服务名 - ribbon - NFLoadBalancedRuleClassName:策略
 shop-service-product:
  ribbon:
    NFLoadBalancedRuleClassName: com.netflix.loadbalancer.RandomRule

Ribbon的请求重试:

引入Spring的重试组件

对Ribbon进行重试配置

``

 #Ribbon请求重试机制
 service-product:
  ribbon:
    ConnectTimeout: 250 #Ribbon的连接超时时间
    ReadTimeout: 1000 #Ribbon的数据读取超时时间
    OkToRetryOnAllOperations: true #是否对所有操作对进行重试
    MaxAutoRetriesNextServer: 1 #切换实例重试次数
    MaxAutoRetries: 1 #对当前实例重试次数

Consul

posted @ 2020-02-03 00:05  计算机的探索者  阅读(286)  评论(0编辑  收藏  举报