NGINX `ngx_stream_core_module` 模块概览

news2025/6/8 7:15:12

一、模块定位与功能

  1. 通用 TCP/UDP 代理

    • 支持同时处理 TCP 和 UDP 流量,透明转发请求到后端服务器组(upstream)。
    • 可作为四层负载均衡,根据客户端 IP、权重、最少连接等策略将连接分发给后端。
  2. 预读(preread)机制

    • 在代理决策前预先读取部分客户端数据(如协议握手头),可用于后端选择或日志统计。
  3. 动态 DNS 解析

    • resolver 指令允许在运行时解析后端主机名,适用于后端节点 IP 可能变动的场景。
  4. 高级监听配置

    • listen 指令支持多种参数(udp/proxy_protocol/reuseport/so_keepalive 等),可细粒度控制监听 socket 特性。
  5. 内置 Hash、变量机制

    • 可通过 $remote_addr 等内置变量实现基于客户端 IP 的一致性哈希、最少连接等负载均衡方式。
    • variables_hash_bucket_sizevariables_hash_max_size 用于调优内部变量哈希表。

二、关键指令详解

1. stream { … }

位于主配置最顶层,用于开启“流”模块上下文,所有流相关配置都置于其内:

stream {
    …  
}

2. upstream <name> { … }

定义一组后端服务器,用于负载均衡:

stream {
    upstream backend {
        hash $remote_addr consistent;
        server backend1.example.com:12345 weight=5;
        server 192.168.0.2:12345      max_fails=3 fail_timeout=30s;
        server unix:/tmp/backend.sock;
    }
    … 
}
  • hash <key> [consistent]:基于 key(如 $remote_addr)做哈希,一致性模式下后端增删时扰动最小。
  • weightmax_failsfail_timeout:与 HTTP upstream 相同,用于调整权重与健康检查策略。

3. server { … }

stream 块内定义一个虚拟服务器,监听指定端口并将流量转发到某个 upstream 或单个后端:

stream {
    server {
        listen              12345;             # 监听 TCP 端口 12345
        proxy_connect_timeout 1s;               # 连接后端超时
        proxy_timeout        3s;               # 读写后端超时
        proxy_pass          backend;            # 转发到 upstream backend
    }
    server {
        listen              127.0.0.1:53 udp reuseport;  # 监听本地 UDP 53
        proxy_timeout        20s;
        proxy_pass          dns_upstream;       # 转发到 upstream dns_upstream
    }
    server {
        listen              [::1]:12345;       # IPv6 地址监听
        proxy_pass          unix:/tmp/stream.sock; # 转发到 Unix 域套接字
    }
}
  • listen <address:port> [参数...]:配置监听地址和端口,可附加 udpssl(若启用 TLS)、proxy_protocolreuseport 等。
  • proxy_pass <upstream|address>:将流量转发到指定 upstream 名称或后端地址(支持 Unix Socket)。
  • proxy_connect_timeout:与后端建立连接的最长期限。
  • proxy_timeout:包括连接、读、写操作的总体超时,若在此期间无数据交换则断开。
常用 listen 参数
  • udp:将该监听 socket 切换为 UDP 模式(默认 TCP)。
  • proxy_protocol:启用 PROXY 协议解码,用于获取客户端真实 IP(需后端或网络层支持 PROXY 协议)。
  • reuseport:为每个工作进程分别创建监听 socket,实现内核级负载均衡。
  • so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]:细粒度控制 TCP Keepalive 行为。
  • fastopen=number:启用 TCP Fast Open,需谨慎使用(允许跨握手发送少量数据)。
  • bind:强制对每个监听地址单独执行 bind(),以便与高级参数兼容。

4. preread_buffer_size <size>

默认16k
上下文stream, server

在真正将客户端流量代理给后端之前,预先在 NGINX 层读取的数据量,用于协议判断、日志或统计。

server {
    listen               54321;
    preread_buffer_size  32k;     # 预读 32KB
    proxy_pass           backend;
}

若需要从预读数据中提取特征(如协议头部),可相应调大此缓冲。

5. preread_timeout <time>

默认30s
上下文stream, server

预读阶段超时时间,若在此期间客户端无数据发送,则关闭连接。

server {
    listen               54321;
    preread_timeout      5s;      # 5 秒未接收数据则关闭
    proxy_pass           backend;
}

6. proxy_protocol_timeout <time>

默认30s
上下文stream, server

