平滑的加权轮询均衡算法

前言

在反向代理、路由、分布式应用调度等场景中通常都需要用到负载均衡算法,负载均衡的关键要点是“均衡”,即确保调用请求能均衡地落到多个处理节点上,负载均衡算法一般使用随机或轮询都可以保证均衡性。

现实中由于服务器性能或资源分配的差异,导致我们需要为服务节点设置不同的权重,权重高的节点得到更多流量,同时降低低权重节点的流量比例。也即带权重的均衡算法。

下面我们讨论几种常见的负载均衡算法,并针对其中一种给出完整的算法讲解及实现。

一、随机

这是最简单的负载均衡算法,每次生成一个随机数,然后对服务节点数进行取模,模值即为服务节点序号,很明显这只能做到“均匀”,无法根据各服务节点的权重进行加权分配。不过略加调整即可实现加权分配:

构造一个范围为总权重值的序列,然后用随机数对总权重取模,模值所在区间即为对应的服务节点。譬如:有三个服务节点,其权重分别为:503020,则节点集图像大致如下:

|<-----------A----------->|<-----B----->|<---C--->|

|<0--------------------50>|<51-------80>|<81--100>|

代码简示:

struct Node<TKey> where TKey : IEquatable<TKey>
{public Node(TKey key, int boundary) {this.Key = key;this.Boundary = boundary;}public TKey Key;public int Boundary;
}class NodeSelector
{int _total;Node<string> _nodes;void Initialize() {_total = 50 + 30 + 20;_nodes = new[] {new Node<string>("Node-A", 50),new Node<string>("Node-B", 50 + 30),new Node<string>("Node-C", 50 + 30 + 20),};}string Select() {var value = Randomizer.GenerateInt32() % _total;for(int i = 0; i < _nodes.Length; i++) {if(value <= _nodes[i].Boundary)return _nodes[i].Key;}return null;}
}

随机算法的表现恰如其名,在一个甚至多个调度周期内也无法确保各节点的权重匹配度,只能在大样本条件下满足权重的概率分布,总之就两字:随缘。

二、一致哈希

关于一致性哈希算法的文章已经汗牛充栋,亦不是本文的重点,所以就不再赘述。在构建哈希环的时候需要依据服务节点的权重比来设置相应数量的虚拟节点,之后确定服务节点的算法与上述随机算法基本差不多。

三、平滑加权轮询

终于来到本文的重点部分,我们假设有三个服务节点,其权重分别为:421,那么在一个调度周期内,最简单调度序列如:{A,A,A,A,B,B,C}{C,B,B,A,A,A,A}{B,B,C,A,A,A,A},但直觉这样的调度顺序不友好,因为它会在某一阵把压力都落到同一个节点上,导致某个节点突然很忙的情况,类似汽车换挡的那种顿挫感。

如果调度序列变成:{A,B,A,C,A,B,A}{A,A,B,A,C,A,B} 这样就显得“平滑”和“均衡”多了,我们主要参考 Nginx 和 LVS 采用的两种算法。

Nginx 算法

  • Nginx 的实现源码:https://github.com/nginx/nginx/blob/52327e0627/src/http/ngx_http_upstream_round_robin.c

  • Nginx 的算法摘要:https://github.com/nginx/nginx/commit/52327e0627f49dbda1e8db695e63a4b0af4448b1

on each peer selection we increase current_weight of each eligible peer by its weight, select peer with greatest current_weight and reduce its urrent_weight by total number of weight points distributed among peers.

算法详解

  • 当前节点集初始值均为零:{0,0,0}

  • 所有节点的当前权重值加上设定的权重值

  • 在当前节点集中选取最大权重值的节点作为命中节点

  • 命中节点的当前权重值减去总权重值作为其新权重值,其他节点保持不变

ABC 三个节点的权重分别为:421,演算步骤如下:

步骤

选择前当前值

选择节点(命中)

选择后当前值

1

{ 4, 2, 1}

A

{-3, 2, 1}

2

{ 1, 4, 2}

B

{ 1,-3, 2}

3

{ 5,-1, 3}

A

{-2,-1, 3}

4

{ 2, 1, 4}

C

{ 2, 1,-3}

5

{ 6, 3,-2}

A

{-1, 3,-2}

6

{ 3, 5,-1}

B

{ 3,-2,-1}

7

{ 7, 0, 0}

A

{ 0, 0, 0}

由上发现三个节点的命中次数符合 4:2:1,而且权重大的节点不会霸占选择权。经过一个周期(7轮选择)后,当前权重值又回到了{0, 0, 0},以上过程将按照周期进行循环,完全符合我们先前期望的平滑性。

