负载均衡 —— SpringCloud Netflix Ribbon

Ribbon 简介

Ribbon 是 Netfix 客户端的负载均衡器,可对 HTTP 和 TCP 客户端的行为进行控制。为 Ribbon 配置服务提供者地址后,Ribbon 就可以基于某种负载均衡算法自动帮助服务消费者去请求。Ribbon 默认提供了很多负载均衡算法,例如轮询、随机等,也可以为 Ribbon 实现自定义的负载均衡算法

Ribbon 有以下几个重要概念:

  • Rule:该组件主要决定从候选服务器中返回哪个服务器地址进行远程调用的操作
  • Ping:在后台运行的组件,用来确认哪些服务器是存活可用的
  • ServerList:当前可以用作 LB 的服务器列表,该列表可以是静态的,也可以是动态的。如果是动态列表(例如从 Eurka 服务器获取),就会有一个后台线程按照时间间隔刷新列表

Ribbon 提供了以下几种 Rule:

  • RoundRobinRule:最简单的规则,会在 ServerList 中依次轮询调用
  • RandomRule:随机
  • AvailabilityFileringRule:在这种规则下 Ribbon 集成了 Hystrix 的功能,默认情况下调用某个远程方法失败三次后断路器的开关会被打开,而之后的请求中 Ribbon 会跳过这个服务器地址,直到三十秒之后断路器关闭后才会重新加入调用列表
  • WeightedResponseTimeRule:将响应时间作为权重的负载规则,某个服务器的响应时越长,它的权重就越低,具体选择服务器时,结合权重进行随机选择
  • RetryRule:按照 RoundRobinRule(轮询)策略获取服务,如果获取服务失败,就在指定时间内重试,获取可用的服务
  • BestAvailableRule:先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
  • ZoneAvoidanceRule:复合判断 Server 所在区域的性能和 Server 的可用性选择服务器

负载均衡算法

服务消费者从服务配置中心获取服务的地址列表后需要选取其中一台发起 RPC/HTTP 调用,这时需要用到具体的负载均衡算法

1. 轮询法

轮询法是指将请求按顺序轮流分配到后端服务器上,均衡地对待后端的每一台服务器,不关心服务器实际的连接数和当前系统负载

2. 加权轮询法

简单的轮询法并不考虑后端机器的性能和负载差异,加权轮询法可以很好地处理这一问题,它将按照顺序且按照权重分派给后端服务器,给性能高、负载低的机器配置较高的权重,让其处理较多的请求,给性能低、负载高的机器配置较低的权重,让其处理较少的请求

假设有 9 个客户端请求、3 台后端服务器,后端服务器 1 被赋予权值 1,后端服务器2被赋予值 2,后端服务器 3 赋值 3,这样一来,客户端请求 1、2、3 都被分派到服务器 3 处理,客户端请求 4、5 被分派到服务器 2 处,客户端请求 6 被分派到服务器 1 处理,客户端请求 7、8、9 被分派到服务器 3 处理,以此类推

3. 随机法

随机法也很简单,就是随机选择一台后端服务器进行请求处理,由于每次服务器被挑中的概率都一样,因此客户端的请求可以被均匀地分派到所有的后端服务器上

4. 加权随机法

加权随机法跟加权轮询法类似,根据后台服务器不同的配置和负载情况配置不同的权重,不同的是,它是按照权重来随机选取服务器的,而非顺序

比如希望抽到 A 的概率是 50%、抽到 B 和 C 的概率是 20%、抽到 D 的概率是 10%,一般来说,我们可以给各项附加一个权重,抽取的概率正比于这个权重,上述集合就成了 {A:5,B:2,C:2,D:1),扩展这个集合,使每一项出现的次数与其权重正相关,即 {A,A,A,A,A,B,BC,C,D},然后就可以用均匀随机算法从中选取了

5. 源地址哈希法

源地址哈希是根据获取客户端的 IP 地址,通过哈希函数计算得到一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果便是客户端要访问服务器的序号。采用源地址哈希法进行负载均衡,当后端服务器列表不变时,同一个 IP 地址的客户端,每次都会映射到同一台后端服务器进行访问,但当后端服务器增加或者减少时,由于次数用于取模的服务器总数发生了变化,就导致同一哈希值的请求无法命中同一台服务器,节点数越高,命中率越低

