Netflix Ribbon

    • Netflix Ribbon
        • 【1】工作图解
        • 【2】POM依赖
        • 【3】配置方式
        • 【4】核心知识点
          • 【4.1】负载均衡策略
          • 【4.2】请求流程源码
          • 【4.3】负载均衡源码

Netflix Ribbon

【1】工作图解

作用:主要提供客服端负载均衡

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

在这里插入图片描述

【2】POM依赖
<!--ribbon依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
【3】配置方式

全局配置:

ribbon:
  #    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #配置规则 随机
  #    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #配置规则 轮询
  #    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule #配置规则 重试
  #    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule #配置规则 响应时间权重
  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
  #以下的配置需要配合fegin使用
  #ConnectTimeout: 1000 #请求连接超时时间
  #ReadTimeout: 1000 #请求处理的超时时间
  #OkToRetryOnAllOperations: true #对所有请求都进行重试
  #MaxAutoRetriesNextServer: 0 #切换实例的重试次数
  #MaxAutoRetries: 1 #对当前实例的重试次数

指定服务配置:

# 指定设置module-user-service 表示作用到哪个微服务
module-user-service:
  ribbon:
#    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #配置规则 随机
#    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #配置规则 轮询
#    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule #配置规则 重试
#    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule #配置规则 响应时间权重
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
    #以下的配置需要配合fegin使用
#    ConnectTimeout: 500 #请求连接超时时间
#    ReadTimeout: 500 #请求处理的超时时间
#    OkToRetryOnAllOperations: true #对所有请求都进行重试
#    MaxAutoRetriesNextServer: 1 #切换实例的重试次数
#    MaxAutoRetries: 2 #对当前实例的重试次数

有的地方说需要开启loadbalancer,这里验证默认是开启的

spring:
  application:
    name: module-user-ribbon
  cloud:
    loadbalancer:
      retry:
        enabled: true #开启重试

在这里插入图片描述

hystrix与ribbon组合使用的时候,需要注意execution.isolation.thread.timeoutInMilliseconds的时间要大于ribbon的处理时间

hystrix:
  command:
    default:
      execution.isolation.thread.timeoutInMilliseconds: 5000 # 请求5S超时后,执行熔断方法

启动配置

package com.it.springcloud;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

/***
 * @description UserRibbonStart
 * @return
 */
@SpringBootApplication
@EnableEurekaClient
public class UserRibbonStart {

    public static void main(String[] args) {
        SpringApplication.run(UserRibbonStart.class);
    }

    @Bean
    //提供负载均衡的功能
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    @Bean
    public IRule ribbonRule() {
        return new RoundRobinRule();//这里配置策略,和配置文件对应
    }
}

使用方式:

package com.it.springcloud.service;

import com.it.springcloud.basic.ResponseWrap;
import com.it.springcloud.exception.ProjectException;
import com.it.springcloud.req.UserVo;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.client.RestTemplate;

import java.util.Date;

/**
 * @ClassName UserController.java
 * @Description 用户controller
 */
@Service
public class UserRibbonService {

    @Autowired
    RestTemplate restTemplate;

    private static String BASIC_URL ="http://module-user-service";

 
    /***
     * @description 注册用户
     * @param userVo 注册信息
     * @return: java.lang.Boolean
     */
    public ResponseWrap<Boolean> registerUser(UserVo userVo) throws ProjectException {
        return restTemplate.postForObject(BASIC_URL+"/user/register",
                                                userVo,
                                                ResponseWrap.class);
    }

   .....
}
【4】核心知识点
【4.1】负载均衡策略

Ribbon作为后端负载均衡器,比Nginx更注重的是承担并发而不是请求分发,可以直接感知后台动态变化来指定分发策略。它一共提供了7种负载均衡策略:

策略名策略声明策略描述实现说明
BestAvailableRulepublic class BestAvailableRule extends ClientConfigEnabledRoundRobinRule选择一个最小的并发请求的server逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server
AvailabilityFilteringRulepublic class AvailabilityFilteringRule extends PredicateBasedRule过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值)使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态
WeightedResponseTimeRulepublic class WeightedResponseTimeRule extends RoundRobinRule根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低。一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成status时,使用roubine策略选择server。
RetryRulepublic class RetryRule extends AbstractLoadBalancerRule对选定的负载均衡策略机上重试机制。在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server
RoundRobinRulepublic class RoundRobinRule extends AbstractLoadBalancerRuleroundRobin方式轮询选择server轮询index,选择index对应位置的server
RandomRulepublic class RandomRule extends AbstractLoadBalancerRule随机选择一个server在index上随机,选择index对应位置的server
ZoneAvoidanceRulepublic class ZoneAvoidanceRule extends PredicateBasedRule复合判断server所在区域的性能和server的可用性选择server使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。

yml文件配置:

# 指定设置名称为module-user-service 服务
module-user-service:
  ribbon:
#    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #配置规则 随机
#    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #配置规则 轮询
#    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule #配置规则 重试
#    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule #配置规则 响应时间权重
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

启动类:

    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @Bean
    public IRule ribbonRule() {
        return new RandomRule();//这里配置策略,和配置文件对应
    }

一定记得为IRule指定yml文件中选择的配置,很多文章没有。里面配具体的策略。

【4.2】请求流程源码

Ribbon是一个客户端负载均衡软件,通过注册到Eureka上的服务名,获取服务列表,缓存到本地,选择负载均衡算法,发送http请求。
在spring cloud可以通过简单配置,即可完成客户端负载均衡,用法如下:配置,注入,请求

LoadBalancerInterceptor

作用:对负载服务的拦截处理,用户发起请求时候他会处理3件事情:

  • 获得请求的路径:request.getURI()
  • 获得目标服务:originalUri.getHost()
  • 执行调用:this.loadBalancer.execute、

在这里插入图片描述

  • LoadBalancerClient

作用:执行目标请求

点击this.loadBalancer.execute进入LoadBalancerClient

public interface LoadBalancerClient extends ServiceInstanceChooser {
	<T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;
	/**
	 * 使用来自LoadBalancer的ServiceInstance,对起执行请求
	 * @param serviceId
	 * @param 服务实例
	 * @param Request。允许在执行前后添加metric
	 * @return 回调结果
	 */
	<T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException;
	/**
	 * 创建一个真正的URL包含主机和端口:
	 * http://myservice/path/to/service --> http://host:port/path/to/service
	 * @param 服务实例
	 * @param 源url,是一个包含serviceId或者dns的URL
	 * @return 重新构造的URL
	 */
	URI reconstructURI(ServiceInstance instance, URI original);
}

RibbonLoadBalancerClient

作用:是LoadBalancerClient的实现,进行追踪源码:
在这里插入图片描述
继续追踪,ILoadBalancer是一个方法重要的接口

在这里插入图片描述
ILoadBalancer

public interface ILoadBalancer {
    void addServers(List<Server> var1); // 初始化服务列表
    Server chooseServer(Object var1);	// 从列表中选择一个服务
    void markServerDown(Server var1);	// 标记服务为down
    List<Server> getReachableServers();	// 获取up和reachable的服务
    List<Server> getAllServers();//获取所有服务(reachable and unreachable)
}
【4.3】负载均衡源码

在刚才的代码中,可以看到获取服务使通过一个getServer方法:
在这里插入图片描述
进入到loadBalancer.chooseServer方法
在这里插入图片描述
我们继续跟入:

继续跟踪源码chooseServer方法,发现这么一段代码:

在这里插入图片描述
我们看看这个rule是谁:

在这里插入图片描述
这里的rule默认值是一个RoundRobinRule
我们注意到,这个类其实是实现了接口IRule的,查看一下:
在这里插入图片描述
定义负载均衡的规则接口。

它有规则实现

Logo

一起探索未来云端世界的核心,云原生技术专区带您领略创新、高效和可扩展的云计算解决方案,引领您在数字化时代的成功之路。

更多推荐