当前位置: 首页 > article >正文

SpringCloud笔记(Hoxton)——Netflix之Ribbon负载均衡

Ribbon使用

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡工具,简单的说,Ribbon是Netflix 发布的开源项目,主要功能是提供客户端软件的负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供了一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮你基于某种规则(如简单轮训,随机连接等)去连接这些机器。我们也很容易实现自定义的负载均衡算法。

代码示例

注册中心

这里是Eureka作为服务注册中心,为Ribbon提供服务端信息的获取,比如说服务的IP地址和端口,使用前面搭建好的项目(eureka-server)。

Provider

  1. 在idea中新建两个项目运行主类,选择前面创建好的项目(eureka-provider)。
    在这里插入图片描述
  2. 设置不同运行主类,使用不同端口号,然后启动三个不同端口号的provider。
    在这里插入图片描述

接口实现

调用不同的服务端,会返回对应服务端的接口。

@RestController
@RequestMapping("/api")
public class PoroviderController {

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

    @PostMapping("/sayHello")
    public String sayHello(String name) {
        return "我是服务端" + serverPort + ",你好" + name;
    }
}

Consumer

新建一个spring-boot工程,取名为consumer-ribbon,在pom文件引入ribbon需要的依赖。

添加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>

配置端口、注册中心等

server:
  port: 8091
  servlet:
    context-path: /ribbon
eureka:
  client:
    # false表示不向注册中心注册自己
    register-with-eureka: false
    service-url:
      defaultZone: http://localhost:8761/eureka/
spring:
  application:
    name: consumer-ribbon

RestTemplate配置

  • SpringCloud为客户端负载均衡创建了特定的注解@LoadBalanced,我们只需要使用该注解修饰创建RestTemplate实例的@Bean函数,SpringCloud就会让RestTemplate使用相关的负载均衡策略,默认情况下使用Ribbon。
  • 除了@LoadBalanced之外,Ribbon还提供@RibbonClient注解。该注解可以为Ribbon客户端声明名称和自定义配置。 name属性可以设置客户端的名称, configuration属性则会设置Ribbon相关的自定义配 类。
@Configuration
public class RestTemplateConfig {

    /**
     * @return org.springframework.web.client.RestTemplate
     * @description 注入一个可以进行负载均衡的RestTemple用于服务问调用
     * @author fengfan
     * @date 2022/5/18 14:43
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

}

全局配置负载

@Configuration
public class RibbonConfig {

    /**
     * @return com.netflix.loadbalancer.IRule
     * @description 配置随机负载策略
     * @author fengfan
     * @date 2022/5/20 16:04
     */
    @Bean
    public IRule iRule(){
        return new RandomRule();
    }
}

单独配置负载

  1. 配置文件方法实现
# 服务提供方的单独配置设置(服务名称大小写必须和注册的一样)
EUREKA-PROVIDER:
  ribbon:
    ConnectTimeout: 1000 #服务请求连接超时时间(毫秒)
    ReadTimeout: 3000 #服务请求处理超时时间(毫秒)
    OkToRetryOnAllOperations: true #对超时请求启用重试机制
    MaxAutoRetriesNextServer: 1 #切换重试实例的最大个数
    MaxAutoRetries: 1 # 切换实例后重试最大次数
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #修改负载均衡算法
  1. 代码配置实现
@Configuration
public class MyRuleConfig {
    @Bean
    public IRule iRule() {
        return new RandomRule();
    }
}
@SpringBootApplication
@EnableEurekaClient
/**
 * 在启动改微服务的时候就能去加载我们自定义的Ribbon配置类,从而配置生效
 * 注意:MyRuleConfig 必须是 @Configuration ,但请注意,它不在主应用程序上下文
 * 的 @ComponentScan 中,否则将由所有 @RibbonClients 共享。
 * 如果您使用 @ComponentScan (或 @SpringBootApplication ),
 * 则需要采取措施避免包含(例如将其放在一个单独的,不重叠的包中,或者指定要在 @ComponentScan )
 */
@RibbonClient(name = "EUREKA-PROVIDER", configuration = MyRuleConfig.class)
public class ConsumerRibbonApplication {

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

}

自定义负载策略