当在 listen … proxy_protocol 模式下启用 PROXY 协议,此指令规定在读取完整 PROXY 协议头前的最大等待时间:

server {
    listen                   12345 proxy_protocol;
    proxy_protocol_timeout   2s;    # 2 秒读完 PROXY 协议头
    proxy_pass               backend;
}

如果客户端连接后未在 proxy_protocol_timeout 指定时间内发送完整的 PROXY 头,则会被关闭。

7. resolver <address> […] [valid=time] [ipv4=on|off] [ipv6=on|off] [status_zone=zone]

默认:无
上下文stream, server

为后端 upstream 名称解析提供 DNS 服务器列表:

stream {
    resolver 127.0.0.1 [::1]:5353 valid=30s;
    resolver_timeout 5s;

    upstream dynamic_backend {
        server  backend1.example.com:12345 resolve;
        server  backend2.example.com:12345 resolve;
    }

    server {
        listen      12345;
        proxy_pass  dynamic_backend;
    }
}
  • valid=30s:覆盖 DNS TTL,强制每隔 30 秒刷新缓存。
  • ipv4=off / ipv6=off:控制是否解析 IPv4/IPv6。
  • resolver_timeout:DNS 查询超时时间。

8. tcp_nodelay on|off

默认on
上下文stream, server

开启或关闭 TCP_NODELAY, 用于禁用 Nagle 算法,减少小包延迟:

stream {
    tcp_nodelay on;

    server {
        listen      10000;
        proxy_pass  backend;
    }
}

多数场景下推荐开启(on),尤其对低延迟要求较高的协议(如 Redis、Memcached 等)。

9. 哈希表调优:variables_hash_bucket_size / variables_hash_max_size

默认64 / 1024
上下文stream

  • 用途:当你在 Stream 配置中使用自定义变量或正则表达式时,会在内部构建哈希表。通过这两项指令可手动调整哈希桶大小及最大容量,避免“桶冲突”或占用过多内存。
stream {
    variables_hash_bucket_size  128;
    variables_hash_max_size    2048;

    server {
        listen       11000;
        set $client_ip $remote_addr;             # 使用自定义变量
        proxy_pass   "$client_ip:20000";
    }
}

10. server_nameserver_names_hash_bucket_sizeserver_names_hash_max_size

上下文stream, server(自 1.25.5 起支持 Server Name Matching)

  • 仅在需要基于 TLS SNI(Server Name Indication)或IP+端口 匹配多个虚拟服务器时使用。
  • server_name 声明可匹配的主机名(支持通配符、正则);
  • 对应的哈希表调优参数与上文类似,用于存储大量 server_name 时的性能优化。
stream {
    variables_hash_bucket_size   64;
    variables_hash_max_size     1024;

    server {
        listen          443 ssl;
        server_name     example.com www.example.org;

        ssl_certificate     /etc/nginx/ssl/stream.pem;
        ssl_certificate_key /etc/nginx/ssl/stream.key;

        proxy_pass       backend;
    }
}

三、常用内置变量

