Nginx 负载均衡的配置方案和配置参数详解

摘要:nginx 利用反向代理来做负载均衡,nginx 给出了多重负载分发的方式,比如轮询,ip_hash,weight 等等,翻翻官方文档用一台服务器实现了最简单的 nginx 负载均衡配置实例,但是配置好负载均衡后也会带来很多问题,我们需要一一应对和解决。

负载均衡是什么

负载均衡其实就是老板指挥多个员工干活,然后按照一定的规则和标准对员工进行管理和分配工作,让每个员工的工作量达到一个均衡的标准。如果换成公司网站服务器的架构来看,就是利用 nginx 来做负载均衡,然后利用 nginx 的反向代理将请求转发到上游的 upstream 多台服务器中,在转发之前我们需要配置下转发方式,比如是一台一次,还是一台多次等等,这中间会有一定的规则需要我们了解。


负载均衡主要配置项

upstream:负载均衡组,负载均衡会将用户请求根据一定规则转发到组中的节点上。

proxy_pass:反向代理,将请求转发到其它服务器,或者上游的 upstream 组中。

http {
    upstream myapp1 {
        server srv1.example.com;
        server srv2.example.com;
        server srv3.example.com;
    }

    server {
        listen 80;
        location / {
            proxy_pass http://myapp1;
        }
    }
}


upstream 指令参数

upstream 主要配置参数有 max_conns、slow_start、down、backup、max_fails、fail_timeout、keepalive 等等,这些是开源版可以使用的参数,还有一些参数是商业版用的,开源版是无法使用的。具体请看:http://nginx.org/en/docs/http/ngx_http_upstream_module.html,以下对上述参数做下配置详解。

max_conns,限制每台 server 连接数,用于保护避免过载,可起到限流的作用。需要注意的是 1.11.5 版本之前是只能用于商业的。

# worker 进程设置 1 个,便于测试观察成功的连接数
worker_processes 1;

upstream myapp1 {
    server 192.168.23.128 max_conns=2;
    server 192.168.23.129 max_conns=2;
    server 192.168.23.130 max_conns=2;
}


slow_start,这个参数现在只能商业版用,开源版是不能用的。他的意思是缓慢启动,因为有可能该 server 在启动之后,需要加载一些别的监听软件或者是不想马上就加入负载的组中。配置上此参数后,他会慢慢的在指定时间内,把 weight 负载权重的参数从 0 升级到对应值,相当于从一个不健康的服务器,变成一个健康的服务器。

upstream myapp1 {
    server 192.168.23.128 weight=6 slow_start=60s;
    server 192.168.23.129 weight=6;
    server 192.168.23.130 weight=6;
}

当 nginx 启动后,192.168.23.128 这台服务器会在 60s 内慢慢从权重 0 升级到 权重 6。需要注意的是该参数不能与 hash,ip_hash和随机 负载平衡方法一起使用。如果只有一组在一台服务器,max_fails, fail_timeout和slow_start参数将被忽略,而这样的服务器将永远不会被视为不可用。


down,用于标记服务节点不可用,意思就是用户请求不会转发给 down 掉的节点。

upstream myapp1 {
    server 192.168.23.128 down;
    server 192.168.23.129 weight=1;
    server 192.168.23.130 weight=1;
}


backup,标识当前节点是一个备用节点,只有在所有的节点都宕机后,自己才会加入到集群中,被用户访问到。需要注意的是,该参数不能与 hash,ip_hash和随机 负载平衡方法一起使用。

upstream myapp1 {
    server 192.168.23.128 down;
    server 192.168.23.129 weight=1;
    server 192.168.23.130 weight=1;
}


max_fails 和 fail_timeout 参数,这两个参数需要一起使用。其中 max_fails(默认 1) 表示失败几次,则标记改节点已宕机,不再被用户访问到,当该参数设置为 0 时,将禁用此服务器的运行状况检查。fail_timeout(默认 10s) 表示失败的重试时间。

upstream myapp1 {
    server 192.168.23.128 max_fails=2 fail_timeout=15s;
    server 192.168.23.129;
    server 192.168.23.130;
}

其实我们可以这样理解,比如在 15s 中,我们的会请求到某一个 server,如果说这个 server 失败了,并且达到了两次,就会认为该 server 宕机了。那么在接下来的 15s 内,就不会有新的请求发送到这台宕机的 server 中去。而是会把请求发送到那些正常运作的 server 中去,让那些正常的 server 去处理请求。在 15s 过后,如果有新的请求过来,那么就会去尝试请求刚刚宕机的那台 server。如果失败了 2 次,就会按照上面的步骤循环下去,直到宕机的 server 服务回复正常。


keepalive,设置长连接处理的数量,可以提高吞吐量。具体请看: http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive。该参数设置每个工作进程的高速缓存中保留的到上游服务器的空闲保持连接的最大数量。如果超过此数量,则关闭最近最少使用的连接。

http {
    upstream myapp1 {
        server srv1.example.com;
        server srv2.example.com;
        server srv3.example.com;
        keepalive 32;
    }

    server {
        listen 80;
        location / {
            proxy_pass http://myapp1;
            proxy_http_version 1.1; # 设置长连接 http 版本为 1.1
            proxy_set_header Connection ""; # 清除 connection header 信息 
        }
    }
}


负载均衡方法

负载均衡方法有三种:轮询(默认)、ip_hash、最少连接等。具体可参考:http://nginx.org/en/docs/http/load_balancing.html。还有几种是第三方的负载均衡方式比如 fair、url_hash 等。

