当前位置:首页 > 随笔 > 正文内容

Nginx与Linux内核性能调优实战

访客 随笔 2026年11月1日 1

在一次部署中,我们使用了两个Nginx实例,一个运行在CentOS 7.6,另一个运行在Windows Server 2008 R2,用于进行流量转发。流量拓扑如下:

随着业务量的急剧增长,转发服务开始出现大量的502错误,同时Nginx也报告了大量的error: 10054 An existing connection was forcibly closed by the remote host错误。在阿里云监控中,我们也观察到流量和TCP连接数陡增,并且出现了大量的TIME_WAIT状态的连接。经过深入排查,我们采取了一系列优化措施。

一、Nginx配置优化

首先,我们针对Nginx报错的10054错误,查找相关的解决方案。当Nginx作为反向代理时,为了支持长连接,需要确保客户端到Nginx以及Nginx到后端服务器的连接都尽可能保持长连接。

1. 保持客户端到Nginx的长连接

通过调整Nginx的keepalive_timeout和keepalive_requests参数来优化:

http {
        keepalive_timeout 120s;
        keepalive_requests 1000;
    }
  • keepalive_timeout: 指定客户端连接在服务器端保持开启的超时时间(默认75秒)。设置为0则禁用keep-alive客户端连接。该参数主要控制浏览器和Nginx之间TCP通道的空闲等待时间。
  • keepalive_requests: 指定一个keep-alive连接上可服务的最大请求数。达到此数量后,连接会被关闭,迫使客户端重新建立连接。默认值为100。

2. 保持Nginx到后端服务器的长连接

默认情况下,Nginx与后端服务器之间使用HTTP/1.0的短连接。为了启用长连接,需要进行如下配置:

location / {
        proxy_http_version 1.1;
        proxy_set_header Connection "keep-alive";
        proxy_pass http://your_backend_server;
    }
  • proxy_http_version 1.1: 启用HTTP/1.1协议,这是支持长连接的基础。
  • proxy_set_header Connection "keep-alive": 显式地向后端服务器发送Keep-Alive头部。

3. Nginx的keepalive指令

keepalive指令用于设置到上游服务器的空闲keep-alive连接的最大数量。当超过此数量时,最近最少使用的连接会被关闭。该指令不限制一个worker进程与上游服务器建立连接的总数。

注意:keepalive参数的设置需要谨慎,尤其在高QPS场景下。可以根据QPS和平均响应时间估算所需的连接数,然后将keepalive设置为该数量的10%-30%。

4. TIME_WAIT状态的产生原因与Nginx配置关系

  • Nginx端出现大量TIME_WAIT:
    • keepalive_requests设置过小,导致高并发下Nginx主动关闭与客户端的连接。
    • keepalive设置过小,导致Nginx在高并发下频繁关闭与后端服务器的连接。
  • 后端服务器端出现大量TIME_WAIT:
    • Nginx未启用与后端的长连接(未设置proxy_http_version 1.1和proxy_set_header Connection "keep-alive"),导致后端每次关闭连接。

二、操作系统层面调优

1. Windows系统TIME_WAIT连接优化

问题:Windows Server默认动态端口范围较小(16384个),且TCP默认TIME_WAIT时长较长(4分钟),在高并发连接下容易导致端口耗尽。

解决方案:

  1. 查看当前动态端口配置:netsh interface ipv4 show dynamicport tcp
  2. 增大动态端口范围:netsh int ipv4 set dynamicport tcp start=15000 num=50000 (无需重启)
  3. (可选)降低TIME_WAIT时间:修改注册表HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters,新增TcpTimedWaitDelay(REG_DWORD),设置为30(秒)。

2. Linux系统TIME_WAIT连接优化

