Nginx负载均衡中常见的算法及原理有哪些

【Nginx负载均衡中常见的算法及原理有哪些】于今腐草无萤火,终古垂杨有暮鸦。这篇文章主要讲述Nginx负载均衡中常见的算法及原理有哪些相关的知识,希望能为你提供帮助。
      nginx在1.9.0版本开始支持tcp模式的负载均衡,在1.9.13版本开始支持udp协议的负载,udp主要用于DNS的域名解析,其配置方式和指令和http代理类似,其基于ngx_stream_proxy_module模块实现tcp负载,另外基于模块ngx_stream_upstream_module实现后端服务器分组转发、权重分配、状态监测、调度算法等高级功能。

  1. 轮询算法
    与第十五周作业中所提到的LVS服务器类似,Nginx服务器也有轮询调度算法,轮询算法是Nginx的默认调度算法,该算法可以按序将用户请求轮流发送给web服务器。
    例如笔者这边在10.0.0.153和10.0.0.154两台虚拟机上均安装httpd服务,为了方便看效果,两台web服务器的的首页均显示各自ip。




    此时,我们希望利用轮询算法将用户请求依次转发到两台web服务器上,则需在配置文件中添加如下图所示信息(因为使用的是默认80端口,IP后面的:80可以省略不写)


    客户端访问时,会按序轮流将请求转发给已添加的两台web服务器。



    相较于LVS服务器,Nginx服务器在使用轮询算法时的优势在于会做健康性检查,即如果某一台提供web服务的服务器出故障,Nginx服务器将不会再把用户请求转发到出故障的web服务器,而是只转发给正常工作的服务器。例如笔者这边停掉ip为10.0.0.153的web服务器,此时客户端访问时,只转发给正常工作的ip为10.0.0.154服务器。




  1. 加权轮询算法
    加权轮询算法是在轮询算法的基础上加入了权重,权重越高,被分配的次数也就越多。在实际生产中,我们可以根据不同服务器的性能来赋予不同的权重,从而达到资源的最大最合理利用。
    上述轮询算法是按照1:1的比例去转发用户请求的,如果ip为10.0.0.153的主机性能更好,我们希望该服务器比另一台服务器多获得1倍的转发请求,则需在配置文件的对应ip后添加权重等于2即可。

    此时客户端去访问,则是按照两次10.0.0.153和一次10.0.0.154的比例去转发用户请求的。



  1. 源地址哈希算法
      源地址哈希调度算法是基于的客户端的remote_addr做哈希算法来实现会话保持,该方法确保来自同一客户端的请求将始终传递到同一服务器,除非该服务器不可用或者服务器的权重发生了改变。在使用该算法时,需在配置文件的upstream部分添加一行ip_hash(也可使用hash $remote_addr代替),同时要注意的是web服务器后面不能添加weight和backup。例如笔者在配置文件中设置了该算法,客户端client和client2去访问时,用户请求分别被调度到不同的目标主机上,并且后续会话会一直绑定在第一次被分配的主机上。





  1. 最少连接调度算法
      最少连接调度算法优先将客户端请求调度到当前连接最少的后端服务器,同时会考虑后端服务器的权重,相当于LVS中的WLC算法。例如笔者在配置文件中设置该调度算法,同时设置两台web服务器的权重分别为2和3,该算法保证在转发请求的时候两台空闲的服务器都能轮流获得一次请求,之后则会按照未完成的权重占比分配,所以客户端测试时,以五次请求为一轮,根据权重分别获得2次和3次转发请求。




  1. 一致性哈希算法
    在普通分布式集群中,用户请求与处理请求的服务器之间是一一对应的,即用户发起请求后,代理服务器会转发到后端服务器上进行处理,固定的由某一台或多台服务器处理用户的同类请求。当同类用户请求过多时,该方法可能会造成某一台或某些服务器过于繁忙,而其他服务器一直处于空闲状态,并且处理请求的服务器出现宕机等现象时还会造成用户请求无法处理,无法实现整体的负载均衡。
    其改进措施是使用哈希算法,哈希算法可以对用户请求进行转换,转换后的结果对服务器节点值进行取模运算,取模后的值就是用户请求对应的请求处理服务器,从而实现动态分配。例如笔者希望Nginx服务器对用户请求中的URI这一KEY来进行哈希运算,根据结果调度用户请求到后端服务器,此时可以在两台后端web服务器上都创建test1-10的主页面,并在主页面显示各自的IP来查看效果。



    客户端去访问时,随着URI的改变,取模所得到的哈希值也不同,用户请求会被调度到对应的后端服务器上,同时只要是URI不变,会被一直调度到同一台服务器上。

    但该算法有一个弊端,即后端服务器数量或权重等发生改变时,需要重新计算用户请求的哈希值,这会造成大量的请求被重定位到不同的服务器而造成请求所要使用的数据失效,这种情况在分布式系统中是非常糟糕的。为了解决这一问题,我们需要使用一致性哈希算法。
      一致性哈希算法将整个哈希值空间映射成一个虚拟的圆环,整个哈希空间的取值范围为0-(2^32-1),按顺时针方向组织,在0点方向重合。使用一致性哈希算法时,会将服务请求使用哈希算法算出对应的哈希值,然后根据哈希值的位置沿圆环顺时针查找,第一台遇到的服务器就是所对应的处理请求服务器。当增加一台新的服务器,受影响的数据仅仅是新添加的服务器到其环空间中前一台的服务器(也就是顺着逆时针方向遇到的第一台服务器)之间的数据,其他都不会受到影响。
    例如笔者还是根据用户请求的URI作为KEY来设置一致性哈希算法,只需在上一步设置的哈希算法后添加consistent这一参数即可,客户端访问时,也是动态分配给后端服务器。


    此时我们添加一台后端web服务器,则之前的两台后端服务器权重也会随之发生改变,如果使用传统的哈希算法,会导致所有的用户请求均要重新计算,而使用一致性则只只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。例如笔者这边添加了一台IP为10.0.0.155的虚拟机作为第三台后端web服务器,客户端再去访问时,通过与使用两台后端服务器的截图对比可以发现,只是更换了test和test4的数据,即web-server2到web-server1这一哈希值区域内的很小一部分数据。



    推荐阅读