对于大型网站来说,负载均衡是一个永恒的话题。随着硬件技术的飞速发展,越来越多的负载均衡硬件设备应运而生,如F5BIG-IP、CitrixNetScaler、Radware等,虽然可以解决问题,但其高昂的价格往往让人望而却步,因此负载均衡软件仍然是大多数公司的首选。作为webserver的后起之秀,nginx以其优秀的反向代理功能和灵活的负载均衡策略,受到了业界的广泛关注。本文将以工业生产为背景,从设计实现和具体应用等方面详细介绍nginx负载均衡策略。一、前言随着互联网信息的爆炸式增长,负载均衡已经不再是一个陌生的话题。顾名思义,负载均衡就是将负载分配到不同的服务单元,这样既保证了服务的可用性,又保证了对用户的响应足够快。非常好的体验。访问和数据流量的快速增长催生了各种各样的负载均衡产品。许多专业的负载均衡硬件提供了很好的功能,但价格昂贵。这使得负载均衡软件非常流行,nginx就是其中之一。之一。Nginx第一个公共版本于2004年发布,1.0版本于2011年发布,具有稳定性高、功能强大、资源消耗低等特点。从目前的市场份额来看,nginx具有与Apache竞争的势头。其中不得不提的特点之一就是它的负载均衡功能,这也成为了很多公司选择它的主要原因。本文将从源码的角度介绍nginx内置的负载均衡策略和扩展的负载均衡策略,并以实际工业生产为案例,对各种负载均衡策略进行比较,为nginx用户提供参考。2.源码分析nginx的负载均衡策略可以分为两大类:内置策略和扩展策略。内置策略包括加权循环和iphash。默认情况下,这两个策略会被编译到nginx内核中,你只需要在nginx配置中指定参数即可。扩展策略有很多,比如fair、generalhash、consistenthash等,默认没有编译到nginx内核中。由于nginx版本升级过程中,负载均衡代码没有本质变化,下面将以nginx1.0.15稳定版为例,从源码的角度分析各个策略。2.1加权轮询(weightedroundrobin)轮询的原理很简单。首先介绍一下轮询的基本过程。下面是处理一个请求的流程图:图中有两点需要注意,***,如果weightedround-robin算法可以分为firstdeepsearch和firstwidesearch,那么nginx使用的是firstdeep搜索算法,即将先将请求分配给权重高的机器,直到该机器的权重下降到比其他机器低的值,然后开始将请求分配给下一个权重高的机器;第二,当所有后端机器宕机时,nginx会立即将所有机器的标志位清零到初始状态,避免导致所有机器都处于超时状态,从而导致整个前端被夯实。接下来看源码。nginx源码的目录结构非常清晰。weightedround-robin的路径是nginx-1.0.15/src/http/ngx_http_upstream_round_robin.[c|h]。我在源码的基础上,对重要难懂的地方进行了注释。先看ngx_http_upstream_round_robin.h中的重要语句:从变量命名我们可以大致猜出它的作用。其中,current_weight和weight的区别主要是前者是一个按权重排序的值,会随着处理请求的处理而动态变化,后者是一个用来恢复初始状态的配置值。接下来看polling的创建过程,代码如下图所示。有一个尝试过的变量需要一些解释。tried记录服务器当前是否尝试连接。他是位图。如果服务器数量少于32台,则将所有服务器状态记录在一个int中即可。如果服务器数量大于32台,则需要在内存池中申请内存进行存储。关于这个位图数组的使用,可以参考下面的代码:***是实际的policy代码,逻辑很简单,代码实现只有30行,直接上传代码。2.2iphash是nginx内置的另一种负载均衡策略。其过程与轮询非常相似,但算法和具体策略有一些变化,如下图所示:iphash算法的核心实现如下图所示:从代码中可以看出,hashvalue与ip和后端机器数量有关。经测试,上述算法可以连续生成1045个不同的值,这是算法的硬限制。为此,nginx使用了一种保护机制。当在20个哈希后没有找到可用的机器时,该算法退化为轮询。因此,iphash算法本质上是一种变相的轮询算法。如果两个ip的初始hash值恰好相同,那么这两个ip的请求总是会登陆同一台服务器,这为平衡性埋下了很深的隐患。2.3fairfair策略是一个扩展策略,默认没有编译到nginx内核中。原理是根据后端服务器的响应时间来判断负载情况,选择负载最轻的机器进行分发。该策略适应性强,但实际网络环境往往不是那么简单,应谨慎使用。2.4Generalhash和consistenthash也是扩展策略,具体实现上有一些区别。generalhash比较简单,用nginx自带的变量hash即可。Consistenthash采用nginx内置的consistenthashring,可以支持memcache。3.对比测试本次测试主要是比较各个策略的平衡性、一致性、容灾性等,从而分析出它们之间的差异,并据此给出各自的适用场景。为了全面客观地测试nginx的负载均衡策略,我们使用两种测试工具在不同的场景下进行测试,以减少环境对测试结果的影响。首先简要介绍测试工具、测试网络拓扑结构和基本测试流程。3.1测试工具3.1.1easyABCEasyABC是公司内部开发的性能测试工具。它是使用epool模型实现的。它易于使用,可以模拟GET/POST请求。极端情况下可提供数万级压力,在公司得到广泛应用。.由于被测对象是一个反向代理服务器,需要在其后端搭建一个存根服务器。这里使用nginx作为stubwebserver,提供最基本的静态文件服务。3.1.2polygraphpolygraph是一款免费的性能测试工具,擅长测试缓存服务、代理、交换机等。它拥有标准化的配置语言PGL(PolygraphLanguage),为软件提供了强大的灵活性。其工作原理如下图所示:此处入图描述测谎仪提供客户端和服务端,并在两者之间放置测试目标nginx,三者之间的网络交互使用http协议,只需要配置ip+port即可。客户端可以配置虚拟机器人的数量和每个机器人的请求速率,向代理服务器发起随机静态文件请求,服务器端根据请求的url生成随机大小的静态文件响应。这也是选择这个测试软件的主要原因之一:可以生成随机url作为nginx各种hash策略的key。3.2测试环境本次测试运行在5台物理机上,其中被测对象单独搭建在一台8核机器上,另外四台4核机器分别搭建easyABC、webserverstub和polygraph,如图下图:3.3测试方案首先介绍一下关键测试指标:balance:请求是否能均匀发送到后端consistency:同一个key的请求是否能落在同一台机器上;能否正常工作以上述指标为指导。我们使用easyABC和polygraph来测试以下四种测试场景:场景1,server_*正常提供服务;场景二,server_4挂了,其他正常;场景三,server_3和server_4挂了,其他正常;场景4server_*全部恢复正常服务。以上四个场景将按时间顺序进行,每个场景都以前一个场景为基础,测试对象不需要做任何事情,最大程度地模拟实际情况。另外考虑到测试工具本身的特点,easyabc上的测试压力在17000左右,polygraph上的测试压力在4000左右。以上测试均保证被测对象可以正常工作,注意上面没有日志级别(警报/错误/警告)出现。每个场景都记录server_*的qps,用于***策略分析。3.4测试结果表1和图1是两种测试工具下轮询策略的负载情况。对比两种测试工具下的测试结果,会发现结果是完全一致的,因此可以排除测试工具的影响。从图中可以看出轮询策略可以同时满足平衡和容灾。表2和图2给出了公平策略在两种测试工具下的负载情况。公平策略受环境的影响很大。排除测试工具的干扰后,结果仍然有很大的抖动。直觉上,这是完全不平衡的。但从另一个角度来看,也正是因为这种适应性,才能在复杂的网络环境中物尽其用。因此,在应用于工业生产之前,需要先做好特定环境下的测试工作。下面的图表展示了各种哈希策略,唯一不同的是哈希键或者具体的算法实现,所以我们一起来比较一下。在实际测试中,发现generalhash和consistencyhash都存在问题:当某台后端机器挂掉时,原本落在这台机器上的流量会丢失,而ip却没有这个问题哈希。就像上面分析iphash源码一样,当iphash失败时,会退化为轮询策略,所以不会有流量丢失。从这个层面来说,iphash也可以看成是polling的升级版。图5显示了ip哈希策略。iphash是nginx内置的一种策略,可以看作是前两种策略的特例:源ip作为key。由于测试工具不方便模拟IP下的大量请求,这里截取线上实际情况进行分析,如下图:图中前1/3使用轮询策略,中间部分使用了iphash策略,最后1/3还是roundrobin策略。可以很明显的看出iphash的balance存在很大的问题。原因不难分析。在实际网络环境中,存在大量的大学出口路由器ip、企业出口路由器ip等网络节点。这些节点带来的流量往往是普通用户的几百上千倍,而iphash策略恰恰是按照IP来划分流量,自然会造成上述后果。4.总结与展望通过实际对比测试,我们验证了nginx的各个负载均衡策略。下面从平衡性、一致性、容灾性、适用场景等角度对各种策略进行对比。以上从源码和实际测试数据的角度对nginx负载均衡策略进行了分析和说明,并给出了各种策略适用的应用场景。通过本文的分析不难发现,没有一种策略是万能的,具体场景选择哪种策略在一定程度上取决于用户对这些策略的熟悉程度。希望本文的分析和测试数据能够对读者有所帮助,也希望能产生更多更好的负载均衡策略。
