• SpringCloud(二)之我学 Ribbon


    1、负载均衡

      Ribbon 虽然不是显示的配置为一个子项目,但是无论是在 API 网关的转发请求,还是服务之间的调用 Feign ,都是通过 Ribbon 来做负载均衡的。

      负载均衡,主要是为了对系统的高可用、网络压力的缓解和处理能力扩容。

    2、客户端负载均衡

      所有客户端节点都维护自己要访问的服务端清单,这些清单主要来源于注册中心(例如 Eureka Server),并且也是用心跳机制去维护服务端清单的健康性。

      微服务中使用负载均衡只需要两步:

      1)、服务提供者只需要启动多个服务实例,注册到一个注册中心,或者多个相关联的注册中心。

      2)、服务消费者直接通过调用,被 @LoadBalanced 注解修饰过的 RestTemplate 来实现面向服务的接口调用。

    3、原理

      RestTemplate有四种不同的请求类型和多种参数类型的服务调用实现。

      GET(查) 、 POST(增) 、PUT(改) 、DELETE(删) 四种请求。

      常见的异服务调用: (仅举例 get 请求)

      restTemplate.getForEntity(url,User.class):传入url,拼接参数。返回的对象 getBody() 就能获取到异服务调用的结果集。

      restTemplate.getObejct():入参和返回值都类似 getForEntity() 方法,只是返回实例不需要再 getBody()。

      源码分析:

      @LoadBalanecd 注解是用来给 RestTemplate 做标记,以使用负载均衡的客户端来配置它。(LoadBalancerClient)

      在 LoadBalancerClient 接口中的参数的定义:

      ServiceInstance choose(String serviceId):根据传入的服务名 serviceId,从负载均衡器中挑选一个对应服务的实例。

      T execute(String serviceId,LoadBalancerRequest request) throws IOException:使用从负载均衡器中挑选出的服务实例来执行请求内容。

      URI reconstructURI(ServiceInstance instance,URI original):为系统构建(返回)一个合适的 host:port 形式的URI。

      Ribbon 实现负载均衡自动化配置,需要满足以下两个条件:

      @ConditionalOnClass(RestTemplate.class):RestTemplate 类必须存在于当前工程的环境中。

      @ConditionalOnBean(LoadBalancerClient.class):在 Spring 的 Bean 工程中必须有 LoadBalancerClient 的实现 Bean。

      通过 LoadBalancerInterceptor 拦截器将 RestTemplate 变成客户端负载均衡。

      实现原理:被@LoadBalanced 注解修饰的 RestTemplate 对象向外发起 HTTP 请求时,会被 LoadBalancerIntercepetor 类的 intercept 函数拦截。在使用RestTemplate 时采用了服务名作为host,所以直接从 HttpRequest 的URI对象中通过 getHost() 拿到服务名,调用 execute 函数去根据服务名来选择 实例 并发起实际的请求。(实例是IP地址)

    4、负载均衡策略

      顶层为 IRule 规则接口,一个 AbstractLoadBalancerRule 继承了 IRule 接口,并且有一系列的实现规则。

      RandomRule:根据一个随机数,去获取可用实例列表,用随机数作为下标获取一个可用服务实例。

      RoundRobinRule:线性轮询方式依次选择每个服务实例。

      RetryRule:重试机制的实例选择功能。内部默认使用了 RoundRobinRule 实例。设定一个时间阈值,尝试时间超过阈值就返回 null。

      WeightedResponseTimeRule:对 RoundRobinRule 策略的扩展,根绝实例的运行情况,来计算权重来挑选实例,达到更优的分配效果。其中三个核心内容:

      1)、定时任务,默认30秒执行一次,为每个服务实例计算权重。

      2)、权重计算:计算每个实例实例平均响应时间,总平均响应时间,获取每个实例的权重区间。例如A、B、C、D 平均响应时间10,40,80,100,总230。计算A=230-10=[0,220],B=220+230-40=(220,410],C=(410,560],D=(560,690]。

      结论是平均响应时间越短,权重区间宽度越大,被选中的机会越大。

      3)、实例选择

      ZoneAvoidanceRule:选择区域策略,过滤实例,得到可用实例。(先过滤清单,再轮询选择)

      调用顺序(选择服务器逻辑): loadBalancerClient ---> ILoadBalancer(ZoneAwareLoadBalancer) 选择区域---> IRule (ZoneAvoidanceRule) 根据算法,选择具体服务实例。

      自己实现一个选择服务实例的负载方法:

     

    5、配置详解

      与 Eureka 结合:Eureka 会为架构维护所有服务的实例清单。由于 Ribbon 默认实现了区域亲和策略,可以通过 Eureka 实例的元数据配置来实现区域化的实例配置方案。比如将不同机房的实例配置成不同的区域值,作为跨区域的容错机制实现。

      实现也很简单,在服务实例的元数据中增加 zone 参数来指定自己所在的区域,例如:

      eureka.instance.metadataMap.zone=chengdu. (配置文件)

      @Bean (main 方法里)

      @LoadBalanced

      RestTemplate restTemplate() {

        return new RestTemplate();

      }

      在调用类里注入 RestTemplate 类,并且

      restTemplate.getForEntity("URL",String.class).getBody();

    6、重试机制

      Eureka 的服务治理机制强调了 CAP 原理的 AP,可用性和可靠性(C 一致性)。

      Eureka 为了实现更高的服务可用性,牺牲了一定的一致性。例如 Eureka 会因为超过85% 的实例丢失心跳而出发保护机制,注册中心会保留此时的所有节点。(极端情况接受故障也不丢掉“健康”实例)

      为了增强对服务故障实例的容错,所以加入了重试机制。通过简单的配置,那些通过 RestTemplate 实现的服务访问,就会自动根据配置来实现重试策略。

       

      重试次数,就是访问到故障请求,再尝试访问同一个实例,如果不行,就换一个实例访问。

      这两个重试由最后两个参数决定。

  • 相关阅读:
    tsc errors All In One
    TypeScript declare Set Array type All In One
    Linux exit nano editor All In One
    Linux bash pbcopy command All In One
    千焦与千卡的换算公式 All In One
    linux 中 sed N选项将两行合并为一行处理
    linux 中 sed n选项将两行作为一行处理,屏蔽第一行
    linux 中sed命令删除匹配字符之前的一行
    linux 中sed命令 P和p的区别
    linux 中 sed命令替换命令时i选项忽略大小写
  • 原文地址:https://www.cnblogs.com/AlmostWasteTime/p/11039392.html
Copyright © 2020-2023  润新知