ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Nginx应用与运维——Nginx负载均衡应用实战(一)

Nginx应用与运维——Nginx负载均衡应用实战(一) Nginx负载均衡应用实战1、Nginx负载均衡模块1.1、服务器配置指令1.2、负载均衡策略指令2、负载均衡策略2.1、轮询2.1.1、加权轮询2.1.2、平滑轮询2.2、一致性哈希2.3、IP哈希2.4、最少连接2.5、随机负载算法随着业务量的增加互联网应用产品对业务处理能力和计算强度的要求也相应增大为了满足业务需求这些产品广泛应用了提升业务处理能力的负载均衡技术。负载均衡是Nginx最重要的功能应用Nginx异步架构的特性使其可以轻松处理高并发请求。高并发的请求发送到Nginx后被Nginx按照负载均衡策略分发给被代理服务器来做复杂的计算、处理和响应当业务量增加的时候可以实现客户端无感知地被代理服务器集群扩容操作。HTTP负载均衡是基于HTTP协议的负载均衡应用。HTTP协议是建立在TCP协议之上的一种应用是把TCP作为底层的传输协议由于工作在第七层—应用层因此它也被称为“七层负载均衡”​。TCP负载均衡是基于TCP协议的负载均衡应用。TCP协议是网络传输的基础协议工作在网络层和传输层因此也被称为“四层负载”​。1、Nginx负载均衡模块Nginx负载均衡是由代理模块和上游(upstream)模块共同实现的Nginx通过代理模块的反向代理功能将用户请求转发到上游服务器组上游模块通过指定的负载均衡策略及相关的参数配置将用户请求转发到目标服务器上。上游模块可以与Nginx的代理指令(proxy_pass)、FastCGI协议指令(fastcgi_pass)、uWSGI协议指令(uwsgi_pass)、SCGI协议指令(scgi_pass)、memcached指令(memcached_pass)及gRPC协议指令(grpc_pass)实现多种协议后端服务器的负载均衡。1.1、服务器配置指令Nginx上游模块定义了upstream指令域在该指令域内可设置服务器、负载均衡策略等负载均衡配置配置样例如下具体指令说明见表。upstream backend{server backend1.example.comweight5;# 被代理服务器端口号为80权重为5server backend2.example.com:8080;# 被代理服务器端口号为8080默认权重为1server unix:/tmp/backend3;server backup1.example.com:8080 backup;# 该被代理服务器为备份状态server backup2.example.com:8080 backup;# 该被代理服务器为备份状态}server{location /{proxy_pass http://backend;# 将客户端请求反向代理到上游服务器组backend}}服务器指令服务器地址可以是指定端口的IP、域名或Unix套接字。如不指定端口默认端口号为80。服务器指令参数slow_start参数不能与Hash负载均衡方法一同使用。若上游服务器组中只有一台被代理服务器则max_fails、fail_timeout和slow_start参数都会被忽略并且这个服务器将永远不会被置为无效。共享内存区指令长连接最大请求数指令长连接缓存数该指令不会对活跃的TCP连接数有影响。长连接缓存超时时间1.2、负载均衡策略指令Nginx支持多种负载均衡策略如轮询(Round Robin)、一致性哈希(Consistent Hash)、IP哈希(IP Hash)、最少连接(least_conn)等。Nginx的默认负载均衡策略为轮询策略不需要配置指令轮询策略通过server的权重参数可实现手动分配的加权轮询策略。负载均衡策略配置指令均应编辑在upstream指令域的最上方常见的配置指令如表所示。哈希策略配置样例如下upstream backend{hash$request_uri;# 以客户端请求URI为计算哈希值的key...}upstream backend{hash$request_uriconsistent;# 以客户端请求URI为计算哈希值的key采用一致性哈希算法...}IP哈希策略配置样例如下upstream backend{ip_hash;# 启用IP哈希负载均衡策略server backend1.example.com;server backend2.example.com;server backend3.example.com down;server backend4.example.com;}当服务器组中一台服务器被临时删除时可使用down参数标记那么客户端IP哈希值将会保留。最少连接策略配置样例如下upstream backend{least_conn;# 启用最少连接负载均衡策略server backend1.example.com;server backend2.example.com;server backend4.example.com;}随机负载策略配置样例如下upstream backend{random;# 每个请求都被随机发送到某个服务器server backend1.example.com;server backend2.example.com;server backend4.example.com;}指令值参数two该参数表示随机选择两台被代理服务器然后使用指定的负载策略进行选择默认方法为least_conn。可被指定的负载策略为least_conn、least_time仅对商业版有效​。2、负载均衡策略负载均衡技术是将大量的客户端请求通过特定的策略分配到集群中的节点实现快速响应的应用技术。在应对高并发的应用请求时单节点的应用服务计算能力有限无法满足客户端的响应需求通过负载均衡技术可以将请求分配到集群中的多个节点中让多个节点分担高并发请求的运算快速完成客户端的请求响应。2.1、轮询轮询(Round Robin)策略是Nginx配置中默认的负载均衡策略该策略将客户端的请求依次分配给后端的服务器节点对后端集群中的服务器实现轮流分配。轮询策略绝对均衡且实现简单但也会因后端服务器处理能力的不同而影响整个集群的处理性能。2.1.1、加权轮询在Nginx的轮询策略中为了避免因集群中服务器性能的差异对整个集群性能造成影响在轮询策略的基础上增加了权重参数让使用者可以手动根据集群中各服务器的性能将请求数量按照权重比例分配给不同的被代理服务器。2.1.2、平滑轮询在加权轮询策略中会按照权重的高低分配客户端请求若按照高权重分配完再进行低权重分配的话可能会出现的情况是高权重的服务器一直处于繁忙状态压力相对集中。Nginx通过平滑轮询算法使得上游服务器组中的每台服务器在总权重比例分配不变的情况下均能参与客户端请求的处理有效避免了在一段时间内集中将请求都分配给高权重服务器的情况发生。配置样例如下http{upstream backend{server aweight5;server bweight1;server cweight1;}server{listen80;location /{proxy_pass http://backend;}}}配置样例中Nginx平滑轮询策略计算过程如下。当前配置中a, b, c服务器的配置权重为{5, 1, 1}。配置样例中Nginx平滑轮询计算过程如表所示。有效权重(effective_weight)初始值为配置文件中权重的值会因节点的健康状态而变化。当前权重(current_weight)节点被选择前的权重值由上一个选择后权重值及各节点与自己的有效权重值相加而得。选择后权重所有节点中权重最高节点的当前权重值为其初始值与有效总权重相减的值其他节点的权重值不变。有效总权重为所有节点中非备份、非失败状态的服务器的有效权重之和。根据上述平滑轮询算法选择节点顺序为{a, a, b, a, c,a, a}。2.2、一致性哈希Nginx启用哈希的负载均衡策略是用hash指令来设置的。哈希策略方法可以针对客户端访问的URL计算哈希值对相同的URL请求Nginx可以因相同的哈希值而将其分配到同一后端服务器。当后端服务器为缓存服务器时将极大提高命中率提升访问速度。一致性哈希的优点是可以使不同客户端的相似请求发送给同一被代理服务器当被代理服务器为缓存服务器场景应用时可以极大提高缓存的命中率。一致性哈希的缺点是当上游服务器组中的节点数量发生变化时将导致所有绑定被代理服务器的哈希值重新计算影响整个集群的绑定关系产生大量回源请求。配置样例如下http{upstream backend{hash$request_uri;# 以客户端请求URI为计算哈希值的keyserver aweight5;server bweight1;server cweight1;}server{listen80;location /{proxy_pass http://backend;}}}配置样例中Nginx哈希策略计算过程如下。首先会根据$request_uri计算哈希值。根据哈希值与配置文件中非备份状态服务器的总权重计算出哈希余数。按照轮询策略选出初始被代理服务器如果哈希余数大于初始被代理服务器的权重则遍历轮询策略中被代理服务器列表。当遍历轮询策略中被代理服务器列表时要用哈希余数依次减去轮询策略中的上一个被代理服务器的权重直到哈希余数小于某个被代理服务器的权重时该被代理服务器被选出。若循环20次仍无法选出则使用轮询策略进行选择。针对哈希算法的缺点Nginx提供了consistent参数启用一致性哈希(Consistent Hash)负载均衡策略。Nginx采用的是Ketama一致性哈希算法使用一致性哈希策略后当上游服务器组中的服务器数量变化时只会影响少部分客户端的请求不会产生大量回源。Nginx一致性哈希计算过程如下。1)根据配置文件中非备份状态服务器的总权重乘以160计算出总的虚拟节点数量初始化虚拟节点数组。2)遍历轮询策略中的被代理服务器列表根据每个服务器的权重数乘以160得出该服务器的虚拟节点数量并根据服务器的HOST和PORT计算出该服务器的基本哈希(base_hash)。3)循环每个服务器虚拟节点总数次数由基本哈希(base_hash)值与上一个虚拟节点的哈希值(PREV_HASH)依次计算出所有属于该服务器的虚拟节点哈希值并把虚拟节点哈希值与服务器映射关系保存在虚拟节点哈希值数组中。4)对虚拟节点哈希值数组进行排序去重处理得到新的有效虚拟节点哈希值数组。配置样例如下http{upstream backend{hash$request_uriconsistent;# 以客户端请求URI为计算哈希值的key使用一致性# 哈希算法server aweight1;server bweight1;server cweight1;server cweight1;}server{listen80;location /{proxy_pass http://backend;}}}配置样例中Nginx一致性哈希策略计算过程如下。首先根据$request_uri计算哈希值。通过二分法快速在虚拟节点列表中选出该哈希值所在范围的最大虚拟节点哈希值。通过虚拟节点哈希值与虚拟节点集合总数取余获得对应的服务器作为备选服务器。遍历轮询策略中被代理服务器列表判断备选服务器的有效性选出服务器。若循环20次仍无法选出则使用轮询策略进行选择。2.3、IP哈希IP哈希(IP Hash)负载均衡策略根据客户端IP计算出哈希值然后把请求分配给该数值对应的被代理服务器。在哈希值不变且被代理服务器可用的前提下同一客户端的请求始终会被分配到同一台被代理服务器上。IP哈希负载均衡策略常被应用在会话(Session)保持的场景。HTTP客户端在与服务端交互时因为HTTP协议是无状态的所以任何需要上下文逻辑的情景都必须使用会话保持机制会话保持机制是通过客户端存储由唯一的SessionID进行标识的会话信息每次与服务器交互时都会将会话信息提交给服务端服务端依照会话信息实现客户端请求上下文的逻辑关联。会话信息通常存储在被代理服务器的内存中如果负载均衡将客户端的会话请求分配给其他被代理服务器则该会话逻辑将因为会话信息失效而中断。所以为确保会话不中断需要负载均衡将同一客户端的会话请求始终都发送到同一台被代理服务器通过会话保持实现会话信息的有效传递。配置样例如下http{upstream backend{ip_hash;# 启用IP哈希负载均衡策略server aweight5;server bweight1;server cweight1;}server{listen80;location /{proxy_pass http://backend;}}}配置样例中Nginx的IP哈希策略计算过程如下。在多层代理的场景下请确保当前Nginx可获得真实的客户端源IP​。首先会根据客户端的IPv4地址的前三个八位字节或整个IPv6地址作为哈希键计算哈希值。根据哈希值与配置文件中非备份状态服务器的总权重计算出哈希余数。按照轮询策略选出初始被代理服务器如果哈希余数大于初始被代理服务器的权重则遍历轮询策略中被代理服务器列表否则初始被代理服务器将被选出。当遍历轮询策略中被代理服务器列表时要用哈希余数依次减去轮询策略中的上一个被代理服务器的权重直到哈希余数小于某个被代理服务器的权重时该被代理服务器被选出。若循环20次仍无法选出则使用轮询策略进行选择。2.4、最少连接默认配置下轮询算法是把客户端的请求平均分配给每个被代理服务器每个被代理服务器的负载大致相同该场景有个前提就是每个被代理服务器的请求处理能力是相当的。如果集群中某个服务器处理请求的时间比较长那么该服务器的负载也相对增高。在最少连接(least_conn)负载均衡策略下会在上游服务器组中各服务器权重的前提下将客户端请求分配给活跃连接最少的被代理服务器进而有效提高处理性能高的被代理服务器的使用率。配置样例如下upstream backend{least_conn;# 启用最少连接负载均衡策略server aweight4;server bweight2;server cweight1;}server{listen80;location /{proxy_pass http://backend;}}配置样例中Nginx最少连接策略计算过程如下。遍历轮询策略中被代理服务器列表比较各个后端的活跃连接数(conns)与其权重(weight)的比值选取比值最小者分配客户端请求。如果上一次选择了a服务器则当前请求将在b和c服务器中选择。设b的活跃连接数为100, c的活跃连接数为60则b的比值(conns/weight)为50, c的比值(conns/weight)为60因此当前请求将分配给b。2.5、随机负载算法在Nginx集群环境下每个Nginx均通过自身对上游服务器的了解情况进行负载均衡处理这种场景下很容易出现多台Nginx同时把请求都分配给同一台被代理服务器的场景该场景被称为羊群行为(Herd Behavior)。Nginx基于两种选择的力量(Power of Two Choices)原理设计了随机(Random)负载算法。该算法使Nginx不再基于片面的情况了解使用固有的负载均衡策略进行被代理服务器的选择而是随机选择两个在经过比较后进行最终的选择。随机负载算法提供了一个参数two当这个参数被指定时Nginx会在考虑权重的前提下随机选择两台服务器然后用以下几种方法选择一个服务器。最少连接数配置指令为least_conn默认配置。响应头最短平均时间配置指令为least_timeheader仅对商业版本有效。最少连接数配置指令为least_conn默认配置。响应头最短平均时间配置指令为least_timeheader仅对商业版本有效。完整请求最短平均时间配置指令为least_timelast_byte仅对商业版本有效。配置样例如下upstream backend{random two least_conn;server backend1.example.com;server backend2.example.com;server backend3.example.com;server backend4.example.com;}在只有单台Nginx服务器时一般不建议使用随机负载算法。
返回列表