流模块#

核心流模块实现了处理 TCP 和 UDP 连接的基本功能:包括定义服务器块、流量路由、配置代理、SSL/TLS 支持,以及管理流式服务(如数据库、DNS 和其他基于 TCP 和 UDP 运行的协议)的连接。

本节中的其他模块扩展了此功能,允许您灵活地配置和优化流服务器以适应各种场景和需求。

从源代码构建 时, 此模块默认不会被构建; 应使用 ‑‑with‑stream 构建选项 启用它。 在来自 我们仓库 的软件包和镜像中, 该模块已包含在构建中。

配置示例#

worker_processes auto;

error_log /var/log/angie/error.log info;

events {
    worker_connections  1024;
}

stream {
    upstream backend {
        hash $remote_addr consistent;

        server backend1.example.com:12345 weight=5;
        server 127.0.0.1:12345            max_fails=3 fail_timeout=30s;
        server unix:/tmp/backend3;
    }

    upstream dns {
       server 192.168.0.1:53535;
       server dns.example.com:53;
    }

    server {
        listen 12345;
        proxy_connect_timeout 1s;
        proxy_timeout 3s;
        proxy_pass backend;
    }

    server {
        listen 127.0.0.1:53 udp reuseport;
        proxy_timeout 20s;
        proxy_pass dns;
    }

    server {
        listen [::1]:12345;
        proxy_pass unix:/tmp/stream.socket;
    }
}

指令#

listen#

语法

listen address[:port] [ssl] [udp] [proxy_protocol] [setfib=number] [fastopen=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [ipv6only=on | off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]];

默认值

上下文

server

设置服务器将接受连接的套接字的 addressport。可以只指定 port,这样 Angie 将监听所有可用的 IPv4(以及 IPv6,如果已启用)接口。地址也可以是主机名,例如:

listen 127.0.0.1:12345;
listen *:12345;
listen 12345;     # 与 *:12345 相同
listen localhost:12345;

IPv6 地址用方括号指定:

listen [::1]:12345;
listen [::]:12345;

UNIX 域套接字使用 unix: 前缀指定:

listen unix:/var/run/angie.sock;

端口范围通过用连字符分隔的第一个和最后一个端口来指定:

listen 127.0.0.1:12345-12399;
listen 12345-12399;

备注

不同的服务器必须监听不同的 address:port 对。

ssl

允许指定在此端口上接受的所有连接应在 SSL 模式下工作。

udp

配置监听套接字以处理数据报。为了在同一会话中处理来自相同地址和端口的数据包,还应指定 reuseport 参数。

proxy_protocol

允许指定在此端口上接受的所有连接应使用 PROXY 协议。

listen 指令可以有几个与套接字相关的系统调用特定的附加参数。

setfib=number

为监听套接字设置关联的路由表 FIB(SO_SETFIB 选项)。目前仅在 FreeBSD 上有效。

fastopen=number

为监听套接字启用"TCP Fast Open",并 限制 尚未完成三次握手的连接队列的最大长度。

警告

除非服务器能够处理多次接收 相同的带数据的 SYN 数据包,否则不要启用此功能。

backlog=number

设置 listen() 调用中的 backlog 参数,该参数限制待处理连接队列的最大长度。默认情况下,在 FreeBSD、DragonFly BSD 和 macOS 上,backlog 设置为 -1,在其他平台上设置为 511。

rcvbuf=size

设置监听套接字的接收缓冲区大小(SO_RCVBUF 选项)。

sndbuf=size

设置监听套接字的发送缓冲区大小(SO_SNDBUF 选项)。

accept_filter=filter

设置监听套接字的接受过滤器名称(SO_ACCEPTFILTER 选项),该过滤器在将传入连接传递给 accept() 之前对其进行过滤。这仅在 FreeBSD 和 NetBSD 5.0+ 上有效。可接受的值为 datareadyhttpready

deferred

指示在 Linux 上使用延迟 accept()TCP_DEFER_ACCEPT 套接字选项)。

bind