轮询(round-robin),对应用程序服务器的请求以轮询的方式分发。这种方式是默认的,如果我们没有配置分发方式,那么默认的分发方式就是轮询。一个节点一次,雨露均沾。

upstream myapp1 {
    server 192.168.23.128;
    server 192.168.23.129;
    server 192.168.23.130;
}


最少连接(least-connected),将下一个请求分配给活动连接数量最少的服务器。在分发请求的过程中,每个请求处理过程的复杂度是不一样的,有的可能消耗的资源的多一些,有的少一些,如果使用轮询的话,可能不会在意每个节点的负载情况,只是一味地将请求分发给该节点。

为了更加公平的分发,nginx 将不使负载过多的服务器因为请求处理不过来而负载过高,会将一些请求分发给不太繁忙的服务器。

upstream myapp1 {
    least_conn;
    server 192.168.23.128;
    server 192.168.23.129;
    server 192.168.23.130;
}


ip_hash,可以根据用户请求的 ip 地址,将请求分发到 upstream 中固定的服务器,前提是用户的  ip 没有改变。这种分发方式有一个优点,就是会话持久性。因为如果是轮询或者最少连接数的分发方式就会导致用户的 session 信息无法同步。为了避免这种情况,可以使用 ip_hash 负载平衡机制。nginx 将通过对客户端 IP 计算哈希值之后,再对服务器数量取模得到目标服务器的序号,来实现会话粘滞。

upstream myapp1 {
    ip_hash;
    server 192.168.23.128;
    server 192.168.23.129;
    server 192.168.23.130;
}

关于 nginx 的 ip_hash 算法源码在 nginx 编译包根目录下的 src/http/modules/ngx_http_upstream_ip_hash_module.c 里面,有兴趣的可以看下。需要注意的是如果某台服务器需要临时删除,则应使用 down 参数标记该服务器,以保留客户端 ip 地址的当前哈希值。还有就是在 1.3.1 和 1.2.2 版本之前,无法使用 ip_hash 负载平衡方法为服务器指定权重。


但是在轮询的基础上还有一个配置就是加权负载均衡。类似地,在最新版本的 nginx 中,可以使用权重最少的连接和 ip-hash 负载平衡。

upstream myapp1 {
    server 192.168.23.128 weight=1;
    server 192.168.23.129 weight=2;
    server 192.168.23.130 weight=5;
}

这样配置后,8 个请求里面有 5 个给 130,2 个给 129,1 个给 128 节点。这种方式一般就是能者多劳,因为有可能所有节点中,有的硬件配置好,有的配置不够好,那么配置好的节点处理的请求就会多一点。


fair,按节点的响应时间来分配请求,响应时间短的优先分配。

upstream myapp1 {
    server 192.168.23.128;
    server 192.168.23.129;
    server 192.168.23.130;
    fair;
}


url_hash,之前的 ip_hash 根据用户 ip 进行的 hash,现在是根据用户访问的 url 进行 hash,然后分发到对应的节点。

upstream myapp1 {
    hash $request_uri;
    
    server 192.168.23.128 weight=1;
    server 192.168.23.129 weight=2;
    server 192.168.23.130 weight=5;
}


一台服务器的负载均衡配置小 demo

events {

}
http {
    #upstream 模块应放于 http 模块中,默认的分配方式是轮寻
    upstream myweb {
        server 98.142.138.117:8081 weight=3;#weight 分配权重,值越大负载的权重越大
        server 98.142.138.117:8082  down;#表示当前 server 不参与负载
        #以下表明如果此分发节点在10秒内出现2次不可用,那10秒内不会再分发到此节点,直到10秒后再次重新检测节点健康情况
        #如果将 max_fails=0 则停止检查节点健康情况 
        server 98.142.138.117:8083 max_fails=2 fail_timeout=10s;
    }

    server {
        listen 80;
    
        location / {
            #配置一个反向代理,这里的设置和上面的 upstream 相对应的,你也可以将这里设置成 http://www.baidu.com
            #这样你访问你的ip浏览器出现的就是百度的内容了
            #如果你将这里设置成和上面的 myweb 一样,那么所有的请求都代理到 upstream 服务器组 myweb
            proxy_pass http://myweb;
        }
    }

    server {
        listen 8081;
        root /usr/local/nginx/html/web1;
    }

    server {
        listen 8082;
        root /usr/local/nginx/html/web2;
    }
}

为了方便演示效果,我用一台服务器搭建了下。正常来讲如果你没有多台服务器,你可以用虚拟机装一台环境,然后再克隆出两台就可以了,然后一台做负载均衡服务器分发服务,另外两台来接受分发来学习负载均衡。

上面的这段我已经配置好了,你只需要将这段配置替换掉你 nginx.conf 中的配置,然后 ip 换成你服务器的 ip 然后在 web1 和 web2 目录下新建两个不同的 index.html 文件就可以了,然后就可以访问查看效果了。


负载均衡带来的问题

负载均衡的优点有很多,但是使用 nginx 搭建负载均衡集群也会带来很多问题,比如会话粘带问题、上传图片问题、当前负责负载均衡的服务器挂掉怎么办?对后端服务器的健康检查等等一系列问题。不过好在这些问题都有解决的办法,此处不赘述。


参考资料:

Using nginx as HTTP load balancer

结束语:感谢您对本网站文章的浏览,欢迎您的分享和转载,但转载请说明文章出处。
Top