Ribbon的入门使用总结

文章目录

  • 1.简介:
  • 2.实现方式
  • 3.简单使用
    • 3.1添加依赖包
    • 3.2创建服务提供者
    • 3.3创建服务消费者
    • 3.4简单测试
  • 4.负载均衡策略
  • 5.自定义负载均衡策略
    • 5.1 定义负载规则
    • 5.2 配置文件配置
    • 5.3 配置类配置
  • 6.Ribbon常用配置
  • 7.官方文档

1.简介:

Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于NetflixRibbon实现。
通过SpringCloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。
Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的。

Ribbon 是一个进程间通信的客户端库,并且已经在云环境下经过大量的生产测试。它提供了以下功能:

  • 负载均衡
  • 容错机制
  • 支持 HTTP、TCP、UDP 等多种协议,并支持异步和响应式的调用方式
  • 缓存与批处理

2.实现方式

相比来说,客户端级别的负载均衡可以有更好的性能,因为不需要多经过一层代理服务器。并且,服务端级别的负载均衡需要额外考虑代理服务的高可用,以及请求量较大时的负载压力。因此,在微服务场景下,一般采用客户端级别的负载均衡为主。

对于客户端的负载均衡来说,最好搭配注册中心一起使用。这样,服务实例的启动和关闭,可以向注册中心发起注册和取消注册,保证能够动态的通知到客户端。
Ribbon的入门使用总结_第1张图片

3.简单使用

以下是基于Nacos注册中心的案例,nacos可以参考
https://blog.csdn.net/weixin_38650898/article/details/106796136

3.1添加依赖包


<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-openfeignartifactId>
dependency>

<dependency>
     <groupId>com.alibaba.cloudgroupId>
     <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>

3.2创建服务提供者

  • bootstarp.yml配置文件
spring:
  application:
    name: cloud-provider
  profiles:
    active: dev
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 #Nacos服务注册中心地址
      config:
        server-addr: 127.0.0.1:8848 #Nacos作为配置中心地址
        file-extension: yaml #指定yaml格式的配置
        group: DEFAULT_GROUP
        # namespace: ad6f2982-2caa-47b0-a02d-95e3b8a54594
server:
  port: 8084
  • 简单控制层
/**
 * @author :xiao7
 * @date :Created in 2020/7/8 20:38
 * @description :服务提供者测试控制器
 */
@RestController
@RequestMapping("provider")
public class ProviderController {

    @Value("${server.port}")
    private String port;

    @GetMapping("/index/{name}")
    public String testProvider(@PathVariable("name") String name) {
        return name + "端口号:" + port;
    }
}
  • 启动类
@EnableDiscoveryClient
@SpringBootApplication
public class ProviderApplication8083 {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication8083.class, args);
    }
}

Ribbon的入门使用总结_第2张图片

3.3创建服务消费者

  • bootstrap.yml配置文件
spring:
  application:
    name: cloud-consumer
  profiles:
    active: dev
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 #Nacos服务注册中心地址
      config:
        server-addr: 127.0.0.1:8848 #Nacos作为配置中心地址
        file-extension: yaml #指定yaml格式的配置
        group: DEFAULT_GROUP
        # namespace: ad6f2982-2caa-47b0-a02d-95e3b8a54594
server:
  port: 8082
  • 配置类

@LoadBalanced 注解,声明 RestTemplate Bean 被配置使用 Spring Cloud LoadBalancerClient(负载均衡客户端),实现在请求目标服务时,能够进行负载均衡。

@Configuration
public class CloudConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        //Http的String转换器编码设置
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        return restTemplate;
    }
}
  • 控制器
/**
 * @author :xiao7
 * @date :Created in 2020/7/8 20:38
 * @description :服务提供者测试控制器
 */
@RestController
@RequestMapping("consumer")
public class ConsumerController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/index/{name}")
    public String testConsumer(@PathVariable("name") String name) {
        return restTemplate.getForObject("http://cloud-provider/provider/index/" + name, String.class);
    }
}
  • 启动类
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerApplication8082 {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication8082.class, args);
    }
}

3.4简单测试

  • 启动两个不同的服务提供者和一个服务消费者测试
    Ribbon的入门使用总结_第3张图片

Ribbon的入门使用总结_第4张图片

4.负载均衡策略

Ribbon 内置了 7 种负载均衡规则,如下图所示:
Ribbon的入门使用总结_第5张图片
每个负载均衡规则说明如下:

策略 策略描述
RandomRule 随机选择一个 server
RoundRobinRule 轮询选择 server
ZoneAvoidanceRule 使用 ZoneAvoidancePredicate 和 AvailabilityPredicate 来判断是否选择某个 server。ZoneAvoidancePredicate 判断判定一个 zone 的运行性能是否可用,剔除不可用的 server;AvailabilityPredicate 用于过滤掉连接数过多的 server
BestAvailableRule 选择一个最小并发请求的 server
AvailabilityFilteringRule 过滤掉那些因为一直连接失败的被标记为 circuit tripped 的后端 server,并过滤掉那些高并发的的后端 server(activeConnections 超过配置的阈值)
WeightedResponseTimeRule 根据 server 的响应时间分配一个 weight,响应时间越长,weight 越小,被选中的可能性越低
RetryRule 对选定的负载均衡策略机上重试机制