此参数指示为给定的 address:port 对进行单独的 bind() 调用。事实上,如果有多个具有相同 port 但不同地址的 listen 指令,并且其中一个 listen 指令监听给定端口的所有地址(*:port),Angie 将只 bind()*:port。应该注意的是,在这种情况下将进行 getsockname() 系统调用以确定接受连接的地址。如果使用了 setfibfastopenbacklogrcvbufsndbufaccept_filterdeferredipv6onlyreuseportso_keepalive 参数,则对于给定的 address:port 对将始终进行单独的 bind() 调用。

ipv6only=on | off

此参数(通过 IPV6_V6ONLY 套接字选项)确定监听通配符地址 [::] 的 IPv6 套接字是仅接受 IPv6 连接还是同时接受 IPv6 和 IPv4 连接。此参数默认开启。它只能在启动时设置一次。

reuseport

此参数指示为每个工作进程创建单独的监听套接字(在 Linux 3.9+ 和 DragonFly BSD 上使用 SO_REUSEPORT 套接字选项,或在 FreeBSD 12+ 上使用 SO_REUSEPORT_LB),允许内核在工作进程之间分配传入连接。目前仅在 Linux 3.9+、DragonFly BSD 和 FreeBSD 12+ 上有效。

警告

不当使用此选项可能会带来安全隐患。

multipath

启用通过 多路径 TCP <https://en.wikipedia.org/wiki/Multipath_TCP>`__(MPTCP)协议接受连接,从 5.6 版本开始在 Linux 内核中支持。 此参数与 :samp:`udp 不兼容

so_keepalive=on | off | [keepidle]:[keepintvl]:[keepcnt]

配置监听套接字的"TCP keepalive"行为。

''

如果省略此参数,则套接字将使用操作系统的设置

on

为套接字开启 SO_KEEPALIVE 选项

off

为套接字关闭 SO_KEEPALIVE 选项

某些操作系统支持使用 TCP_KEEPIDLETCP_KEEPINTVLTCP_KEEPCNT 套接字选项在每个套接字的基础上设置 TCP keepalive 参数。在这些系统上(目前包括 Linux 2.4+、NetBSD 5+ 和 FreeBSD 9.0-STABLE),可以使用 keepidlekeepintvlkeepcnt 参数进行配置。可以省略一个或两个参数,在这种情况下,相应套接字选项的系统默认设置将生效。

例如,

so_keepalive=30m::10

将空闲超时(TCP_KEEPIDLE)设置为 30 分钟,将探测间隔(TCP_KEEPINTVL)保留为系统默认值,并将探测次数(TCP_KEEPCNT)设置为 10 次探测。

preread_buffer_size#

语法

preread_buffer_size size;

默认值

preread_buffer_size 16k;

上下文

stream, server

指定 预读 缓冲区的大小。

preread_timeout#

语法

preread_timeout timeout;

默认值

preread_timeout 30s;

上下文

stream, server

指定 预读 阶段的超时时间。

proxy_protocol_timeout#

语法

proxy_protocol_timeout timeout;

默认值

proxy_protocol_timeout 30s;

上下文

stream, server

指定读取 PROXY 协议头完成的超时时间。如果在此时间内未传输完整个头部,则连接将被关闭。

resolver#

语法

resolver address ... [valid=time] [ipv4=on | off] [ipv6=on | off] [status_zone=zone];

默认值

上下文

stream, server, upstream

配置用于将上游服务器名称解析为地址的域名服务器,例如:

resolver 127.0.0.53 [::1]:5353;

地址可以指定为域名或 IP 地址,并可选端口。如果未指定端口,则使用端口 53。域名服务器以轮询方式查询。

备注

该指令值会被嵌套块继承, 并可在其中根据需要覆盖。 在单个块内,该指令只能指定一次。 如果重复指定,则最后的定义生效。

默认情况下,Angie 使用响应的 TTL 值缓存答案。如果 未指定 resolver 指令且不执行动态 DNS 查询 (例如,在 代理 中使用固定名称而不使用 变量时),则不需要指定解析器:名称将在启动时 使用系统解析器进行解析。可选的 valid 参数允许 覆盖此行为:

valid

可选 参数允许覆盖响应缓存的有效期

resolver 127.0.0.53 [::1]:5353 valid=30s;

默认情况下,Angie 在解析时会同时查找 IPv4 和 IPv6 地址。

ipv4=off

禁用 IPv4 地址查找

ipv6=off

禁用 IPv6 地址查找

status_zone

