You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nginx向Socket写入最大16413字节及EAGAIN报错原因排查

Nginx写入文件描述符时频繁触发EAGAIN错误的原因分析

问题背景

Nginx向文件描述符(FD)写入数据时,单次最大写入字节数固定为16413,且写入后频繁出现-1 EAGAIN (Resource temporarily unavailable)错误。尝试调整系统参数net.ipv4.tcp_wmem = 4096 65536 4194304后,问题仍未解决。

相关Strace日志

epoll_wait(29, [{EPOLLOUT, {u32=526027040, u64=139844661184800}}], 512, 8) = 1
write(37, "3Q\233\201:z(\301\355\306\330\25f\342I`\321\236~\370\243\371\356-0h\250\330t\231Pm"..., 1328) = 1328
write(37, "\27\3\3@\30\302\v\240\3032\273\251\273\267F'+i\271\226\361-\264\347\202\337\375WeBE\250"..., 16413) = 16413
write(37, "\27\3\3@\30\302\v\240\3032\273\251\274\7\23\274\200\253H?%\3276\305\224\204\20T\f\202\25\253"..., 16413) = 16413
write(37, "\27\3\3@\30\302\v\240\3032\273\251\275v\260\241\223\250\303\353N*\202\310#\204\251\245\1\245}\324"..., 16413) = 16413
write(37, "\27\3\3@\30\302\v\240\3032\273\251\276\241\312\310\276\344\265]<\330\"\2016$\37\215\36\345x\3"..., 16413) = 16413
write(37, "\27\3\3@\30\302\v\240\3032\273\251\277\302<e\21\241\213A-\345\265\246\271v,w5c\225\200"..., 16413) = 16413
write(37, "\27\3\3@\30\302\v\240\3032\273\251\300\353O\204\36,\377\260\7\21\341\3L\307\345t\6\6\274\377"..., 16413) = 2739
write(37, "\206\241\34\342F\345\272\216\336\2@\27cE\204 )\211\261\3744\365\305Z\367O\276\nA\35(K"..., 13674) = -1 EAGAIN (Resource temporarily unavailable)
write(65, "\25\3\3\0\32\234\206\273\n(\224\346G\7\317\363<#\357~\242d\213\16\345\231\371\340vY\253", 31) = 31
close(65)                               = 0
epoll_wait(29, [{EPOLLOUT, {u32=526029921, u64=139844661187681}}], 512, 352) = 1
write(119, "s\243\6h\243\303-\317\344\0F\332\237<C\17\370\252\257\242\263\364\34\232=\302Y\177\4\177\241C"..., 5186) = 5186
write(119, "\27\3\3@\30\214\rA9=\216x\270\242Q\374\223\3\334\375@\357\276m\252\253o\372\rv7\6"..., 16413) = 16413
write(119, "\27\3\3@\30\214\rA9=\216x\271\365G\320\350[ \313\231\223\302\262O\302\202\246^:R_"..., 16413) = 16413
write(119, "\27\3\3@\30\214\rA9=\216x\272\311\274B'\372\262\24\277Ti5\245\7(q3ms\7"..., 16413) = 16413
write(119, "\27\3\3@\30\214\rA9=\216x\273s\363c5\16D\204(+\210,\2335zKN)\10\362"..., 16413) = 16413
write(119, "\27\3\3@\30\214\rA9=\216x\274\350\220&\330,Z\220_.\241\345\212\224\7\344\266\30\341\334"..., 16413) = 16413
write(119, "\27\3\3@\30\214\rA9=\216x\275\351\3642\374\355\30c\317C\356Aa\324\vj.\\\203\340"..., 16413) = 16413
write(119, "\27\3\3@\30\214\rA9=\216x\276.\313i\326*\303\271B\254\30159:\215\235#\265\16\274"..., 16413) = 16413
write(119, "\27\3\3@\30\214\rA9=\216x\277[\275\266\316$P\275\227\334\312\\\236\362\362R\242\261Q\227"..., 16413) = 8403
write(119, "i(\242\200\233\204\322\366J\342\3772\325U\261\23\26\215_\362\356q\221\214=?\314\235\345\263\30\374"..., 8010) = -1 EAGAIN (Resource temporarily unavailable)
epoll_wait(29, [{EPOLLOUT, {u32=526006400, u64=139844661164160}}], 512, 348) = 1
write(39, "\244\v\27\363\341\271\6\273\rt\"\236\200\305Z\v\261@8'\271\336#\373\n\247v\16~aY\267"..., 3180) = 3180
write(39, "\27\3\3@\30D\34\216\23\372\177\254\240\337\242\332\355\372\210.\260\f\22](\\\33PK'I\341"..., 16413) = 16413
write(39, "\27\3\3@\30D\34\216\23\372\177\254\241\224\r5 \340`\223\305T\n\211*\203q\352\200\341\270l"..., 16413) = 16413
write(39, "\27\3\3@\30D\34\216\23\372\177\254\242\234\273\242\23\373\2162\244\257M\0064\341\0160\37\262\242*"..., 16413) = 16413
write(39, "\27\3\3@\30D\34\216\23\372\177\254\243\32\357 8\253M\306#?ub`\201\241t\25\277+\n"..., 16413) = 16413
write(39, "\27\3\3@\30D\34\216\23\372\177\254\244\244h\267\313\32t\251\fw2\342\336I\375P\2121\263\201"..., 16413) = 16413
write(39, "\27\3\3@\30D\34\216\23\372\177\254\245_\271\342\23\350\362V'\324\362\351g\322\360\255R=\34\321"..., 16413) = 16413
write(39, "\27\3\3@\30D\34\216\23\372\177\254\246b\367\22\3004^.\351\3616\351&\352\266\333\5:\317I"..., 16413) = 16413
write(39, "\27\3\3@\30D\34\216\23\372\177\254\247\365#\365z\2154MQ\271\275w\3002c\204\335\24a3"..., 16413) = 9705
write(39, "\321\204\316\226k\210\340,_'q>\\\365K\210\2202:f\301\223,\267D\324\263A\326\16\2b"..., 6708) = -1 EAGAIN (Resource temporarily unavailable)