stream 配置与日志中,可使用以下常见变量:

  • 客户端信息

    • $remote_addr:客户端 IP;
    • $remote_port:客户端端口;
    • $binary_remote_addr:二进制形式的客户端 IP,适合做哈希。
  • 代理协议(需 proxy_protocol

    • $proxy_protocol_addr / $proxy_protocol_port:来自 PROXY 头中的真实 IP/端口;
    • $proxy_protocol_server_addr / $proxy_protocol_server_port:服务器地址/端口(1.17.6+);
    • $proxy_protocol_tlv_*:支持访问 PROXY Protocol v2 TLV(如 $proxy_protocol_tlv_ssl_version)。
  • 会话统计

    • $bytes_received / $bytes_sent:当前会话已接收/发送字节数(1.11.4+);
    • $session_time:会话时长(秒.msec)(1.11.4+);
    • $status:当前会话状态码(200、400、403、500、502、503)(1.11.4+);
  • 服务器信息

    • $server_addr / $server_port:接收连接的本地地址及端口;
    • $hostname:Nginx 主机名;
    • $pid:工作进程 PID;
  • 时间

    • $msec:当前时间(秒.毫秒);
    • $time_local:本地时间(Common Log 格式);
    • $time_iso8601:本地时间(ISO 8601 格式);
  • 其他

    • $nginx_version:Nginx 编译版本;
    • $connection:会话编号(对当前 worker 进程)。

示例日志格式:

stream {
    log_format stream_log '$remote_addr:$remote_port '
                          '$proxy_protocol_addr:$proxy_protocol_port - '
                          'bytes_in=$bytes_received bytes_out=$bytes_sent '
                          'status=$status '
                          'time=$msec';
    access_log /var/log/nginx/stream_access.log stream_log;

    server {
        listen       3306;            # MySQL Proxy
        proxy_pass   mysql_upstream;
    }
}

四、完整示例

以下示例演示如何基于 ngx_stream_core_module 搭建一个通用的 TCP 流代理环境,支持多个后端集群、动态 DNS、PROXY 协议以及日志统计。

worker_processes auto;

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

events {
    worker_connections 2048;
}

stream {
    ###############################
    ## 全局调优(哈希、缓冲)   ##
    ###############################
    preread_buffer_size       16k;
    preread_timeout           10s;
    proxy_protocol_timeout    5s;
    tcp_nodelay               on;

    variables_hash_bucket_size   64;
    variables_hash_max_size     2048;

    ###############################
    ## DNS 动态解析与超时       ##
    ###############################
    resolver             127.0.0.1 [::1]:5353 valid=30s ipv6=on ipv4=on;
    resolver_timeout     3s;

    ###############################
    ## 定义后端 upstream 集群   ##
    ###############################
    upstream mysql_backend {
        hash               $binary_remote_addr consistent;  
        server             db1.example.com:3306 weight=5;
        server             db2.example.com:3306 weight=5;
        server             192.168.1.100:3306  max_fails=2 fail_timeout=20s;
    }

    upstream redis_backend {
        server             10.0.0.10:6379;
        server             redis2.example.com:6379 resolve;  # 动态 DNS
    }

    upstream dns_servers {
        server             192.168.0.53:53;
        server             dns2.example.com:53 resolve;
    }

    ###############################
    ## MySQL TCP 代理 (3306)     ##
    ###############################
    server {
        listen         3306;
        proxy_connect_timeout   1s;
        proxy_timeout           5s;
        proxy_pass      mysql_backend;

        # 记录访问日志
        access_log /var/log/nginx/stream_mysql.log 
            '$remote_addr:$remote_port '
            'bytes_in=$bytes_received bytes_out=$bytes_sent '
            'time=$msec status=$status';
    }

    ###############################
    ## Redis TCP 代理 (6379)     ##
    ###############################
    server {
        listen         6379;
        proxy_connect_timeout   0.5s;
        proxy_timeout           2s;
        proxy_pass      redis_backend;

        access_log /var/log/nginx/stream_redis.log 
            '$remote_addr:$remote_port -> $upstream_addr '
            'rx=$bytes_received tx=$bytes_sent time=$msec';
    }

    ###############################
    ## DNS UDP 代理 (53)         ##
    ###############################
    server {
        listen         53 udp reuseport;
        proxy_pass     dns_servers;
        proxy_timeout  10s;

        access_log /var/log/nginx/stream_dns.log 
            '$remote_addr:$remote_port '
            'dns_request rx=$bytes_received tx=$bytes_sent '
            'time=$msec';
    }

    ###############################
    ## Unix Domain Socket 代理示例 ## 
    ###############################
    server {
        listen         unix:/var/run/stream.sock;
        proxy_pass     unix:/var/run/backend.sock;
    }
}

要点解析:

  • 多协议示例:TCP(MySQL、Redis)和 UDP(DNS)共存,示范了 listen … udp reuseport; 与常规 TCP 监听的区别。
  • 动态 DNS:后端 redis_backenddns_servers 使用 resolve,结合全局 resolver 定期刷新。
  • 健康检查参数max_fails=2 fail_timeout=20s,后端 db1 连续失败 2 次且在 20 秒内失败则被标记为不可用。
  • 日志记录:示例自定义了访问日志格式,记录客户端 IP/端口、上下行字节数、会话时长与状态码。
  • UDP 重用端口reuseport 让内核将 53 端口请求分发给多个 worker 进程,提高并发 DNS 性能。
  • Unix 域套接字:可将流量从一个 Unix Socket 转发到另一个,适用于本机进程间高性能通信。

五、总结

ngx_stream_core_module 是 NGINX 在第四层(L4)协议上的通用解决方案,能够:

  • 支持任意 TCP/UDP 转发与负载均衡;
  • 提供预读、超时、PROXY 协议、安全套接字等高级功能;
  • 允许动态 DNS 解析、哈希负载均衡、TCP 优化(TCP_NODELAY、Keepalive);
  • 与内置变量结合,轻松实现日志统计与会话追踪。

通过合理配置上述指令,你可以根据不同业务场景(MySQL、Redis、DNS、SMTP 等)构建高可用、高并发且安全可靠的四层代理架构。希望本文的指令详解与示例配置,能让你快速掌握 ngx_stream_core_module 并在生产环境中灵活运用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2403863.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

iOS、Android、鸿蒙、Web、桌面 多端开发框架Kotlin Multiplatform

Kotlin Multiplatform&#xff08;简称 KMP&#xff09;是 JetBrains 推出的开源跨平台开发框架 Kuikly 是腾讯开源的跨端开发框架&#xff0c;基于 Kotlin Multiplatform 技术构建&#xff0c;为开发者提供了技术栈更统一的跨端开发体验 KMP 不仅局限于移动端&#xff0c;它…

探索C++标准模板库(STL):String接口的底层实现(下篇)

前引&#xff1a;在C的面向对象编程中&#xff0c;对象模型是理解语言行为的核心。无论是类的成员函数如何访问数据&#xff0c;还是资源管理如何自动化&#xff0c;其底层机制均围绕两个关键概念展开&#xff1a;this指针与六大默认成员函数。它们如同对象的“隐形守护者”&am…

Flutter知识点汇总

Flutter架构解析 1. Flutter 是什么?它与其他移动开发框架有什么不同? Flutter 是 Google 开发的开源移动应用开发框架,可用于快速构建高性能、高保真的移动应用(iOS 和 Android),也支持 Web、桌面和嵌入式设备。。它与其他移动开发框架(如 React Native、Xamarin、原…

​线性注意力 vs. 传统注意力:效率与表达的博弈新解

​核心结论​&#xff1a;线性注意力用计算复杂度降维换取全局建模能力&#xff0c;通过核函数和结构优化补足表达缺陷 一、本质差异&#xff1a;两种注意力如何工作&#xff1f; ​特性​传统注意力&#xff08;Softmax Attention&#xff09;线性注意力&#xff08;Linear At…

YOLO在QT中的完整训练、验证与部署方案

以下是YOLO在QT中的完整训练、验证与部署方案&#xff1a; 训练方案 准备数据集&#xff1a; 收集数据&#xff1a;收集与目标检测任务相关的图像数据集&#xff0c;可以是公开数据集如COCO、Pascal VOC&#xff0c;也可以是自定义数据集。标注数据&#xff1a;使用标注工具如…

增量式网络爬虫通用模板

之前做过一个项目&#xff0c;他要求是只爬取新产生的或者已经更新的页面&#xff0c;避免重复爬取未变化的页面&#xff0c;从而节省资源和时间。这里我需要设计一个增量式网络爬虫的通用模板。可以继承该类并重写部分方法以实现特定的解析和数据处理逻辑。这样可以更好的节约…

【JVM】三色标记法原理

在JVM中&#xff0c;三色标记法是GC过程中对象状态的判断依据&#xff0c;回收前给对象设置上不同的三种颜色&#xff0c;三色分为白色、灰色、黑色。根据颜色的不同&#xff0c;决定对象是否要被回收。 白色表示&#xff1a; 初始状态&#xff1a;所有对象未被 GC 访问。含义…

【uniapp开发】picker组件的使用

项目uniapp&#xff0c;结合fastadmin后端开发 picker组件的官方文档说明 https://en.uniapp.dcloud.io/component/picker.html#普通选择器 先看效果&#xff1a; 1、实现设备类型的筛选&#xff1b;2、实现设备状态的筛选&#xff1b; 前端代码&#xff08;节选&#xff0…

【HarmonyOS Next之旅】DevEco Studio使用指南(三十一) -> 同步云端代码至DevEco Studio工程

目录 1 -> 同步云函数/云对象 1.1 -> 同步单个云函数/云对象 1.2 -> 批量同步云函数/云对象 2 -> 同步云数据库 2.1 -> 同步单个对象类型 2.2 -> 批量同步对象类型 3 -> 一键同步云侧代码 1 -> 同步云函数/云对象 说明 对于使用DevEco Studio…

go-zero微服务入门案例

一、go-zero微服务环境安装 1、go-zero脚手架的安装 go install github.com/zeromicro/go-zero/tools/goctllatest2、etcd的安装下载地址根据自己电脑操作系统下载对应的版本&#xff0c;具体的使用自己查阅文章 二、创建一个user-rpc服务 1、定义user.proto文件 syntax &qu…

Python控制台输出彩色字体指南

在Python开发中&#xff0c;有时我们需要在控制台输出彩色文本以提高可读性或创建更友好的用户界面。本文将介绍如何使用colorama库来实现这一功能。 为什么需要彩色输出&#xff1f; 提高可读性&#xff1a;重要信息可以用不同颜色突出显示更好的用户体验&#xff1a;错误信息…

开源之夏·西安电子科技大学站精彩回顾:OpenTiny开源技术下沉校园,点燃高校开发者技术热情

开源之夏2025编程活动正在如火如荼的进行中&#xff0c;当前也迎来了报名的倒计时阶段&#xff0c;开源之夏组织方也通过高校行系列活动进入各大高校&#xff0c;帮助高校开发者科普开源文化、开源活动、开源技术。 6月4日 开源之夏携手多位开源技术大咖、经验型选手走进西安电…

解决数据库重启问题

最近部署软件时&#xff0c;发现mysql会一直在重启&#xff0c;记录下解决办法&#xff1a; 1.删除/home/dataexa/install/docker/datas/mysql路径下的data文件夹 2.重新构建mysql docker-compose up -d --build mysql 3.停掉所有应用&#xff0c;在全部重启&#xff1a; do…

前后端交互过程中—各类文件/图片的上传、下载、显示转换

前后端交互过程中—各类文件/图片的上传、下载、显示转换 图片补充&#xff1a;new Blob()URL.createObjectURL()替代方案&#xff1a;FileReader.readAsDataURL()​​对比&#xff1a; tiff文件TIFF库TIFF转换通过url转换tiff文件为png通过文件选择的方式转换tiff文件为png 下…

数据库同步是什么意思?数据库架构有哪些?

目录 一、数据库同步是什么 &#xff08;一&#xff09;基本概念 &#xff08;二&#xff09;数据库同步的类型 &#xff08;三&#xff09;数据库同步的实现方式 二、数据库架构的类型 &#xff08;一&#xff09;单机架构 &#xff08;二&#xff09;主从复制架构 &a…

【数据结构】详解算法复杂度:时间复杂度和空间复杂度

&#x1f525;个人主页&#xff1a;艾莉丝努力练剑 ❄专栏传送门&#xff1a;《C语言》、《数据结构与算法》 &#x1f349;学习方向&#xff1a;C/C方向 ⭐️人生格言&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为往圣继绝学&#xff0c;为万世开太平 前言&…

Rest-Assured API 测试:基于 Java 和 TestNG 的接口自动化测试

1. 右键点击项目的文件夹&#xff0c;选择 New > File。 2. 输入文件名&#xff0c;例如 notes.md&#xff0c;然后点击 OK。 3. 选择项目类型 在左侧的 Generators 部分&#xff0c;选择 Maven Archetype&#xff0c;这将为你生成一个基于 Maven 的项目。 4. 配置项目基…

react public/index.html文件使用env里面的变量

env文件 ENVdevelopment NODE_ENVdevelopment REACT_APP_URL#{REACT_APP_URL}# REACT_APP_CLIENTID#{REACT_APP_CLIENTID}# REACT_APP_TENANTID#{REACT_APP_TENANTID}# REACT_APP_REDIRECTURL#{REACT_APP_REDIRECTURL}# REACT_APP_DOMAIN_SCRIPT#{REACT_APP_DOMAIN_SCRIPT}#pu…

chili3d 笔记17 c++ 编译hlr 带隐藏线工程图

这个要注册不然emscripten编译不起来 --------------- 行不通 ---------------- 结构体 using LineSegment std::pair<gp_Pnt, gp_Pnt>;using LineSegmentList std::vector<LineSegment>; EMSCRIPTEN_BINDINGS(Shape_Projection) {value_object<LineSegment&g…

创建一个纯直线组成的字体库

纯直线组成的字体&#xff0c;一个“却”由五组坐标点组成&#xff0c;存储5个点共占21字节&#xff0c;使用简单&#xff0c;只要画直线即可&#xff0c; “微软雅黑”&#xff0c;2个轮廓&#xff0c;55坐标点&#xff0c;使用复杂&#xff0c;还填充。 自创直线字体 “微软…