数学证明

该算法的合理性和平滑性的数学证明:https://tenfy.cn/2018/11/12/smooth-weighted-round-robin

LVS 算法

Linux Virtual Server 采用的是另外一种,算法wiki文档:http://kb.linuxvirtualserver.org/wiki/Weighted_Round-Robin_Scheduling

从算法步骤和计算量上看,相对 Nginx 而言 LVS 算法略微简单一些,性能可能会略好一点点(但都是同一个量级);通过模拟数据发现当节点权重差异较大时,其平滑性没有 Nginx 算法好。

总结

在 Zongsoft.Data 数据访问框架的读写分离中需要将读写操作路由到不同权重的数据库,于是采用 Nginx 的平滑权重轮询均衡算法实现了数据源路由选择器,下面分别是平滑权重轮询器和数据路由的代码:

  • 平滑权重轮询源码:https://github.com/Zongsoft/Framework/blob/master/Zongsoft.Core/src/Components/Weighter.cs

  • 数据源权重选择器:https://github.com/Zongsoft/Framework/blob/master/Zongsoft.Data/src/Common/DataSourceSelector.cs


参考资料

  • Nginx 平滑的基于权重轮询算法分析

  • Nginx 负载均衡及算法分析

  • Nginx SWRR 算法解读


提示:点击“阅读原文”以更舒适的姿势阅览本文。

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

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

相关文章

php类精确验证身份证号码