6. 一致性哈希法

一致性哈希法解决了分布式环境下机器增加或者减少时简单的取模运算无法获取较高命中率的问题,通过一个一致性哈希环的数据结构实现映射,具体算法过程为:先构造一个长度为 2 的 32 次方的整数环(一致性哈希环),根据节点计算得出的哈希值将缓存服务器节点放置在这个哈希环上,然后在哈希环上顺时针查找距离这个哈希值最近的服务器节点,完成请求到服务器的映射

在这里插入图片描述

假设现在增加一台服务器 4,那么影响的就只有一个的请求,也就是说原本到服务器 1 的请求会被映射到服务器 4 上,虽然也会影响到整个集群,但是影响的只是加粗的那一段而已,这种影响要小得多。更重要的是,集群中缓存服务器节点越多,增加节点带来的影响越小

在这里插入图片描述


第一个 Ribbon 程序

创建名为 ribbon-provider 的项目,添加配置文件 application-01.properties 和 application-02.properties

# application-01.properties 配置文件内容
server.port=8080# application-02.properties 配置文件内容
server.port=8081

开发 UserController 类

@RestController
@RequestMapping("user")
public class UserCon {@Resourceprivate Environment environment;public String getPort() {return environment.getProperty("local.server.port");}@RequestMapping("getName")public String getUserName (){return "hello,ay" + "-" + getPort();}
}

通过使用不同的配置文件,可以启动多个 SpringBoot 应用,分别启动 ribbon-provider-8080 和 ribbon-provider-8081

创建名为 ribbon-consumer 的项目,pom.xml 添加依赖

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

添加配置文件 application.yml

my-client:  #负载均衡配置ribbon:listOfServers: localhost:8080,localhost:8081  # 配置服务列表NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule  # 配置负载均衡算法 RoundRobinRule(轮询)

Ribbon 的配置格式是 <clientName>:ribbon:需要配置的属性<clientName> 是 Ribbon 的客户端名称,如果省略就配置所有客户端,配置的属性有以下几种:

  • NFLoadBalancerClassName:配置 ILoadBalancer 的实现类
  • NFLoadBalancerRuleClassName:配置 IRule 的实现类
  • NFLoadBalancerPingClassName:配置 IPing 的实现类
  • NIWSServerListClassName:配置 ServerList 的实现类
  • NIWSServerListFilterClassName:配置 ServerListFilter 的实现类

在 main 方法中添加如下代码:

@SpringBootApplication
public class RibbonConsumerApplication {public static void main(String[] args) throws Exception {SpringApplication.run(RibbonConsumerApplication.class, args);//获取客户端RestClient client = (RestClient) ClientFactory.getNamedClient("my-client");//调用UserController类的getUserName 方法HttpRequest request = HttpRequest.newBuilder().uri("/user/getName").build();//循环调用for(int i = 0; i<10; i++) {HttpResponse response = client.executeWithLoadBalancer(request);String result = response.getEntity(String.class);System.out.println(result);}}
}

启动 ribbon-consumer 项目,从打印信息中可以看出,服务通过轮询的方式调用


Ribbon 整合 Nacos & 自定义负载均衡策略

创建 ribbon-custom-consumer 的项目,添加配置类

@Configuration
public class RibbonConfig {@Beanpublic IRule ribbonRule() {// ribbon默认使用的是zoneAvoidanceRule规则,这里修改为自定义方式return new MyRule();}
}

创建 MyRule 类,用来自定义负载均衡规则

/*** 负载规则:始终返回第一个服务*/
public class MyRule extends AbstractLoadBalancerRule {@Overridepublic void initWithNiwsConfig(IClientConfig iClientConfig) {}@Overridepublic Server choose(Object o) {ILoadBalancer loadBalancer = getLoadBalancer();// 获取所有的服务List<Server> servers = loadBalancer.getAllServers();// 始终返回第一个服务return servers.get(0);}
}

自定义指定 Ribbon 客户端的配置

/*** 使用 RibbonClient 为特定 name 的 Ribbon Client 自定义配置* 使用 @RibbonClient 的 configuration 属性指定 Ribbon 的配置类*/
@Configuration
@RibbonClient(name = "service-provider", configuration = RibbonConfig.class)
public class TestConfig {}

在 application.properties 配置文件中添加如下配置

server.port=7089
spring.application.name=service-custom
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

在启动类中添加 @EnableDiscoveryClient 注解

@EnableDiscoveryClient
@SpringBootApplication
public class RibbonCustomApplication {public static void main(String[] args) {SpringApplication.run(RibbonCustomApplication.class, args);}
}

创建 TesController类,具体代码如下

@RestController
@RequestMapping("test")
public class TestController {@Resourceprivate LoadBalancerClient loadBalancerClient;@RequestMapping("getUserName")public String getUserName() {for (int i = 0; i < 20; i++) {//获取service-provider服务ServiceInstance serviceInstance = loadBalancerClient.choose("service-provider");//打印当前选择的是哪个节点System.out.println(serviceInstance.getServiceId() + serviceInstance.getHost() + "; " + serviceInstance.getPort());}return "hello,ay";}
}

在上述步骤中,我们创建了 ribbon-custom-consumer 项目,并定义了负载均衡规则 MyRule,服务启动后注册到 Nacos 中,这样一来,在调用 getUserName 方法时,会从 Nacos 中获取已注册的服务提供者列表,并按照我们自定义的负载规则进行调用


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/139646.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IAP固件升级分几步?(Qt上位机、)

前言 这周一直想做一个IAP固件升级的上位机&#xff0c;然后把升级流程全都搞懂 有纰漏请指出&#xff0c;转载请说明。 学习交流请发邮件 1280253714qq.com IAP原理 IAP的原理我就不多赘述了&#xff0c;这里贴上几位大佬的文章 STM32CubeIDE IAP原理讲解&#xff0c;及U…

学会使用Git 和 GitHub

Git 和 GitHub 都是程序员每天都要用到的东西 —— 前者是目前最先进的 版本控制工具&#xff0c;拥有最多的用户&#xff0c;且管理着地球上最庞大的代码仓库&#xff1b;而后者是全球最大 同性交友 代码托管平台、开源社区。 在没有这两个工具时&#xff0c;编程可能是这样的…

驱动代码整理

一&#xff0c;控制LED灯控制实验 头文件 #ifndef __HEAD_H__ #define __HEAD_H__#define LED1_MODER 0X50006000 #define LED1_ODR 0X50006014 #define LED1_RCC 0X50000A28#endif 驱动 #include <linux/init.h> #include <linux/module.h> #include &l…

洛谷刷题入门篇:分支结构

今天又来了&#xff0c;刷题刷题&#xff0c;我爱刷题&#xff0c;题单链接如下&#xff1a; https://www.luogu.com.cn/training/101#problems 一、【深基1-2】小学数学 N 合一 题目如下&#xff1a;https://www.luogu.com.cn/problem/P2433 题目描述 问题 1 请输出 I lov…

【C语言】指针经典笔试题(上)

C语言的一大重头戏就是指针。 对于指针有一些认识&#xff1a; 1.指针是存放变量的地址&#xff0c;一般说的指针和指针变量是一个概念。 2.地址的单位是字节&#xff0c;大小在不同编译器环境下有所不同&#xff0c;32位机器是4个字节&#xff0c;64位机器是8个字节。 3.数组名…

C# ref 学习1

ref 关键字用在四种不同的上下文中&#xff1b; 1.在方法签名和方法调用中&#xff0c;按引用将参数传递给方法。 2.在方法签名中&#xff0c;按引用将值返回给调用方。 3.在成员正文中&#xff0c;指示引用返回值是否作为调用方欲修改的引用被存储在本地&#xff0c;或在一般…

大厂面试-16道面试题

1 java集合类有哪些&#xff1f; List是有序的Collection&#xff0c;使用此接口能够精确的控制每个元素的插入位置&#xff0c;用户能根据索引访问List中元素。常用的实现List的类有LinkedList&#xff0c;ArrayList&#xff0c;Vector&#xff0c;Stack。 ArrayList是容量…

C语言内存函数的使用、剖析及模拟实现

目录 一、内存拷贝函数——memcpy 1.函数声明&#xff1a; 注意&#xff1a; 2.函数使用用例&#xff1a; 3.memcpy函数的模拟实现&#xff1a; 二、内存拷贝函数2——memmove 1.函数声明&#xff1a; 2.memmove函数的模拟实现 三、内存比较函数——memcmp 1.函数声明…

卸载Visual Studio 2010学习版 —— 卸载VCExpress

目录 最初安装Visual Studio 2010学习版是因为计算机二级 C语言考试而装&#xff0c;现如今考完试后便可卸载掉了&#xff0c;安装简便而卸载却没有uninstall.exe文件。故本文提供卸载方式。 进入到程序目录&#xff0c;找到setup.exe文件&#xff0c;也可以在程序目录搜索set…

【lesson10】进程状态

文章目录 认识进程状态新建运行阻塞挂起 Linux具体的进程状态RSDtTXZ是什么为什么 认识进程状态 上面就是各种进程状态&#xff0c;上面都是理论进程状态理论进程状态放在哪个操作系统中都是正确的&#xff0c;但是具体的操作系统实现可能又会有所不同。 下面我们来理解进程状态…

springBoot对接多个mq并且实现延迟队列---未完待续

mq调用流程 创建消息转换器 package com.wd.config;import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; import org.springframework.amqp.support.converter.MessageConverter; import org.springframework.context.annotation.Bean; import o…

Vue的详细教程--Vue路由与nodejs

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Vue的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.Vue路由是什么 二.使用Vue路由的步骤 1、…

小程序中如何划分会员级别以及不同级别不同积分累计、折扣、返佣、升级条件等

以下是一些关键步骤和注意事项&#xff0c;帮助商家在小程序中有效设置会员卡等级和相关规则。 1. 设定会员卡等级。在管理员后台->会员管理处&#xff0c;点击“等级...”。会出现级别设置界面。 可以创建会员卡等级&#xff0c;并为每个等级设定名称和对应的规则。一般会员…

MyBatis 日志模块

文章目录 前言LogLogFactory日志应用JDBC 日志BaseJdbcLoggerConnectionLogger应用实现 总结 前言 日志在我们开发过程中占据了一个非常重要的地位&#xff0c;是开发和运维管理之间的桥梁&#xff0c;在Java中的日志框架也非常多&#xff0c;Log4j、Log4j2、slf4j等&#xff…

创建表

MySQL从小白到总裁完整教程目录:https://blog.csdn.net/weixin_67859959/article/details/129334507?spm1001.2014.3001.5502 创建表 语法格式: create table 表名(列名1 数据类型,列名2 数据类型,... ,列名n, 数据类型 ); 练习:在czwbkl库中,创建一格test01表 跟大家说…

开发高性能知识付费平台:关键技术策略

引言 在构建知识付费平台时&#xff0c;高性能是确保用户满意度和平台成功的关键因素之一。本文将探讨一些关键的技术策略&#xff0c;帮助开发者打造高性能的知识付费平台。 1. 前端性能优化 使用CDN加速资源加载 使用内容分发网络&#xff08;CDN&#xff09;来托管和加…

Flask数据库之SQLAlchemy--介绍--链接数据库

目录 SQLAlchemy介绍 SQLAlchemy连接数据库 SQLAlchemy介绍 数据库是一个网站的基础&#xff01;&#xff01;&#xff01; 比如MySQL、MongoDB、SQLite、PostgreSQL等&#xff0c;这里我们以MySQL为例进行讲解。 SQLAlchemy是一个ORM框架 对象关系映射&#xff08;英语&…

第一个 Go 程序“hello,world“ 与 main 函数

第一个 Go 程序"hello&#xff0c;world" 与 main 函数 文章目录 第一个 Go 程序"hello&#xff0c;world" 与 main 函数一.创建“hello&#xff0c;world”示例程序二. “hello&#xff0c;world” 程序结构拆解三、main 函数四、Go 语言中程序是怎么编译…

Xpath使用

有如下网页&#xff1a; 需要选中“若出现" 操作如下&#xff1a; 打开Xpath Helper 选中"若出现",右击检查 复制对应的Xpath 在QUERY栏插入即可

[杂谈]-快速了解半波和全波整流

快速了解半波和全波整流 文章目录 快速了解半波和全波整流1、滤波2、半波整流器3、全波整流器4、常见问题 整流器是一种将交流信号转换为脉动直流信号以及将交流电转换为直流电的电子电路。 我们日常生活中几乎所有的电子项目都会用到它。 根据周期传导&#xff0c;本文我们介绍…