Nginx 教程

Nginx 教程 Nginx 简介 Nginx 源码架构分析 Nginx 编译安装 Nginx(Tengine) 编译安装 Nginx(OpenResty) 编译安装 Nginx 配置简述 Nginx Docker 容器化配置

Nginx 核心配置指令

Nginx 核心配置指令 Nginx 配置文件 Nginx 进程配置指令 Nginx 端口监听:listen Nginx 主机名server_name Nginx 处理HTTP请求 Nginx 路由匹配规则:localhost Nginx 重定向配置:rewrite Nginx 根目录配置:root Nginx 访问路径别名:alias Nginx 文件判断:try_files Nginx 零复制:sendfile Nginx 日志记录配置

Nginx HTTP模块

Nginx 镜像模块 Nginx 请求头控制模块 Nginx IP访问控制模块 Nginx 用户cookie模块 Nginx 并发连接数限制模块 Nginx 首页处理模块 Nginx 请求频率限制模块 Nginx 页面缓存时间配置 Nginx gzip压缩及相关配置

Nginx Web服务

Nginx 静态资源服务器搭建 Nginx 文件下载服务器搭建 Nginx 伪动态SSI服务器 Nginx HTTPS服务器搭建 Nginx FastCGI模块配置简述 Nginx PHP服务器环境搭建 Nginx 基于FastCGI负载均衡 Nginx CGI网关接口 Nginx uWSGI模块配置 Nginx Python项目部署 Nginx 伪流媒体服务器搭建 Nginx HTTP2模块配置简述 Nginx WebDAV模块配置简述

Nginx 代理服务器

Nginx HTTP代理服务器 Nginx stream模块简述 Nginx TCP/UDP代理简述 Nginx 基于SSL的TCP代理服务器 Nginx gRPC代理服务器

Nginx 缓存

Nginx Web缓存配置 Nginx 代理缓存配置 Nginx Memcached 缓存模块 Nginx 反向代理缓存服务器配置 Nginx 客户端缓存控制

Nginx 负载均衡

Nginx 负载均衡模块 Nginx 负载均衡策略 Nginx 长连接负载均衡 Nginx upstream容错机制 Nginx upstream动态更新 Nginx TCP/UDP负载均衡

Nginx 日志管理监控

Nginx 日志分析简述 Nginx 访问日志配置 Nginx 错误日志配置 Nginx 日志归档配置 Nginx 日志分析工具 ELK Nginx 监控工具 Prometheus

Nginx 集群

LVS(Linux虚拟服务器)简介 Keepalived 配置简述 Nginx 集群负载搭建 Nginx 集群配置管理规划 Nginx 配置归档工具GitLab Nginx 配置修改工具Ansible Jenkins 安装与配置简述 Nginx 集群配置管理实例

Nginx 在 k8s 的应用

Kubernetes(k8s)系统简述 Kubernetes(k8s)集群部署 Kubernetes(k8s)网络通信 Nginx Ingress 简介 Nginx Ingress 安装部署 Nginx Ingress 配置映射 Nginx Ingress 注解


Nginx upstream容错机制详解

Nginx 在 upstream 模块中默认的检测机制是通过用户的真实请求去检查被代理服务器的可用性,这是一种被动的检测机制,通过 upstream 模块中 server 指令的指令值参数 max_fails 及 fail_timeout 实现对被代理服务器的检测和熔断。

配置样例如下:
upstream http_backend {
    # 10s内出现3次错误,该服务器将被熔断10s
    server 192.168.2.154:8080 max_fails=3 fail_timeout=10s;
    server 192.168.2.109:8080 max_fails=3 fail_timeout=10s;
    server 192.168.2.108:8080 max_fails=3 fail_timeout=10s;
    server 192.168.2.107:8080 max_fails=3 fail_timeout=10s;
}

server {
    proxy_connect_timeout 5s;               # 与被代理服务器建立连接的超时时间为5s
    proxy_read_timeout 10s;                 # 获取被代理服务器的响应最大超时时间为10s

    # 当与被代理服务器通信出现指令值指定的情况时,认为被代理出错,并将请求转发给上游服务器组中
    # 的下一个可用服务器
    proxy_next_upstream http_502 http_504 http_404 error timeout invalid_header;
    proxy_next_upstream_tries 3;            # 转发请求最多3次
    proxy_next_upstream_timeout 10s;        # 总尝试超时时间为10s

    location /http/ {
        proxy_pass http://http_backend;
    }
}
其中的参数和指令说明如下。
  • 指令值参数 max_fails 是指 10s 内 Nginx 分配给当前服务器的请求失败次数累加值,每 10s 会重置为 0;
  • 指令值参数 fail_timeout 既是失败计数的最大时间,又是服务器被置为失败状态的熔断时间,超过这个时间将再次被分配请求;
  • 指令 proxy_connect_timeout 或 proxy_read_timeout 为超时状态时,都会触发 proxy_next_upstream 的 timeout 条件;
  • proxy_next_upstream 是 Nginx 下提高请求成功率的机制,当被代理服务器返回错误并符合 proxy_next_upstream 指令值设置的条件时,将尝试转发给下一个可用的被代理服务器;
  • 指令 proxy_next_upstream_tries 的指令值次数包括第一次转发请求的次数。