TCP连接状态详解:

  • 三次握手 (建立连接): SYN -> SYN/ACK -> ACK
  • 四次挥手 (终止连接): FIN -> ACK -> FIN -> ACK (TCP连接是全双工的,每个方向的关闭都需要单独进行)
  • 常见状态:
    • LISTEN: 服务器等待连接。
    • SYN_RCVD: 服务器收到SYN,等待ACK。
    • SYN_SENT: 客户端发送SYN,等待SYN/ACK。
    • ESTABLISHED: 连接已建立。
    • FIN_WAIT_1: 主动关闭方发送FIN,等待对方ACK。
    • FIN_WAIT_2: 主动关闭方收到ACK,等待对方FIN。
    • TIME_WAIT: 收到对方FIN,发送ACK,等待2MSL后返回CLOSED。这是为了确保对方收到了最后的ACK,并允许重发丢失的ACK。MSL是TCP报文在网络上存在的最长时间(通常为30秒-2分钟)。
    • CLOSE_WAIT: 被动关闭方收到FIN,发送ACK,等待应用程序关闭连接。
    • LAST_ACK: 被动关闭方发送FIN,等待对方最后的ACK。

检查当前连接状态:

netstat -ano|awk -F " " '{print $6}'|sort |uniq -c |sort -r -n

通过调整内核参数解决大量TIME_WAIT问题:

编辑/etc/sysctl.conf文件,添加或修改以下参数:

# 开启SYN Cookies,防止SYN Flood攻击
    net.ipv4.tcp_syncookies = 1
    # 允许TIME-WAIT sockets重用
    net.ipv4.tcp_tw_reuse = 1
    # 开启TIME-WAIT sockets的快速回收(谨慎使用,可能导致问题)
    # net.ipv4.tcp_tw_recycle = 1
    # TIME-WAIT状态的连接保持时间(秒)
    net.ipv4.tcp_fin_timeout = 30
    # IP本地端口范围,用于向外连接
    net.ipv4.ip_local_port_range = 1024 65535
    # SYN队列长度
    net.ipv4.tcp_max_syn_backlog = 8192
    # 系统同时保持TIME_WAIT套接字的最大数量
    net.ipv4.tcp_max_tw_buckets = 5000

运行sysctl -p使配置生效。

三、阿里云 Linux 内核优化实战

对于阿里云ECS实例,可以进一步优化内核参数。

1. sysctl.conf 优化

编辑/etc/sysctl.conf或在/etc/sysctl.d/目录下创建新文件,并添加以下参数:

# 最大打开文件数
    fs.file-max = 2097152

    # 减少内存交换使用
    vm.swappiness = 30

    # 允许分配所有物理内存
    vm.overcommit_memory = 1
    # 最大内存映射区域数
    vm.max_map_count = 262144

    # 开启SYN Cookies
    net.ipv4.tcp_syncookies = 1

    # TIME_WAIT socket的最大数目
    net.ipv4.tcp_max_tw_buckets = 50000
    # 激活TCP窗口扩充
    net.ipv4.tcp_window_scaling = 1

    # TCP缓冲区内存设置
    net.ipv4.tcp_mem = 786432 2097152 3145728
    net.ipv4.tcp_rmem = 4096 4096 16777216
    net.ipv4.tcp_wmem = 4096 4096 16777216

    # Socket缓冲区默认值和最大值
    net.core.wmem_default = 8388608
    net.core.rmem_default = 8388608
    net.core.rmem_max = 16777216
    net.core.wmem_max = 16777216

    # ACCEPT等待队列长度
    net.core.netdev_max_backlog = 65535
    # 系统最大并发连接数
    net.core.somaxconn = 65535

    # 不属于任何进程的socket最大数量
    net.ipv4.tcp_max_orphans = 65535
    # SYN等待队列长度
    net.ipv4.tcp_max_syn_backlog = 65535

    # 禁用TCP timestamps (在高并发下重要)
    net.ipv4.tcp_timestamps = 0

    # SYN/SYN-ACK重试次数
    net.ipv4.tcp_synack_retries = 1
    net.ipv4.tcp_syn_retries = 1

    # 允许回收TCP连接
    net.ipv4.tcp_tw_recycle = 1
    # 允许重用TCP连接
    net.ipv4.tcp_tw_reuse = 1

    # 服务端主动关闭后,客户端释放连接的超时时间
    net.ipv4.tcp_fin_timeout = 5
    # TCP保持空闲keepalive时长
    net.ipv4.tcp_keepalive_time = 30

    # 系统作为TCP客户端连接自动使用的端口范围
    net.ipv4.ip_local_port_range = 10240 65535

