6

这是 Nginx 学习总结的第六篇,上一篇介绍到了 Nginx 学习总结(5) —— 反向代理,本文主要演示结合 proxyupstream 模块的使用来实现 Nginx 的负载均衡。

Nginx 官网中对 upstream 模块的介绍:ngx_http_upstream_module 模块用于定义可由 proxy_passfastcgi_passuwsgi_passscgi_passmemcached_pass 指令引用的服务器组。

Context:http

准备工作

在 VMware 上准备 3 台服务器(centos_7_x64),分别安装了 Nginx(1.12.0),它们能够互相 ping 通,3台服务器 IP 分别为:

  • 192.168.4.221(Web 服务器 A)
  • 192.168.4.222(Web 服务器 B)
  • 192.168.4.223(反向代理服务器 C)

在 Web 服务器的根目录下的 index.html 文件内容分别为:

<h1>Welcome to 192.168.4.221 !</h1>
<h1>Welcome to 192.168.4.222 !</h1>

反向代理配置

在 Nginx 下配置反向代理,主要是 proxyupstream 模块的配置。我们将反向代理服务器 C 的配置修改成如下:

upstream jochen {
    server 192.168.4.221:80;
    server 192.168.4.222:80;
}

server {
    listen       80;
    server_name  localhost;

    charset      utf-8;

    location / {
        proxy_pass http://jochen;

        proxy_set_header HOST            $host;
        proxy_set_header X-Real-IP       $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
    
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}

配置好之后,重启反向代理服务器 C ,浏览器访问 http://192.168.4.223
图片描述

浏览器刷新页面:
图片描述

我们可以发现,访问的内容的确是 Web 服务器 A 或 B 提供的内容,表明我们的反向代理是配置成功了。而且,响应内容是由 Web 服务器 A、B 依次轮流提供的。

实现负载均衡

负载均衡是反向代理技术的一种运用。客户端访问服务器,服务器会把请求分发给其它多个不同的服务器(即反向代理),从而减轻了单个服务器处理海量请求的压力,不会出现崩溃,即如图:
图片描述

在上面的配置中,我们没有设置 upstream 的分配方式,默认情况下,这将采用轮询的方式,即每个请求按时间逐一分配到不同的后端服务器。如果后端服务器 down 掉,能自动剔除。而实现负载均衡的核心在于如何将请求合理地分配给不同的后端服务器。

在现实生活中,不同服务器的 CPU 、内存、硬盘、网络带宽的性能都是不同的,因而它们各自的处理能力各不一样。需要采用某种负载均衡调度算法,来将请求合理地分配给不同的后端服务器,以达到最佳化资源使用、最大化吞吐率、最小化响应时间、同时避免过载的目的。

在 Nginx 中,upstream 的分配方式有 5 种,分别是:

1. 轮询(默认)

每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器 down 掉,能自动剔除。如:

upstream jochen {
    server 192.168.4.221:80;
    server 192.168.4.222:80;
}
2. weight

指定轮询几率,weight 和访问比率成正比,用于后端服务器性能不均的情况。如:

upstream jochen {
    server 192.168.4.221:80 weight=10;
    server 192.168.4.222:80 weight=20;
}
3. ip_hash

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

upstream jochen {
    server 192.168.4.221:80;
    server 192.168.4.222:80;
    ip_hash;
}
4. fair(第三方)

按后端服务器的响应时间来分配请求,响应时间短的优先分配。这个是第三方模块,需要额外安装。如:

upstream jochen {
    server 192.168.4.221:80;
    server 192.168.4.222:80;
    fair;
}
5. url_hash(第三方)

按访问 url 的 hash 结果来分配请求,使每个 url 定向到同一个后端服务器,后端服务器为缓存时比较有效。这个是第三方模块,需要额外安装。如:

upstream jochen {
    server 192.168.4.221:80;
    server 192.168.4.222:80;
    hash $request_uri;
    hash_method crc32;
}

upstream 模块中,可以通过 server 指令定义服务器的地址和其他参数。地址可以指定为域名,或 IP 地址(端口可选,默认为80),或 "unix" 为前缀的套接字路径。

Context: upstream

常用的参数有:

  • down 将服务器标记为永久不可用
  • weight 设置服务器的权重,默认情况下为 1
  • backup 将服务器标记为备份服务器。当主服务器不可用时,它将被传递请求
  • max_fails 允许请求失败的次数,默认为 1
  • fail_timeout 在经历了 max_fails 次失败后,暂停服务的时间。max_fails 可以和 fail_timeout 一起使用
upstream jochen {
    server backend1.example.com  weight=5;
    server 192.168.4.222:80      max_fails=3 fail_timeout=30s;
    server unix:/tmp/backend3;
    server backup1.example.com   backup;
}

健康检查

Nginx 自身是没有针对负载均衡后端节点健康检查的模块,nginx_upstream_check_module 是专门用于负载均衡健康检查的第三方模块,由淘宝的姚伟斌大神开发,通过它可以用来检测后端 server 的健康状态。nginx_upstream_check_module 模块会持续检查 server 的状态,如果某个 server 不可用,则请求就不会被转发到该 server 上。项目地址:https://github.com/yaoweibin/...

下面的是一个带负载均衡健康检查的 nginx.conf 配置:

upstream jochen {
    server 192.168.4.221:80 weight=5 max_fails=2 fail_timeout=30s;
    server 192.168.4.222:80 weight=1 max_fails=2 fail_timeout=30s;

    check interval=5000 rise=2 fall=3 timeout=1000 type=http;
    check_http_send "HEAD / HTTP/1.0\r\n\r\n";
    check_http_expect_alive http_2xx http_3xx;
}

server {
    listen       80;
    server_name  localhost;

    charset      utf-8;

    location / {
        proxy_pass http://jochen;

        proxy_set_header HOST            $host;
        proxy_set_header X-Real-IP       $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location /nginx-status {
        stub_status; 
        access_log off;
        allow 192.168.4.220;
        deny all;
    }

    location /check-status {
        check_status;
        access_log off;
        allow 192.168.4.220;
        deny all;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}

重启 Nginx 配置生效之后,可以看到 error.log 日志如下信息,说明 nginx_upstream_check_module 模块已正常运行:

2018/03/29 15:12:48 [error] 46931#46931: enable check peer: 192.168.4.221:80 
2018/03/29 15:12:50 [error] 46931#46931: enable check peer: 192.168.4.222:80

同时,访问 http://192.168.4.223/check-status ,可以看到如下页面:
图片描述

上面配置的意思是,对 jochen 这个服务器组中的所有 server,每5秒检测一次,请求 2 次正常则标记 server 状态为up,如果检测 3 次都失败,则标记 server 的状态为 down,超时时间为1秒。

nginx_upstream_check_module 模块的指令详情见 https://github.com/yaoweibin/...,常用指令说明如下:

  1. check 为上游服务器添加运行状况检查,常用参数如下:

    • interval 向后端发送的健康检查包的间隔
    • fall 如果连续失败次数达到 fall_count,服务器就被认为是 down
    • rise 如果连续成功次数达到 rise_count,服务器就被认为是 up
    • timeout 后端健康请求的超时时间
    • type 健康检查包的类型,包括 tcp、http、ajp、ssl_hello、mysql、fastcgi
  2. check_http_send 配置 HTTP 监控检查包发送的请求内容,为了减少传输数据量,推荐采用 HEAD 方法。
  3. check_http_expect_alive 指定 HTTP 回复的成功状态,默认认为 2XX 和 3XX 的状态是健康的。

参考文章:

  1. Nginx 反向代理和负载均衡配置
  2. Module ngx_http_upstream_module
  3. nginx 做负载均衡器以及 proxy 缓存配置
  4. nginx_upstream_check_module

Jochen
846 声望85 粉丝

Stay hungry, stay foolish.