<?php class check_IdCard {// $num为身份证号码&#xff0c;$checkSex&#xff1a;1为男&#xff0c;2为女&#xff0c;不输入为不验证public function checkIdentity($num, $checkSex ) { // 不是15位或不是18位都是无效身份证号if (strlen($num) ! 15 && strl…

请说说接口和抽象类的区别?

1.从使用目的来看&#xff1a; 接口只是一个类间的协议&#xff0c;它并没有规定怎么去实现&#xff1b; 抽象类可以重用你代码使你的代码更加简洁&#xff1b;2.从行为来看&#xff1a; 接口可以多继承,multi-implement 抽象类不能实例化&#xff0c;必须子类化才能实例化…

GitHub 使用

Git 是由 Linux 之父 Linus Tovalds 为了更好的管理 linux 内核开发而创立的分布是版本控制/软件管理配置软件. 简单来说, Git 管理你的 代码的历史记录 的工具. 首先注册账户 (已经完成, moveofgod) 然后, 下载一个 GitHub Desktop(mac), msisgit 客户端 (可以用命令行实现, …

LinkedHashMap 与 HashMap区别

2019独角兽企业重金招聘Python工程师标准>>> LinkedHashMap 与 HashMap区别 &#xff08;非原创&#xff09; HashMap,LinkedHashMap,TreeMap都属于Map Map 主要用于存储键(key)值(value)对&#xff0c;根据键得到值&#xff0c;因此键不允许键重复,但允许值重复。 …

C# 11 中的 file local type

C# 11 中的 file local typeIntro在之前的版本中&#xff0c;我们想要一个类型只在当前的类型中生效&#xff0c;通常我们会在一个类的内部声明一个 private 的类型以此来控制这个类型的访问权限&#xff0c;在 C# 11 中引入了一个 file local type&#xff0c;仅在声明类型的这…

PHP实现类似百度搜索自动完成(代码简单)

一、效果图: 二、HTML代码 <html lang"en"> <head><meta charset"utf-8"><title>jQuery UI 自动完成&#xff08;Autocomplete&#xff09; - 默认功能</title><link rel"stylesheet" href"/public/Auto…

Mysql读写分离php脚本

<?php/*php如何连接mysql*/ /*$link mysql_connect(‘localhost‘, ‘root‘, ‘‘);if (!$link) {die(‘Could not connect: ‘ . mysql_error());}echo ‘Connected successfully‘;mysql_close($link);*/ /*php如何选择数据库*//*$link mysql_connect(‘localhost‘, …

CentOS 搭建Postfix+Dovecot简单邮件系统

2019独角兽企业重金招聘Python工程师标准>>> 服务器信息 系统&#xff1a;CentOS 6.5 minimal版本 主机&#xff1a;虚拟机 虚拟机IP&#xff1a;192.168.128.128/24 宿主IP:10.1.79.24/24 安装postfix 注意&#xff1a;CentOS 7实际上已经用postfixSasl2代替sendma…

Js获取当前页面URL各种参数

JS获取当前页面URL各种参数 一&#xff1a;Location Location 对象包含有关当前 URL 的信息。 Location 对象是 Window 对象的一个部分&#xff0c;可通过 window.location 属性来访问。 hash设置或返回从井号 (#) 开始的 URL&#xff08;锚&#xff09;。host设置或返回主机名…

php面试题2018

一 、PHP基础部分 1、PHP语言的一大优势是跨平台&#xff0c;什么是跨平台&#xff1f; PHP的运行环境最优搭配为ApacheMySQLPHP&#xff0c;此运行环境可以在不同操作系统&#xff08;例如windows、Linux等&#xff09;上配置&#xff0c;不受操作系统的限制&#xff0c;所以…

学生党的专属定制福利,你想要的这里全都有!

同学们&#xff1a;您好&#xff01;很⾼兴认识⼤家&#xff01;我是微软的 Regional Cloud Advocate Kinfey Lo&#xff0c;感谢您在课余时间打开这封信。踏⼊⾦秋&#xff0c;技术峰会进⼊了旺季&#xff0c;有⾯向商业的&#xff0c;有⾯向开发者的&#xff0c;有⾯向技术社…

Quartus prime16.0 与modelsim ae 联调

前言 quartus和modelsim联调对仿真还是很方便的&#xff0c;当然最好是quartus干综合到烧录的活&#xff0c;modelsim单独仿真。而且ae版的性能比se版差。 流程&#xff1a; 1.配置modelsim ae路径&#xff1a; 我这里是这个路径&#xff0c;根据你自己安装的地方配置路径。 2.…

30分钟搞定后台登录界面(103个后台PSD源文件、素材网站)

去年八月时要做一个OA系统为了后台界面而烦恼&#xff0c;后来写了一篇博客&#xff08;《后台管理UI的选择》&#xff09;介绍了选择过程与常用后台UI&#xff0c;令我想不到的时竟然有许多开发者与我一样都为这个事情而花费不少时间&#xff0c;最后界面效果还是不佳&#xf…

分析拼多多的崛起【产品思维】

最近朋友圈讨论拼多多上市的新闻大火&#xff0c;各有各的看法&#xff0c;很有意思&#xff0c;突然想起前段时间得到上的《梁宁-产品思维30讲》&#xff0c;所以想从数据和产品角度分析分析拼多多的崛起。 一&#xff1a;拼多多的迅速崛起 我们先看看拼多多这几年的成长历程&…

62、滑动窗口的最大值

一、题目 给定一个数组和滑动窗口的大小&#xff0c;找出所有滑动窗口里数值的最大值。例如&#xff0c;如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3&#xff0c;那么一共存在6个滑动窗口&#xff0c;他们的最大值分别为{4,4,6,6,6,5}&#xff1b; 针对数组{2,3,4,2,6,2,5…

KestrelServer详解[2]: 网络连接是如何创建的?

《KestrelServer详解[1]&#xff1a;注册监听终结点&#xff08;Endpoint&#xff09;》已经详细讲述了如何使用KestrelServer&#xff0c;现在我们来简单聊聊这种服务器的总体设计和实现原理。当KestrelServer启动的时候&#xff0c;注册的每个终结点将转换成对应的“连接监听…

PHP操作文件和目录的相关函数

//判断文件类型 filetype(a.php);//打开或创建文件 fopen(a.php,w);//读取文件 fgets(a.php);//按行读取 fread(a.php,1049);//按块读取 file_get_contents(a.php);//读取文件//复制文件 copy(a.php,./b.php);//将a.php复制到b.php//删除文件 unlink(b.php);//移动文件 rename(…

linux LyX中文编辑环境安装配置指南-TeX可视化工具

TeX可以说是国际上排版的标准&#xff0c;尤其是论文、书籍之类&#xff0c;对公式的表现比MS办公系列强的太多&#xff0c;格式异常优美&#xff0c;但是由于其比较复杂的命令&#xff0c;非可视化编辑&#xff0c;所以使得入门门槛较高&#xff0c;所以出现了LaTeX这样的命令…

pandas DataFrame 数据处理常用操作

Xgboost调参&#xff1a; https://wuhuhu800.github.io/2018/02/28/XGboost_param_share/ https://blog.csdn.net/hx2017/article/details/78064362 pandas DataFrame中的空值处理&#xff1a; https://blog.csdn.net/yuanxiang01/article/details/78738812 pandas的DataFrame、…

redis集群报Jedis does not support password protected Redis Cluster configurations异常解决办法...

解决spring-data-redis操作redis集群报“Jedis does not support password protected Redis Cluster configurations”的异常 原因&#xff1a;使用spring-data-redis操作redis集群时由于redis集群设置了密码。 解决方案&#xff1a;升级spring-data-redis版本即可解决&#xf…