运行sysctl -p加载配置。

查询参数:sysctl -a | grep <参数名>

2. ulimits 优化

限制系统打开文件的最大数量(文件描述符)。

编辑/etc/security/limits.conf文件,添加或修改以下行:

root hard nofile 65535
    * soft nofile 65535
    * hard nofile 65535
    * soft nproc 65535
    * hard nproc 65535

断开SSH连接并重新登录,或重启服务使配置生效。使用ulimit -a检查。

相关文章

可以按小时收费的VPS

很多 VPS 提供商都支持 按小时计费(hourly billing),想短期试用 / 临时搭建节点、测试网络、短期项目等场景非常合适。下面是当前最主流且靠谱的按小时 VPS 选项,分别按不同需求场景整理: 1. Vultr(全球节点,包括日本) 按小时计费 可选机房:东京 / 大阪 / 洛杉矶 / 法兰克福 / 伦敦 … 支持 PayPal(部分情况),但更常用信用卡/PayPal+卡价格参考$...

在 iPhone 上下载国外App

地区/国家限制App Store 会根据 Apple ID 的国家或地区限制应用下载。如果你的 Apple ID 绑定的是中国大陆,就可能无法下载 OpenAI 官方的 ChatGPT 应用,因为它在大陆 App Store 不上架。解决办法:换成美国、加拿大、香港等地区的 Apple ID。或者在现有 Apple ID 上更改地区。注册一个国外 Apple ID(推荐)比如注册 美国区 Appl...

Node.js 中的异步编程:回调与 Promise

Node.js 是一个基于 JavaScript 构建的单线程、非阻塞运行环境,它通过异步编程机制来高效处理多个操作。在执行如文件读取、API 请求或数据库查询等任务时,Node.js 不会等待这些操作完成,而是使用回调函数和 Promise 来避免阻塞主线程。 回调方式实现异步 那么当异步操作完成后,Node.js 如何知道接下来要做什么呢?这就要用到 回调函数(callback)。 回调本质上...

Selenium自动化测试入门指南

Selenium自动化测试入门指南

什么是自动化测试? 自动化测试是指利用软件工具自动执行测试用例,模拟用户操作,如打开网页、点击链接、输入文本等,并验证结果是否符合预期。 其主要优点包括: 大幅减少人工成本 测试速度快 可以在非工作时间运行 支持持续集成和交付 然而,它也存在一些局限性,例如开发成本较高、不适合快速变化的项目、依赖稳定的UI界面等。 自动化测试的应用条件 适合引入自动化测试的情况包括: 手动测试耗时且需要大量...

MariaDB Galera集群故障快速恢复指南

OpenStack控制节点采用三节点MariaDB Galera集群架构。当数据库集群因故障重启时,有时会出现Galera集群无法正常启动的问题。虽然有多种方法可以恢复数据库服务,但如何实现快速启动同时确保数据完整性呢? 通过分析日志发现,MariaDB Galera集群节点宕机时会在日志中输出以下信息: [Note] WSREP: 新集群视图:全局状态: 874d8e7e-5980-11e8-8...

Android 中 EventBus 的通信机制与实现原理深度解析

EventBus 核心设计思想 EventBus 是一个基于观察者模式的事件总线框架,广泛应用于 Android 平台以实现组件解耦。它通过中心化的消息分发机制,使不同层级、不同线程的对象能够以"发布-订阅"方式通信,避免了传统接口回调或广播带来的强依赖问题。 核心角色说明 事件(Event):任意 Java 对象,作为数据载体,如网络状态变更通知、用户登录信息等。 发布者(Publi...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。