可选 参数; 在指定区域中启用 DNS 服务器请求和响应指标的收集 (/status/resolvers/<zone>)

小技巧

为防止 DNS 欺骗,建议在适当安全的可信本地网络中使用 DNS 服务器。

小技巧

Docker 中运行时,使用相应的内部 DNS 服务器地址,例如 127.0.0.11

resolver_timeout#

语法

resolver_timeout time;

默认值

resolver_timeout 30s;

上下文

stream、server、upstream

设置名称解析的超时时间,例如:

resolver_timeout 5s;

server#

语法

server { ... }

默认值

上下文

stream

设置服务器的配置。

server_name#

语法

server_name name ...;

默认值

server_name "";

上下文

server

设置虚拟服务器的名称。

警告

stream 模块中,:samp:server_name 指令基于服务器名称指示 (SNI),仅适用于 TLS 连接。要使用它, 必须在相应的 server 块中 配置 TLS 终止启用 TLS 预读

配置示例:

server {
    listen 443 ssl;
    server_name example.com www.example.com;
    ssl_certificate /etc/angie/cert.pem;
    ssl_certificate_key /etc/angie/key.pem;
}

第一个名称成为主服务器名称。

服务器名称可以包含星号 (*) 来替换名称的第一部分或最后一部分:

server {
    server_name example.com *.example.com www.example.*;
}

这些名称称为通配符名称。

您还可以在服务器名称中使用正则表达式,方法是在名称前加上 波浪号 (~):

server {
    server_name www.example.com ~^www\d+\.example\.com$;
}

正则表达式可以包含捕获,可在其他指令中使用:

server {
    server_name ~^(www\.)?(.+)$;

    proxy_pass www.$2:12345;
}

正则表达式中的命名捕获会创建变量, 可在其他指令中使用:

server {
    server_name ~^(www\.)?(?<domain>.+)$;

    proxy_pass www.$domain:12345;
}

如果指令的参数设置为 $hostname,则会插入机器的主机名。

按名称搜索虚拟服务器时,如果名称匹配多个 指定的变体(例如,通配符名称和正则表达式 都匹配),将按以下优先级顺序选择第一个匹配的变体:

  • 精确名称

  • 以星号开头的最长通配符名称,例如 *.example.com

  • 以星号结尾的最长通配符名称,例如 mail.*

  • 第一个匹配的正则表达式(按配置文件中出现的顺序)

server_names_hash_bucket_size#

语法

server_names_hash_bucket_size size;

默认值

server_names_hash_bucket_size 32|64|128;

上下文

stream

设置服务器名称哈希表的桶大小。默认值取决于 处理器缓存行的大小。

server_names_hash_max_size#

语法

server_names_hash_max_size size;

默认值

server_names_hash_max_size 512;

上下文

stream

设置服务器名称哈希表的最大大小。

status_zone#

语法

status_zone zone | key zone=zone[:count];

默认值

上下文

server

分配共享内存区域以收集 /status/stream/server_zones/<zone> 的指标。

多个 server 上下文可以共享同一区域进行数据收集。

单值 zone 语法将当前上下文的所有指标聚合 在一个共享内存区域中:

server {

    listen 80;
    server_name *.example.com;

    status_zone single;
    # ...
}

替代语法允许指定以下参数:

key

包含变量的字符串, 其值决定区域中连接的分组。 所有在替换后产生相同值的连接 会被分组在一起。 如果替换产生空值,则不更新指标。

zone

共享内存区域的名称。

count (可选)

用于收集指标的单独组的最大数量。 如果新的 key 值超过此限制, 它们将被分组到 zone 下。

默认值为 1。

在以下示例中, 所有具有相同 $server_addr 值的连接 被分组到 host_zone 中。 为每个唯一的 $server_addr 单独收集指标, 直到指标组数量达到 10。 之后,任何新的 $server_addr 值 将被添加到 server_zone 组:

stream {

    upstream backend {
        server 192.168.0.1:3306;
        server 192.168.0.2:3306;
        # ...
    }

    server {

        listen 3306;
        proxy_pass backend;

        status_zone $server_addr zone=server_zone:10;
    }
}

生成的指标在 API 输出中按各个服务器拆分。

stream#

语法

stream { ... }

默认值

上下文

main

提供配置文件上下文,在其中指定流服务器指令。

