[原创]nginx写日志时机与tcp write写成功是否送达对端疑问解析

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
日志服务 SLS,月写入数据量 50GB 1个月
简介: 前些天和另外部门的同事在排查一个网络问题, 问到nginx日志中成功记录了http 200响应码能否证明响应数据就达到了对端? 这个问题涉及nginx在做server功能时写日志是在什么时机? 是client端收到响应数据后才生成, 还是nginx丢出数据就生成了而不管是否client端收到数据?

原创文章:来自nginx写日志时机与tcp write写成功是否送达对端疑问解析

前些天和另外部门的同事在排查一个网络问题, 问到nginx日志中成功记录了http 200响应码能否证明响应数据就达到了对端? 这个问题涉及nginx在做server功能时写日志是在什么时机? 是client端收到响应数据后才生成, 还是nginx丢出数据就生成了而不管是否client端收到数据?

做上层应用的人员一般对底层网络部分研究的较少,另外针对应用层调用write写TCP数据并返回写入的字节数就认为成功到达了对端这个问题很多人存在误解。涉及的nginx发出响应处理流程和linux系统TCP的处理过程,,简要解释如下:

nginx记录访问日志的时机

通过ngx_http_output_filter()发送响应数据给client
ngx_http_write_filter()会调用c->send_chain()往客户端发送数据,c->send_chain()的取值
在不同操作系统,编译选项以及协议下(https下用的是
ngx_ssl_send_chain)会取不同的函数,典型的Linux操作系统下,它的取值为ngx_linux_sendfile_chain(),这个函数中使用rc = writev(c->fd, header.elts, header.nelts);发送数据;

响应的字节全部发送完成后调用 ngx_http_finalize_request(r, rc);

ngx_http_finalize_request()

-->ngx_http_terminate_request()强制结束请求

或者直接调用-->

-->ngx_http_close_request()

-->ngx_http_free_request()

-->ngx_http_log_request(r);//记录日志

再看一下TCP数据的发送流程

这里定义为数据拷贝到协议栈缓存和缓存数据发送两个阶段。

应用层发送数据时调用TCP数据发送函数可以是write、send、sendmsg 这三个函数参数中携带需要发送的数据,最终在内核层面都是通过调用__sock_sendmsg()实现,对TCP数据来说__sock_sendmsg()函数中会再调用tcp_sendmsg(); 而tcp_sendmsg()函数中根据现有的TCP缓存是否足够会选择将应用层的数据复制到sk_buff中,复制完成的sk_buff挂入到sk_write_queue 队列尾部等待发送; 这个流程的代码中用copied变量代表了真实从应用层已经拷贝到sk_buff中的数据量,下边会走真正的TCP发送流程。但不管下边的流程能否真正的发送出去数据,会返回这个copied到应用层代表写入成功的数量; 而协议栈缓存数据的发送就由我们所熟知的TCP可靠传输机制去保证到达对端了。

协议栈缓存数据的发送通过以下几个函数负责:

-->tcp_push()

-->__tcp_push_pending_frames()

-->tcp_write_xmit()

** 在tcp_write_xmit()中会逐步检查本端的拥塞窗口(拥塞控制算法不断的在调整)设置是否有配额cwnd_quota可以发送报文? 配额不足则跳出;

** 进行发送窗口snd_wnd 检测, 若发送的MSS超过了发送窗口则跳出;

** 若开启了Nagle算法不能立即发送此报文则跳出;

如果能通过以上等的限制则调用tcp_transmit_skb()真正的执行发送数据。

综合所述TCP数据的发送其实是个异步的执行过程,应用层负责把数据写入到TCP缓存中,而缓存中的数据需要靠TCP的可靠传输机制去保证发送到对端,由于TCP的可靠传输机制执行过程中会考虑拥塞窗口、对端接收窗口、MSS、nagle算法等因素,执行完成后返回的copied字节量并不一定就代表对端接收成功了。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
17天前
|
开发框架 安全 应用服务中间件
【文件上传绕过】——解析漏洞_IIS7.0 | IIS7.5 | Nginx的解析漏洞
【文件上传绕过】——解析漏洞_IIS7.0 | IIS7.5 | Nginx的解析漏洞
29 9
|
30天前
|
Java Shell Linux
【Linux入门技巧】新员工必看:用Shell脚本轻松解析应用服务日志
关于如何使用Shell脚本来解析Linux系统中的应用服务日志,提供了脚本实现的详细步骤和技巧,以及一些Shell编程的技能扩展。
23 0
【Linux入门技巧】新员工必看:用Shell脚本轻松解析应用服务日志
|
1月前
|
存储 运维 监控
深入Linux核心:文件系统与日志解析
【8月更文挑战第20天】
36 2
|
2月前
|
网络协议 算法 程序员
提高网络稳定性的关键:TCP滑动窗口与拥塞控制解析
**TCP可靠传输与拥塞控制概要:** 小米讲解TCP如何确保数据可靠性。TCP通过分割数据、编号段、校验和、流量控制(滑动窗口)和拥塞控制(慢开始、拥塞避免、快重传、快恢复)保证数据安全传输。拥塞控制动态调整窗口大小,防止网络过载,提升效率。当连续收到3个相同ACK时执行快重传,快恢复避免剧烈波动。关注“软件求生”获取更多技术内容。
64 4
提高网络稳定性的关键:TCP滑动窗口与拥塞控制解析
|
2月前
|
缓存 负载均衡 应用服务中间件
nginx.conf 配置解析及常用配置
nginx.conf 配置解析及常用配置
64 6
|
29天前
|
域名解析 网络协议 Linux
在Linux中,我们都知道,dns采用了tcp协议,又采用了udp协议,什么时候采用tcp协议?什么 时候采用udp协议?为什么要这么设计?
在Linux中,我们都知道,dns采用了tcp协议,又采用了udp协议,什么时候采用tcp协议?什么 时候采用udp协议?为什么要这么设计?
|
2月前
|
数据采集 分布式计算 DataWorks
DataWorks产品使用合集之任务工作流中遇到了日志信息显示参数值没有正确解析的问题,该如何处理
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
|
1月前
|
Ubuntu 应用服务中间件 nginx
Docker 解析:如何将 Nginx 容器化并用作代理
Docker 解析:如何将 Nginx 容器化并用作代理
38 0
|
1月前
|
域名解析 缓存 负载均衡
深度解析Nginx正向代理的原理与实现
Nginx虽然主要被用作反向代理,但也可以通过一些特殊配置用作正向代理。虽然不是它的主流用途,但它仍能以其高性能和高稳定性为用户提供代理服务。不过,出于安全性和匿名性的考虑,在使用它作为正向代理时须谨慎配置,并根据实际需求做出调整。
56 0
|
2月前
|
网络协议 程序员
TCP报文格式全解析:网络小白变高手的必读指南
**TCP报文格式详解摘要** 探索TCP,传输层的关键协议,提供可靠数据传输。报文含源/目的端口(标识应用),32位序号(跟踪字节顺序),确认序号(确认接收),4位首部长度,6位标志(URG, ACK, PSH, RST, SYN, FIN),窗口大小(流量控制),检验和(数据完整性),紧急指针(优先数据)及可变长选项(如MSS, 时间戳)。了解这些字段,能更好地理解TCP连接的建立、管理和数据交换。
187 3

推荐镜像

更多