首页 > 系统相关 >nginx 负载均衡相关知识

nginx 负载均衡相关知识

时间:2023-07-18 21:02:26浏览次数:45  
标签:负载 hash weight server nginx 均衡 服务器 peer http

Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。

nginx也可以做web站点,不过更多情况下,nginx都是作为负载均衡服务器来使用的。负载均衡简单的分流类似如下图:

nginx 负载均衡相关知识_后端服务

nginx的upstream模块,主要完成网络数据的接收、处理和转发,是做负载均衡的关键。下面介绍几种常见的负载分配算法。

 

Nginx的几种常见负载分配算法

轮询(round-robin 默认)

     默认情况下,Nginx 会为你提供轮询作为负载均衡策略。即每台服务器的权重是一样的。每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。

轮询调度算法(Round-Robin Scheduling) 轮询调度算法的原理是每一次把来自用户的请求轮流分配给内部中的服务器,从1开始,直到N(内部服务器个数),然后重新开始循环。
算法的优点是其简洁性,它无需记录当前所有连接的状态,所以它是一种无状态调度。
轮询调度算法流程
假设有一组服务器N台,S = {S1, S2, …, Sn},一个指示变量i表示上一次选择的服务器ID。变量i被初始化为N-1。其算法如下:

j = i;
do
{
    j = (j + 1) mod n;
    i = j;
    return Si;
} while (j != i);
return NULL;

参考:http://www.iteye.com/topic/1113595

权重 weight

      指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况,默认每个服务器的weight权重是1,如果后端服务器down掉,能自动剔除。

      当一个客户请求到达后,RR策略是从upstream的所有server中选择一个当前权重(current_weight)最大的server作为最初的server.

 

权重配置例子:

http {
   upstream myproject {
     server 127.0.0.18000 weight=3;
     server 127.0.0.18001;
     server 127.0.0.18002;
     server 127.0.0.18003;
   }

   server {
     listen 80;
     server_name www.domain.com;
     location / {
         proxy_pass http//myproject;
    }
   }
}

这样的权重算法逻辑:http://blog.sina.com.cn/s/blog_7303a1dc01014i0j.html

最早的算法代码逻辑如下:

 

nginx 负载均衡相关知识_后端服务_02

算法如下:

//按照weight来返回一个peer的下标
//找到当前比率最大的那项,返回这项的下标
static ngx_uint_t
ngx_http_upstream_get_peer( ngx_http_upstream_rr_peers_t *peers )
{
    ngx_uint_t                    i, n;
    ngx_http_upstream_rr_peer_t  *peer;
    peer = &peers->peer[0];
for ( ; ; ){
for ( i = 0; i < peers->number; i++ ) {
if ( peer[i].current_weight <= 0 ){
continue;
            }
            n = i;
while ( i < peers->number - 1 ) {
                i++; // 和下一个比较是否大,如果比下一个小,则返回下一个
if ( peer[i].current_weight <= 0 ){
continue;
                }
if ( peer[n].current_weight * 1000 / peer[i].current_weight
                        > peer[n].weight * 1000 / peer[i].weight ){
return n;
                }
                n = i;
            }
//找到最后了,还没有比第i项比率大的,则说明这项就是,返回这项
if ( peer[i].current_weight > 0 ) {
                n = i;
            }
return n;
        }
//走到这里的时候,说明都是0了,重新初始化为满额,接着循环找,总是能找到一个
for ( i = 0; i < peers->number; i++ ){
            peer[i].current_weight = peer[i].weight;
        }
    }
}


http://blog.xcai.net/fav/nginx-load-balance-analyze

http://stblog.baidu-tech.com/?p=2027

算法伪代码(2012.5.14后修正的算法):

foreach peer in peers {
peer->current_weight += peer->effective_weight;
    total += peer->effective_weight;
 
    if (best == NULL || peer->current_weight > best->current_weight) {
        best = peer;
    }
}
best->current_weight -= total;

一个具体计算的例子:

selected server

current_weight before selected

current_weight after selected

a

{ 5, 1, 2 }

{ -3, 1, 2 }

c

{ 2, 2, 4 }

{ 2, 2, -4 }

a

{ 7, 3, -2 }

{ -1, 3, -2 }

a

{ 4, 4, 0 }

{ -4, 4, 0 }

b

{ 1, 5, 2 }

{ 1, -3, 2 }

a

{ 6, -2, 4 }

{ -2, -2, 4 }

b

{ 3, -1, 6 }