Nginx 被动检测机制的优点是不需要增加额外进程进行健康检测,但用该方法检测是不准确的。如当响应超时时,有可能是被代理服务器故障,也可能是业务响应慢引起的。如果是被代理服务器故障,那么 Nginx 仍会在一定时间内将客户端的请求转发给该服务器,用以判断其是否恢复。

Nginx 官方的主动健康检测模块仅集成在商业版本中,对于开源版本,推荐使用 Nginx 扩展版 OpenResty 中的健康检测模块 lua-resty-upstream-healthcheck。该模块的检测参数如下表所示。

参数 默认值 参数说明
shm -- 指定用于健康检测的共享内存名称,共享内存名称由 lua_shared_dict 设定
upstream -- 指定要做健康检查的 upstream 组名
type http 指定检测的协议类型,目前只支持 http
http_req -- 指定用于健康探测的 raw 格式 http 请求字符串
timeout 1000 检测请求超时时间,单位为 ms
interval 1000 健康检测的时间间隔,单位为 ms
valid_status -- 健康检测请求返回的合法响应码列表,比如 {200, 302}
concurrency 1 健康检测请求的并发数,建议大于上游服务器组中的节点数
fall 5 对 UP 状态的设备,连续 fall 次失败,认定为 DOWN
rise 2 对 DOWN 状态的设备,连续 rise 次成功,认定为 UP
version 0 每次执行健康检测时的版本号,有节点状态改变,版本号加 1

模块 lua-resty-upstream-healthcheck 的原理是每到(interval)设定的时间,就会对被代理服务器的 HTTP 端口主动发起 GET 请求(http_req),当请求的响应状态码在确定为合法的列表(valid_status)中出现时,则认为被代理服务器是健康的,如果请求的连续(fall)设定次数返回响应状态码都未在列表(valid_status)中出现,则认为是故障状态。

对处于故障状态的设备,该模块会将其置为 DOWN 状态,直到请求的连续(rise)次返回的状态码都在确定为合法的列表中出现,被代理服务器才会被置为 UP 状态,并获得 Nginx 分配的请求,Nginx 在整个运行过程中不会将请求分配给 DOWN 状态的被代理服务器。

lua-resty-upstream-healthcheck 模块只会使用 Nginx 中的一个工作进程对被代理服务器进行检测,不会对被代理服务器产生大量的重复检测。

配置样例如下:
http {
    # 关闭socket错误日志
    lua_socket_log_errors off;

    # 上游服务器组样例
    upstream foo.com {
        server 127.0.0.1:12354;
        server 127.0.0.1:12355;
        server 127.0.0.1:12356 backup;
    }

    # 设置共享内存名称及大小
    lua_shared_dict _foo_zone 1m;

    init_worker_by_lua_block {
        # 引用resty.upstream.health-check模块
        local hc = require "resty.upstream.healthcheck"

        local ok, err = hc.spawn_checker{
            shm = "_foo_zone",              # 绑定lua_shared_dict定义的共享内存
            upstream = "foo.com",           # 绑定upstream指令域
            type = "http",

            http_req = "GET /status HTTP/1.0\r\nHost: foo.com\r\n\r\n",
                                                # 用以检测的raw格式http请求

            interval = 2000,                # 每2s检测一次
            timeout = 1000,                 # 检测请求超时时间为1s
            fall = 3,                       # 连续失败3次,被检测节点被置为DOWN状态
            rise = 2,                       # 连续成功2次,被检测节点被置为UP状态
            valid_statuses = {200, 302},    # 当健康检测请求返回的响应码为200或302时,被认
                                                # 为检测通过
            concurrency = 10,               # 健康检测请求的并发数为10
        }
        if not ok then
            ngx.log(ngx.ERR, "failed to spawn health checker: ", err)
            return
        end
    }

    server {
        listen 10080;
        access_log  off;                    # 关闭access日志输出
        error_log  off;                     # 关闭error日志输出

        # 健康检测状态页
        location = /healthcheck {
            allow 127.0.0.1;
            deny all;

            default_type text/plain;
            content_by_lua_block {
                # 引用resty.upstream.healthcheck模块
                local hc = require "resty.upstream.healthcheck"
                ngx.say("Nginx Worker PID: ", ngx.worker.pid())
                ngx.print(hc.status_page())
            }
        }
    }
}
以下是对该配置样例的几点说明。
  • 该配置样例参照 OpenResty 官方样例简单修改;
  • 对不同的 upstream 需要通过参数 upstream 进行绑定;
  • 建议为每个上游服务器组指定独享的共享内存,并用参数 shm 进行绑定。