AI 摘要(由 ChatGPT 总结生成):
本文介绍了Nginx负载均衡的相关概念和实现方式。负载均衡通过在多台服务器之间分配访问量,减轻服务器压力,提高响应速度和项目可用性。Nginx支持多种负载均衡方式,包括轮询、权重、IP哈希等。文章还提供了负载均衡的实例配置,并解决了在配置中遇到的301重定向、Session保持和文件存取等问题。通过合理配置,可以实现高效的负载均衡系统。

相关介绍

介绍

负载均衡(Load Balance),它在网络现有结构之上可以提供一种廉价、有效、透明的方法来扩展网络设备和服务器的带宽,并可以在一定程度上增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性等。在网络中,它充当着网络流中“交通指挥官”的角色,“站在”服务器前处理所有服务器端和客户端之间的请求,从而最大程度地提高响应速率和容量利用率,同时确保任何服务器都没有超负荷工作。如果单个服务器出现故障,负载均衡的方法会将流量重定向到其余的集群服务器,以保证服务的稳定性。当新的服务器添加到服务器组后,也可通过负载均衡的方法使其开始自动处理客户端发来的请求。

作用

将原本一台服务器所要承受的访问量分给了多台,减少服务器并发压力,降低网络拥塞,提高服务器响应速度,达到更好的访问质量,也提高了项目的可用性

Nginx负载均衡几种方式

Nginx的upstream目前支持以下几种方式的分配:

轮询(默认):每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
weight:指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
ip_hash:每个请求按访问IP的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。使用后不可给服务器加权重,否则默认为权重请求;不可加 backup ,否则报错。
fair(第三方):按后端服务器的响应时间来分配请求,响应时间短的优先分配。(使用时参数放服务器组最后)
url_hash(第三方):按访问URL的hash结果来分配请求,使每个URL定向到同一个后端服务器,后端服务器为缓存时比较有效。

根据服务器的本身的性能差别及职能,可以设置不同的参数控制。

down:表示负载过重或者不参与负载
weight:权重过大代表承担的负载就越大
backup:备用服务器, 其它所有的非backup机器down或者忙的时候,请求backup机器。
max_fails:失败超过指定次数会暂停或请求转往其它服务器
fail_timeout:失败超过指定次数后暂停时间

负载均衡实例

环境与图示

实验环境:

主机IP系统及环境承载服务
master192.168.17.132CentOS_7_LNMPWAF、网关、负载均衡器
node1192.168.17.131CentOS_7_LNMPWEB服务
node2192.168.17.133CentOS_7_LNMPWEB服务
node3192.168.17.130CentOS_7_LNMPMySQL、文件存储、WEB服务(备份)、memcached缓存

简单拓补图如图所示:
拓补图1.png

负载均衡策略

master端Nginx配置如下:

#定义后端服务器组
upstream typecho{
        # ip_hash;   #每个请求按访问ip的hash结果分配,以此每个访客固定访问一个后端服务器;不可给服务器加权重
        # url_hash;    #每个请求按访问url的hash结果分配,这样每个url请求固定访问一个后端服务器,需额外安装模块(hash $request_uri;)
        # fair;   #按后端服务器的响应时间来分配请求,响应时间短的优先分配。 放最后
        # weight   #指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。

        #ip_hash; # 后面由于采用了memcached存取Session会话凭据,故此处不在采用ip_hash策略
        server 192.168.17.133:8080 weight=1 max_fails=3 fail_timeout=30s;
        server 192.168.17.131:8080 weight=1 max_fails=3 fail_timeout=30s;
        server 192.168.17.130:8080 backup;
    }

server {
        listen 80;
        listen [::]:80;

        #启用HTTPS
        #listen 443 ssl http2;
        #listen [::]:443 ssl http2;

        server_name _;  #设置请求域名或IP
        
        
        #SSL相关配置,勿删除或修改下一行带注释的404规则
        #error_page 404/404.html;
        #ssl_certificate    /******/fullchain.pem;
        #ssl_certificate_key    /******/privkey.pem;
        #ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
        #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
        #ssl_prefer_server_ciphers on;
        #ssl_session_cache shared:SSL:10m;
        #ssl_session_timeout 10m;
        #add_header Strict-Transport-Security "max-age=31536000";  # HSTS配置
        #error_page 497  https://$host$request_uri;

    location / {
        #开启Modsecurity功能(WAF)
        modsecurity on;
        modsecurity_rules_file /usr/local/nginx/conf/modsec_includes.conf;

        proxy_pass http://typecho;
        #proxy_set_header HOST   $host:$server_port;  #转发时定义端口,测试时使用,正常情况使用下面那条
        proxy_set_header HOST   $host;
        proxy_set_header X-Real-IP      $remote_addr;
        proxy_set_header X-Forwarded-FOR $proxy_add_x_forwarded_for;

        #设置相关优化
        #proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
        proxy_buffering on;
        proxy_buffer_size 32k;
        proxy_busy_buffers_size 256k;
        proxy_buffers 256 4k;
        proxy_max_temp_file_size 0;
        proxy_connect_timeout 30;
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 301 1h;
        proxy_cache_valid any 1m;
    }

        #访问记录日志与错误日志
        access_log  /www/wwwlogs/test.log;
        error_log  /www/wwwlogs/test.error.log;
    }