{ 3, -1, -2 }

a

{ 8, 0, 0 }

{ 0, 0, 0 }

http://book.51cto.com/art/201202/314691.htm

 

ip_hash


      每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。 

在ip_hash策略中,它选择最初的server的方法是根据请求客户端的IP计算出一个哈希值,再根据哈希值选择后台的服务器。

由IP计算哈希值的算法如下, 其中公式中hash初始值为89,iphp->addr[i]表示客户端的IP, 通过三次哈希计算得出一个IP的哈希值:

for (i = 0; i < 3; i++) {
      hash = (hash * 113 + iphp->addr[i]) % 6271;
}

在选择下一个server时,ip_hash的选择策略是这样的:它在上一次哈希值的基础上,再次哈希,就会得到一个全新的哈希值,再根据哈希值选择另外一个后台的服务器。
哈希算法仍然是:

for (i = 0; i < 3; i++) {
      hash = (hash * 113 + iphp->addr[i]) % 6271;
}

在这种ip_hash策略,如果一个后台服务器不能提供提服务(连接超时或读超时),该服务器的失败次数就会加一,当一个服务器的失败次数达到max_fails所设置的值,就会在fail_timeout所设置的时间段内不能对外提供服务,这点和RR是一致的。
如果当前server不能提供服务,就会根据当前的哈希值再哈希出一个新哈希值,选择另一个服务器继续尝试,尝试的最大次是upstream中server的个数,如果server的个数超过20,也就是要最大尝试次数在20次以上,当尝试次数达到20次,仍然找不到一个合适的服务器,ip_hah策略不再尝试ip哈希值来选择server, 而在剩余的尝试中,它会转而使用RR的策略,使用轮循的方法,选择新的server。

参考: http://blog.sina.com.cn/s/blog_9c3ba23d01010rof.html

fair


      按后端服务器的响应时间来分配请求,响应时间短的优先分配。 

配置例子如下:

upstream web_pool {
    server 172.23.136.148;
    server 172.23.136.149;
    fair;
}

url_hash

按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。

例:在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法。

upstream web_pool {
    server squid1:3128;
    server squid2:3128;
    hash $request_uri;
    hash_method crc32;
}


 

一致性hash模块(淘宝 tengine特有的算法)

这个模块提供一致性hash作为负载均衡算法。

具体算法,将每个server虚拟成n个节点(根据server权重对应到n个节点),均匀分布到hash环上,每次请求,根据配置的参数计算出一个hash值,在hash环
上查找离这个hash最近的虚拟节点,对应的server作为该次请求的后端机器。

具体哈希值的计算,依赖于客户端信息(如:$ip, $uri, $args等变量)。

例子:

worker_processes  1;

http {
    upstream test {
        consistent_hash $request_uri;

        server 127.0.0.1:9001 id=1001 weight=3;
        server 127.0.0.1:9002 id=1002 weight=10;
        server 127.0.0.1:9003 id=1003 weight=20;
    }
}


说明:该模块可以根据配置参数采取不同的方式将请求均匀映射到后端机器,比如:

  • consistent_hash $remote_addr:可以根据客户端ip映射;
  • consistent_hash $request_uri: 根据客户端请求的uri映射;
  • consistent_hash $args:根据客户端携带的参数进行映射;

上面配置中我们可以看到server id 字段,如果配置id字段,则使用id字段作为server标识,否则使用server ip和端口作为server标识,使用id字段可以手动设置server的标识,比如一台机器的ip或者端口变化,id仍然可以表示这台机器。使用id字段.可以减低增减服务器时hash的波动。

参考:
nginx(tengine)反向代理以及upstream的六种调度算法
http://itoedr.blog.163.com/blog/static/12028429720137113244975

 

 

这几种负载均衡分配方法并不是互相冲突的,我们可以组合使用。

另外还有一些其他负载算法,比如tengine支持的: Session保持模块、后端连接数限制模块、随机负载均衡模块 等就不详细描述了,参看:http://tengine.taobao.org/download/programmer-201209-Tengine.pdf

 

 

 

参考资料:

nginx 的模块及处理流程

Module ngx_http_upstream_module
http://nginx.org/en/docs/http/ngx_http_upstream_module.html 

upstream模块
http://tengine.taobao.org/book/chapter_05.html

nginx中upstream的设计和实现(三)
http://www.pagefault.info/?p=273

 

Nginx学习之六-nginx核心进程模型

解析nginx负载均衡
http://stblog.baidu-tech.com/?p=2027