5.自定义负载均衡策略

5.1 定义负载规则

继承AbstractLoadBalancerRule


/**
 * 每个服务调用五次
 *
 * @author xiao7
 */
public class FiveTimeRule extends AbstractLoadBalancerRule {

    private AtomicInteger nextServerCyclicCounter;

    private AtomicInteger currentCount;

    public FiveTimeRule() {
        nextServerCyclicCounter = new AtomicInteger(0);
        currentCount = new AtomicInteger(1);
    }

    public FiveTimeRule(ILoadBalancer lb) {
        this();
        setLoadBalancer(lb);
    }


    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        }

        Server server = null;

        while (true) {
            List<Server> reachableServers = lb.getReachableServers();
            List<Server> allServers = lb.getAllServers();
            int upCount = reachableServers.size();
            int serverCount = allServers.size();

            if ((upCount == 0) || (serverCount == 0)) {
                return null;
            }

            if (currentCount.get() <= 5) {
                server = allServers.get(nextServerCyclicCounter.get());
            } else {
                int nextServerIndex = incrementAndGetModulo(serverCount);
                server = allServers.get(nextServerIndex);
            }


            if (server == null) {

                Thread.yield();
                continue;
            }

            if (server.isAlive() && (server.isReadyToServe())) {
                if (currentCount.get() >= 5) {
                    currentCount.compareAndSet(currentCount.get(), 1);
                } else {
                    currentCount.incrementAndGet();
                }
                return (server);
            }
        }
    }

    @Override
    public Server choose(Object key) {
        return choose(getLoadBalancer(), key);
    }

    private int incrementAndGetModulo(int modulo) {
        for (; ; ) {
            int current = nextServerCyclicCounter.get();
            int next = (current + 1) % modulo;
            if (nextServerCyclicCounter.compareAndSet(current, next)) {
                return next;
            }
        }
    }

    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig) {

    }
}

5.2 配置文件配置

通过在配置文件中,添加 {clientName}.ribbon.{key}={value} 配置项,设置指定名字的 Ribbon 客户端的指定属性的值。如此,我们就可以实现 Ribbon 客户端级别的自定义配置。

修改 配置文件,额外添加如下配置:

cloud-provider:
  ribbon:
    NFLoadBalancerRuleClassName: xiao7.cloud.consumer.FiveTimeRule # 自定义规则
    #  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 使用已有的其他规则

5.3 配置类配置

在启动类中加入@RibbonClient(value = "cloud-provider", configuration = FiveTimeRule.class)

/**
 * @author xiao7
 */
@EnableDiscoveryClient
@SpringBootApplication
@RibbonClient(value = "cloud-provider", configuration = FiveTimeRule.class)
public class ConsumerApplication8082 {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication8082.class, args);
    }
}

然后启动两个服务提供者,一个消费者测试~~

6.Ribbon常用配置

默认配置下,Ribbon 客户端是在首次请求服务时,才创建该服务的对应的 Ribbon 客户端。
可通过下面的配置,提前创建 Ribbon客户端。

ribbon:
  # Ribbon 饥饿加载配置项,对应 RibbonEagerLoadProperties 配置类
  eager-load:
    enabled: true # 是否开启饥饿加载。默认为 false 不开启
    clients: user-provider # 开启饥饿加载的 Ribbon 客户端名字。如果有多个,使用 , 逗号分隔。

Ribbon 只负责服务实例的选择,提供负载均衡的功能,而服务的 HTTP 调用则是交给 RestTemplate 来完成。实际上,Ribbon 也是提供 HTTP 调用功能的。
Ribbon 中,提供了 3 种 HTTP 客户端,如下:

ribbon:
  okhttp:
    enabled: true # 设置使用 OkHttp,对应 OkHttpRibbonConfiguration 配置类
  restclient:
    enabled: true # 设置使用 Jersey Client,对应 RestClientRibbonConfiguration 配置类
  httpclient:
    enabled: true # 设置使用 Apache HttpClient,对应 HttpClientRibbonConfiguration 配置类

Ribbon超时和重试配置

spring:	
  cloud:
     loadbalancer:
     	retry:	true
  ribbon:
    ConnectTimeout: 1000 # 请求的连接超时时间,单位:毫秒。默认为 1000
    ReadTimeout: 1 # 请求的读取超时时间,单位:毫秒。默认为 1000
    OkToRetryOnAllOperations: true # 是否对所有操作都进行重试,默认为 false。
    MaxAutoRetries: 0 # 对当前服务的重试次数,默认为 0 次。
    MaxAutoRetriesNextServer: 1 # 重新选择服务实例的次数,默认为 1 次。注意,不包含第 1 次哈。

7.官方文档

  • 英文文档
    https://github.com/Netflix/ribbon/wiki
  • 中文文档
    https://www.docs4dev.com/docs/zh/spring-cloud/Edgware.SR5/reference/multi_spring-cloud-ribbon.html

你可能感兴趣的:(springcloud,java,ribbon)