这里自己将RandomRule抄一份,实际情况根据需求自己实现

public class ZDYRule extends AbstractLoadBalancerRule {
    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

    @Override
    public Server choose(Object o) {
        return this.choose(this.getLoadBalancer(), o);
    }

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

            while(server == null) {
                if (Thread.interrupted()) {
                    return null;
                }

                List<Server> upList = lb.getReachableServers();
                List<Server> allList = lb.getAllServers();
                int serverCount = allList.size();
                if (serverCount == 0) {
                    return null;
                }

                int index = this.chooseRandomInt(serverCount);
                server = (Server)upList.get(index);
                if (server == null) {
                    Thread.yield();
                } else {
                    if (server.isAlive()) {
                        return server;
                    }

                    server = null;
                    Thread.yield();
                }
            }

            return server;
        }
    }
    protected int chooseRandomInt(int serverCount) {
        return ThreadLocalRandom.current().nextInt(serverCount);
    }
}
@Configuration
public class MyRuleConfig {
    @Bean
    public IRule iRule() {
        return new ZDYRule();
    }
}

客户端调用实现

@RestController
@RequestMapping("/api")
public class ConsumerRibbonController {
    @Resource
    private RestTemplate restTemplate;

    @PostMapping("/getServerInfo")
    public String getServerInfo(){
        MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
        body.add("name", "consumer8081");
        ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://EUREKA-PROVIDER/provider/api/sayHello", body, String.class);
        return responseEntity.getBody();
    }
}

Ribbon的负载均衡策略

  • com.netflix.loadbalancer.RandomRule:从提供服务的实例中以随机的方式;
  • com.netflix.loadbalancer.RoundRobinRule:以线性轮询的方式,就是维护一个计数器,从提供服务的实例中按顺序选取,第一次选第一个,第二次选第二个,以此类推,到最后一个以后再从头来过;
  • com.netflix.loadbalancer.RetryRule:在RoundRobinRule的基础上添加重试机制,即在指定的重试时间内,反复使用线性轮询策略来选择可用实例;
  • com.netflix.loadbalancer.WeightedResponseTimeRule:对RoundRobinRule的扩展,响应速度越快的实例选择权重越大,越容易被选择;
  • com.netflix.loadbalancer.BestAvailableRule:选择并发较小的实例;
  • com.netflix.loadbalancer.AvailabilityFilteringRule:先过滤掉故障实例,再选择并发较小的实例;
  • com.netflix.loadbalancer.ZoneAwareLoadBalancer:采用双重过滤,同时过滤不是同一区域的实例和故障实例,选择并发较小的实例。

测试

在这里插入图片描述

多次请求的服务端,端口随机变化,证明配置成功。
在这里插入图片描述


http://www.kler.cn/a/1386.html

相关文章:

  • 预训练语言模型——BERT
  • 设计模式 行为型 责任链模式(Chain of Responsibility Pattern)与 常见技术框架应用 解析
  • OpenBSD之安装指南
  • 计算机网络(三)——局域网和广域网
  • ThreadLocal 的使用场景
  • 【Ubuntu】 Ubuntu22.04搭建NFS服务
  • 知识点16--k8s资源清单定义入门
  • 好久没写过Qt了,写个Qt回味一下信号与槽
  • 海思SD3403/SS928V100开发(7)mcp2515-SPI转CAN驱动开发
  • Linux用户和权限 —— 操作演示
  • 【5G RRC】NR测量事件介绍
  • 关于字符类型
  • 基于 gma 绘制古代洛阳 5 大都城遗址空间分布地图
  • 使用vite创建vue3工程
  • 【SpringBoot项目实战】瑞吉外卖优化篇
  • 美团笔试-3.18
  • 微前端-qiankun
  • 分布式微服务架构下网络通信的底层实现原理
  • GPT-4最震撼我的一点
  • Python截图自动化工具
  • MySQL高级面试题整理
  • 面试造火箭?GitHub顶级“java 复习宝典“一一攻克!star破数十万
  • 计算机面试常见问答题目
  • 解读Flaky Test
  • 并发基础之线程池(Thread Pool)
  • SpringBoot(微服务)注册分布式Consul