node1、node2端Nginx配置如下,此处为测试,故引用了typecho博客作为测试站点:

server {
        listen       8080;  #监听8080端口
        server_name _;  #设置请求域名或IP

        root   /www/wwwroot/book;    #默认网站根目录
       
        absolute_redirect off;    #取消绝对路径的重定向(nginx ≥1.11.8)
        #port_in_redirect off;   #取消绝对路径的重定向(nginx <1.11.8)

        location / {
        #默认页面
        index index.php index.html index.htm default.php default.htm default.html;

        #伪静态(typecho)
        if (!-e $request_filename) {
        rewrite ^(.*)$ /index.php$1 last;
        }

    }
    
    #禁止访问文件
    location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md)
        {
            return 404;
        }
    
    #申请SSL证书验证目录相关设置
    location ~ \.well-known{
            allow all;
        }
    
    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
        {
            expires      30d;
            error_log off;
            access_log /dev/null;
        }

    location ~ .*\.(js|css)?$
        {
            expires      12h;
            error_log off;
            access_log /dev/null; 
        }

        #引用的PHP配置
        include /usr/local/nginx/conf/enable-php73.conf;

        #访问记录日志与错误日志
        access_log  /www/wwwlogs/test.log;
        error_log  /www/wwwlogs/test.error.log;
    }

遇到的问题

1、301重定向问题

在上述配置中,前端服务器master将接收到的请求分配到后端服务器完成处理,后端服务器完成处理后在交由前端服务器分发给客户。但是在处理的时候,对于访问二级目录,例如:http://test.yfriend.xyz/admin,对于此请求正常来说应该是访问的是一个文件,但是在WEB目录下这表示一个二级目录,请求时Nginx会自动给它一个301重定向到http://test.yfriend.xyz/admin/,即在新的Location中加了斜杠,再去寻找页面文件;但这个默认行为在Nginx前端有负载均衡器、且后端端口与Nginx Server监听的端口不同时,可能会导致访问出错。

比如域名所指向的前端Nginx对外监听端口80,转发到后端Nginx 8080端口,当Nginx进行上述自动重定向时,导致重定向到了域名的8080端口,如:

$ curl -I http://test.yfriend.xyz/admin

HTTP/1.1 301 Moved Permanently
Date: Fri, 05 Feb 2021 08:27:50 GMT
Content-Type: text/html
Content-Length: 178
Connection: keep-alive
Server: nginx
Location: http://test.yfriend.xyz:8080/admin/

此时,对于Nginx有两种解决办法:

1)新版本Nginx(版本 ≥1.11.8)可以通过设置absolute_redirect off;来解决,如下:

server {
        listen       8080;  #监听8080端口
        server_name _;  #主机,默认全部

        root   /www/wwwroot/book;    #默认网站根目录
       
        absolute_redirect off;   #取消绝对路径的重定向,使用相对路径重定向
        …………

2)旧版本Nginx(版本<1.11.8)可以增加port_in_redirect off;参数来解决,如下:

server {
        listen       8080;  #监听8080端口
        server_name _;  #主机,默认全部

        root   /www/wwwroot/book;    #默认网站根目录
       
        #absolute_redirect off;   #取消绝对路径的重定向,使用相对路径重定向
        port_in_redirect off;   #去掉重定向后的Location中的端口
        …………

然后重启后端Nginx服务,即可

2、Session保持

当一个用户第一次访问被负载均衡代理到后端服务器node1并登录后,服务器node1上保留了用户的登录信息;当用户再次发送请求时,
根据负载均衡策略可能被代理到后端不同的服务器,例如服务器node2,由于这台服务器node2没有用户的登录信息,所以导致用户需要重新登录。

对于Nginx可以选用Session保持的方法实行负载均衡,Nginx的upstream目前支持5种方式的分配方式,其中有两种比较通用的Session解决方法,ip_hashurl_hashurl_hash需额外安装拓展)。但是这种方法仍有不合理之处,即后端某服务器若是遭到意外宕机,那么基于该服务器的请求会转移至另一台机器,但是另一台机器没你的session凭据,就会重新验证。于是在这儿采用Memcached服务用作会话存储,使得负载均衡对机器实现session会话共享。

3、文件存取

由于采用负载均衡,如果某个文件上传页面将文件txt1上传到node1主机,但是使用下载页面却分流到node2主机,那么下载文件txt1时,就会出现找不到文件txt1的情况。现考虑几种部署方案,如下:

一、采用局域网内NFS网络挂载磁盘至文件目录,以此达到文件共享;
二、方案是采用分布式文件系统存储文件;
三、采用文件同步方式

End

本文标题:Nginx实现负载均衡

本文链接:https://www.isisy.com/1061.html

除非另有说明,本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

声明:转载请注明文章来源。

如果觉得我的文章对你有用,请随意赞赏