tcp_nodelay#

语法

tcp_nodelay on | off;

默认值

tcp_nodelay on;

上下文

stream、server

启用或禁用 TCP_NODELAY 选项的使用。该选项对客户端连接和到代理服务器的连接都启用。

variables_hash_bucket_size#

语法

variables_hash_bucket_size size;

默认值

variables_hash_bucket_size 64;

上下文

stream

设置变量哈希表的桶大小。设置哈希表的详细信息在单独的 文档 中提供。

variables_hash_max_size#

语法

variables_hash_max_size size;

默认值

variables_hash_max_size 1024;

上下文

stream

设置变量哈希表的最大大小。设置哈希表的详细信息在单独的 文档 中提供。

内置变量#

核心 stream 模块支持以下内置变量:

$angie_version#

Angie 版本

$binary_remote_addr#

二进制形式的客户端地址,IPv4 地址的值长度始终为 4 字节,IPv6 地址为 16 字节

$bytes_received#

从客户端接收的字节数

$bytes_sent#

发送到客户端的字节数

$connection#

连接序列号

$hostname#

主机名

$msec#

当前时间(秒),精度为毫秒

$pid#

工作进程的 PID

$protocol#

用于与客户端通信的协议:TCPUDP

$proxy_protocol_addr#

来自 PROXY 协议头的客户端地址。 必须先通过在 listen 指令中设置 proxy_protocol 参数来启用 PROXY 协议。

$proxy_protocol_port#

来自 PROXY 协议头的客户端端口。 必须先通过在 listen 指令中设置 proxy_protocol 参数来启用 PROXY 协议。

$proxy_protocol_server_addr#

来自 PROXY 协议头的服务器地址。 必须先通过在 listen 指令中设置 proxy_protocol 参数来启用 PROXY 协议。

$proxy_protocol_server_port#

来自 PROXY 协议头的服务器端口。 必须先通过在 listen 指令中设置 proxy_protocol 参数来启用 PROXY 协议。

$proxy_protocol_tlv_<name>#

从 PROXY 协议头获取的 TLV。name 可以是 TLV 类型名称或其数值。在后一种情况下,该值以十六进制指定,并且必须以 0x 开头:

$proxy_protocol_tlv_alpn
$proxy_protocol_tlv_0x01

SSL TLV 也可以通过 TLV 类型名称和其数值来访问,两者都必须以 ssl_ 开头:

$proxy_protocol_tlv_ssl_version
$proxy_protocol_tlv_ssl_0x21

支持以下 TLV 类型名称:

  • alpn (0x01) - 连接上使用的上层协议

  • authority (0x02) - 客户端传递的主机名值

  • unique_id (0x05) - 唯一连接标识符

  • netns (0x30) - 命名空间名称

  • ssl (0x20) - 二进制格式的 SSL TLV 结构

支持以下 SSL TLV 类型名称:

  • ssl_version (0x21) - 客户端连接中使用的 SSL 版本

  • ssl_cn (0x22) - 证书通用名称

  • ssl_cipher (0x23) - 使用的密码套件名称

  • ssl_sig_alg (0x24) - 用于签署证书的算法

  • ssl_key_alg (0x25) - 公钥算法

还支持以下特殊 SSL TLV 类型名称:

  • ssl_verify - 客户端证书验证结果:如果客户端提供了证书并且验证成功则为 0,否则为非零值

必须先通过在 listen 指令中设置 proxy_protocol 参数来启用 PROXY 协议。

$remote_addr#

客户端地址

$remote_port#

客户端端口

$server_addr#

接受连接的服务器地址。 计算此变量的值通常需要一次系统调用。为了避免系统调用,:ref:s_listen 指令必须指定地址并使用 bind 参数。

$server_port#

接受连接的服务器端口

$session_time#

会话持续时间,以秒为单位,精确到毫秒

$status#

会话状态,可以是以下之一:

200

会话成功完成

400

无法解析客户端数据,例如 PROXY 协议头

403

禁止访问,例如当访问受 特定客户端地址 限制时

500

内部服务器错误

502

错误网关,例如无法选择或访问上游服务器

503

服务不可用,例如当访问受 连接数 限制时

$time_iso8601#

ISO 8601 标准格式的本地时间

$time_local#

通用日志格式的本地时间