nginx 配置轮询分流 实现负载均衡的方法
http://www.jbxue.com/article/11590.html

高性能Web服务器Nginx的配置与部署研究(15)Upstream负载均衡模块

Nginx中的upstream轮询机制介绍

高性能Linux服务器构建实战:运维监控、性能调优与集群应用
http://book.51cto.com/art/201202/314644.htm

Nginx 做负载均衡的几种轮询策略
http://zhuruxin86.iteye.com/blog/1694557

标签:负载,hash,weight,server,nginx,均衡,服务器,peer,http
From: https://blog.51cto.com/u_15588078/6768272

相关文章

  • Nginx 代理 WebSocket 、TCP协议
    Nginx代理WebSocket什么是WebSocketWebSocket是一种网络传输协议,可在单个TCP连接上进行全双工通信,位于OSI模型的应用层。WebSocket中的握手和HTTP中的握手过程兼容,且可以使用HTTP中的Upgrade协议头将连接从HTTP升级到WebSocket。代理结构WebSocket可以工作在......
  • 宝塔面板无法开启nginx是怎么回事
    宝塔面板无法开启nginx是怎么回事诶,好不容易解决一个报错,又来一个报错求助解答:您好,您那边是否有安装网站加速插件呢?如果有安装将此插件卸载然后重新安装插件看下是否正常。......
  • nginx 中根据 $http_upgrade 变量将 HTTP 连接升级为 WebSocket 连接
    配置“$connection_upgrade”变量连接升级通常与WebSockets结合使用。在nginx中,我们可以根据$http_upgrade变量将HTTP连接升级为WebSocket连接。我们可以使用map块在nginx中定义连接和http升级之间的依赖关系:vimnginx.confmap$http_upgrade$connection_......
  • crane-scheduler基于真实负载进行k8s调度
    介绍kubernetes的原生调度器只能通过资源请求来调度pod,这很容易造成一系列负载不均的问题:对于某些节点,实际负载与资源请求相差不大,这会导致很大概率出现稳定性问题。对于其他节点来说,实际负载远小于资源请求,这将导致资源的巨大浪费。为了解决这些问题,动态调度器根据实际的......
  • 伪负载均衡(拷贝多个流程
    数厂代码,未实现伪负载均衡//伪负载均衡/*;(()=>{letnodes=JSON.parse(JSON.stringify(data.nodes));letedges=JSON.parse(JSON.stringify(data.edges));//排查特殊节点并记录letstart_node=null,......
  • linux中nginx下载安装部署
    反向代理动静结合负载均衡官网下载稳定版解压tar-zxvfnginx-1.24.0.tar.gz安装nginx的相关依赖yum-yinstallgcczlibzlib-develpcre-developensslopenssl-devel进入解压后的nginx-1.20.2目录cdnginx-1.20.2目录执行configure脚本,设置安装nginx的初始化......
  • Nginx:超时 keeplive_timeout 配置
    参考:Nginx的超时keeplive_timeout配置详解HTTP是一种无状态协议,客户端向服务器发送一个TCP请求,服务端响应完毕后断开连接。如果客户端向服务器发送多个请求,每个请求都要建立各自独立的连接以传输数据。HTTP有一个KeepAlive模式,它告诉webserver在处理完一个请求后保持......
  • Nginx负载均衡配置
    Nginx负载均衡实现:需求:两台Web:192.168.1.2/192.168.1.3,nginx负载均衡服务器192.168.1.10Nginx服务器上实现web负载。 配置步骤:1.安装Nginx  (1)安装依赖包  yuminstall-ypcrepcre-developensslopenssl-develgccgccgcc-c++ncurses-develperl  use......
  • Nginx部署/反向代理配置
    1.Nginx用途介绍  主要技术:地址转换  负载均衡:将客户单请求,按照一定的规则分配到一群服务器上,并将处理结果返回给相应的客户端  作用:负责调度客户端请求、消除单点故障、减少错误返回结果、session持久化。  反向代理:客户端请求,经过反向代理,分发到各服务器,然后服务......
  • shell脚本-Nginx访问日志分析
    shell脚本-Nginx访问日志分析1.原理可以通过/usr/local/nginx/logs/access.log文件-查看nginx的日志[root@localhostscripts]#tail-f/usr/local/nginx/logs/access.log192.168.70.1-[17/Jul/2023:17:35:21+0800]"GET/HTTP/1.1"200173833"-""Mozilla......