核心原因拆解

  1. EAGAIN本质:发送缓冲区耗尽
    EAGAIN错误表示内核的TCP发送缓冲区已满,无法再写入新数据。这并非Nginx本身的问题,而是下游客户端或服务的TCP接收窗口已被占满,未能及时返回ACK确认数据,导致本地发送缓冲区无法释放空间。

  2. 16413字节的来源
    这个数值是TLS记录的最大分片尺寸:TLS记录层默认最大 payload 为16384字节,加上29字节的TLS协议头,总长度正好是16413字节。Nginx发送加密数据时,会自动按这个尺寸分片,所以每次写入固定为16413字节。

  3. tcp_wmem调整无效的原因
    tcp_wmem仅控制TCP发送缓冲区的最小、默认、最大容量,但如果下游一直无法消费数据,即使调大缓冲区,最终还是会被填满,无法解决根本的流量阻塞问题。

解决方案建议

  • 排查下游消费能力:检查客户端是否存在处理缓慢、网络延迟过高的情况,或下游服务是否出现阻塞(如数据库慢查询、进程卡死),导致无法及时接收并ACK数据。
  • 调整Nginx发送缓冲区:在Nginx配置中添加send_buffer_size 64k;,同时调整系统参数net.core.wmem_max为更大值(如echo 262144 > /proc/sys/net/core/wmem_max),确保内核允许Nginx使用更大的发送缓冲区。
  • 启用TCP_NODELAY:在Nginx location或server块中添加tcp_nodelay on;,关闭Nagle算法,减少小数据包的延迟发送,提升数据传输的实时性(需权衡是否增加网络开销)。
  • 监控TCP连接状态:使用ss -ti命令查看目标连接的cwnd(拥塞窗口)和rwnd(接收窗口),确认是否是接收端窗口持续为0导致的阻塞。

内容的提问来源于stack exchange,提问作者Vladislav Eganov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 15:14:50