nginx负载均衡的5种策略及原理

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处连接和本声明。
本文连接: http://www.javashuo.com/article/p-crzvlagr-dh.html

nginx的upstream目前支持的5种方式的分配html


一、轮询(默认)
每一个请求按时间顺序逐一分配到不一样的后端服务器,若是后端服务器down掉,能自动剔除。 
upstream backserver { 
server 192.168.0.14; 
server 192.168.0.15; 


二、指定权重
指定轮询概率,weight和访问比率成正比,用于后端服务器性能不均的状况。 
upstream backserver { 
server 192.168.0.14 weight=8; 
server 192.168.0.15 weight=10; 


三、IP绑定 ip_hash
每一个请求按访问ip的hash结果分配,这样每一个访客固定访问一个后端服务器,能够解决session的问题。 
upstream backserver { 
ip_hash; 
server 192.168.0.14:88; 
server 192.168.0.15:80; 


四、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。 
upstream backserver { 
server server1; 
server server2; 
fair; 


五、url_hash(第三方)
按访问url的hash结果来分配请求,使每一个url定向到同一个后端服务器,后端服务器为缓存时比较有效。 
upstream backserver { 
server squid1:3128; 
server squid2:3128; 
hash $request_uri; 
hash_method crc32; 


在须要使用负载均衡的server中增长 

proxy_pass http://backserver/; 
upstream backserver{ 
ip_hash; 
server 127.0.0.1:9090 down; (down 表示当前的server暂时不参与负载) 
server 127.0.0.1:8080 weight=2; (weight 默认为1.weight越大,负载的权重就越大) 
server 127.0.0.1:6060; 
server 127.0.0.1:7070 backup; (其它全部的非backup机器down或者忙的时候,请求backup机器) 


max_fails :容许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误 
fail_timeout:max_fails次失败后,暂停的时间前端

 

深刻解析:

1 前言



随着网站负载的不断增长,负载均衡(load balance)已不是陌生话题。负载均衡是将流量负载分摊到不一样的服务单元,保证服务器的高可用,保证响应足够快,给用户良好的体验。

nginx第一个公开版发布于2004年。2011年发布了1.0版。它的特色是稳定性高、功能强大、资源消耗低。从服务器市场占有率来看,nginx已有与Apache平起平坐势头。其中,不得不提到的特性就是其负载均衡功能,这也成了不少公司选择它的主要缘由。

咱们将从源码的角度介绍nginx的内置负载均衡策略和扩展负载均衡策略,以实际的工业生产为案例,对比各负载均衡策略,为nginx使用者提供一些参考。
 nginx

2. 源码剖析



nginx的负载均衡策略能够划分为两大类:内置策略和扩展策略。

内置策略包含加权轮询和ip hash,在默认状况下这两种策略会编译进nginx内核,只需在nginx配置中指明参数便可。扩展策略有不少,如fair、通用hash、consistent hash等,默认不编译进nginx内核。

因为在nginx版本升级中负载均衡的代码没有本质性的变化,所以下面将以nginx1.0.15稳定版为例,从源码角度分析各个策略。

2.1. 加权轮询(weighted round robin)

轮询的原理很简单,首先咱们介绍一下轮询的基本流程。以下是处理一次请求的流程图:



图中有两点须要注意:

第一,若是能够把加权轮询算法分为先深搜索和先广搜索,那么nginx采用的是先深搜索算法,即将首先将请求都分给高权重的机器,直到该机器的权值降到了比其余机器低,才开始将请求分给下一个高权重的机器。

第二,当全部后端机器都down掉时,nginx会当即将全部机器的标志位清成初始状态,以免形成全部的机器都处在timeout的状态,从而致使整个前端被夯住。

接下来看下源码。nginx的目录结构很清晰,加权轮询所在路径为nginx-1.0.15/src/http/ngx_http_upstream_round_robin.[c|h],在源码的基础上,针对重要的、不易理解的地方我加了注释。首先看下ngx_http_upstream_round_robin.h中的重要声明:



从变量命名中就能够大体猜出其做用。解释一下current_weight和weight的区别,前者为权重排序的值,随着处理请求会动态的变化,后者则是配置值,用来恢复初始状态。

接下咱们来看下轮询的建立过程。代码以下图:



这里有个tried变量须要作些说明:tried中记录了服务器当前是否被尝试链接过。他是一个位图。若是服务器数量小于32,则只需在一个int中便可记录下全部服务器状态。若是服务器数量大于32,则需在内存池中申请内存来存储。

对该位图数组的使用可参考以下代码:



最后是实际的策略代码,逻辑较简单,代码实现也只有30行。来看代码。



2.2. ip hash策略

ip hash是nginx内置的另外一个负载均衡策略,流程和轮询很相似,只是其中的算法和具体的策略有些变化。以下图所示:



ip hash算法的核心实现请看以下代码:



能够看到,hash值既与ip有关又与后端机器的数量有关。经测试,上述算法能够连续产生1045个互异的value,这是此算法硬限制。nginx使用了保护机制,当通过20次hash仍然找不到可用的机器时,算法退化成轮询。

所以,从本质上说,ip hash算法是一种变相的轮询算法,若是两个ip的初始hash值刚好相同,那么来自这两个ip的请求将永远落在同一台服务器上,这为均衡性埋下了较深隐患。

2.3. fair

fair策略是扩展策略,默认不被编译进nginx内核。它根据后端服务器的响应时间判断负载状况,从中选出负载最轻的机器进行分流。
这种策略具备很强的自适应性,可是实际的网络环境每每不是那么简单,所以须慎用。

2.4.通用hash、一致性hash

通用hash和一致性hash也是种扩展策略。通用hash能够以nginx内置的变量为key进行hash,一致性hash采用了nginx内置的一致性hash环,可支持memcache。
 web

3 对比测试



了解了以上负载均衡策略,接下来咱们来作一些测试。
主要是对比各个策略的均衡性、一致性、容灾性等,从而分析出其中的差别性,根据数据给出各自的适用场景。

为了可以全面、客观的测试nginx的负载均衡策略,咱们采用两个测试工具、在不一样场景下作测试,以此来下降环境对测试结果形成的影响。

首先给你们介绍测试工具、测试网络拓扑和基本之测试流程。

3.1 测试工具

3.1.1  easyABC

easyABC是百度内部开发的性能测试工具,培训采用epool模型实现,简单易上手,能够模拟GET/POST请求,极限状况下能够提供上万的压力,在团队内部获得普遍使用。

因为被测试对象为反向代理服务器,所以须要在其后端搭建桩服务器,这里用nginx做为桩Web Server,提供最基本的静态文件服务。

3.1.2  polygraph

polygraph是一款免费的性能测试工具,以对缓存服务、代理、交换机等方面的测试见长。它有规范的配置语言PGL(Polygraph Language),为软件提供了强大的灵活性。其工做原理以下图所示:



polygraph提供Client端和Server端,将测试目标nginx放在两者之间,三者之间的网络交互均走http协议,只需配置ip+port便可。

Client端能够配置虚拟robot的个数以及每一个robot发请求的速率,并向代理服务器发起随机的静态文件请求,Server端将按照请求的url生成随机大小的静态文件作响应。

选用这个测试软件的一个主要缘由:能够产生随机的url做为nginx各类hash策略key。
另外polygraph还提供了日志分析工具,功能比较丰富,感兴趣的同窗能够参考附录材料。

3.2. 测试环境

本次测试运行在5台物理机。其中:被测对象单独搭在一台8核机器上,另外四台4核机器分别搭建了easyABC、webserver桩和polygraph。以下图所示:



3.3. 测试方案

给各位介绍一下关键的测试指标:

均衡性:是否可以将请求均匀的发送给后端
一致性:同一个key的请求,是否能落到同一台机器
容灾性:当部分后端机器挂掉时,是否可以正常工做

以上述指标为指导,咱们针对以下4个测试场景分别用easyABC和polygraph测试:

场景1      server_*均正常提供服务;
场景2      server_4挂掉,其余正常;
场景3      server_三、server_4挂掉,其余正常;
场景4      server_*均恢复正常服务。

上述四个场景将按照时间顺序进行,每一个场景将创建在上一个场景基础上,被测试对象无需作任何操做,以最大程度模拟实际状况。

另外,考虑到测试工具自身的特色,在easyabc上的测试压力在17000左右,polygraph上的测试压力在4000左右。以上测试均保证被测试对象能够正常工做,且无任何notice级别以上(alert/error/warn)的日志出现,在每一个场景中记录下server_*的qps用于最后的策略分析。

3.4.  结果

对比在两种测试工具下的测试结果会发现,结果彻底一致,所以能够排除测试工具的影响。表1和图1是轮询策略在两种测试工具下的负载状况。

从图表中能够看出,轮询策略对于均衡性和容灾性均可以作到较好的知足。





表2和图2是fair策略在两种测试工具下的负载状况。fair策略受环境影响很是大,在排除了测试工具的干扰以后,结果仍然有很是大的抖动。

从直观上讲,这彻底不知足均衡性。但从另外一个角度出发,偏偏是因为这种自适应性确保了在复杂的网络环境中可以物尽所用。所以,在应用到工业生产中以前,须要在具体的环境中作好测试工做。





如下图表是各类hash策略,所不一样的仅仅是hash key或者是具体的算法实现,所以一块儿作对比。实际测试中发现,通用hash和一致性hash均存在一个问题:当某台后端的机器挂掉时,原有落到这台机器上的流量会丢失,可是在ip hash中就不存在这样的问题。

正如上文中对ip hash源码的分析,当ip hash失效时,会退化为轮询策略,所以不会有丢失流量的状况。从这个层面上说,ip hash也能够当作是轮询的升级版。



图5为ip hash策略,ip hash是nginx内置策略,能够看作是前两种策略的特例:以来源IP为key。

因为测试工具不太擅于模拟海量IP下的请求,所以这里截取线上实际的状况加以分析。以下图所示:



图5 IP Hash策略

图中前1/3使用轮询策略,中间段使用ip hash策略,后1/3仍然是轮询策略。能够明显的看出,ip hash的均衡性存在着很大的问题。

缘由并不难分析,在实际的网络环境中,有大量的高校出口路由器ip、企业出口路由器ip等网络节点,这些节点带来的流量每每是普通用户的成百上千倍,而ip hash策略偏偏是按照ip来划分流量,所以形成上述后果也就天然而然了。
 算法

4 小结



经过实际的对比测试,咱们对nginx各个负载均衡策略进行了验证。下面从均衡性、一致性、容灾性以及适用场景等角度对比各类策略。以下图示:



咱们从源码和实际测试数据角度分析说明了nginx负载均衡的策略,给出了各类策略适合的应用场景。经过分析不难发现,不管哪一种策略都不是万金油,在具体场景下应该选择哪一种策略必定程度上依赖于使用者对策略的熟悉程度。

以上分析和测试数据可以对你们有所帮助,期待有更多愈来愈好的负载均衡策略涌现,造福更多运维开发同窗。
 后端

参考:

https://www.cnblogs.com/wpjamer/articles/6443332.html数组

http://www.javashuo.com/article/p-efxuillj-mv.html缓存

相关文章
相关标签/搜索