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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
日志服务 SLS,月写入数据量 50GB 1个月
云解析 DNS,旗舰版 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日志并进行多维度分析。
目录
相关文章
|
27天前
|
监控 应用服务中间件 定位技术
要统计Nginx的客户端IP,可以通过分析Nginx的访问日志文件来实现
要统计Nginx的客户端IP,可以通过分析Nginx的访问日志文件来实现
|
2月前
|
存储 监控 安全
深入解析Sysmon日志:增强网络安全与威胁应对的关键一环
在不断演进的网络安全领域中,保持对威胁的及时了解至关重要。Sysmon日志在这方面发挥了至关重要的作用,通过提供有价值的见解,使组织能够加强其安全姿态。Windows在企业环境中是主导的操作系统,因此深入了解Windows事件日志、它们的独特特性和局限性,并通过Sysmon进行增强,变得至关重要。
|
2月前
|
应用服务中间件 测试技术 nginx
Nginx入门 -- 解析Nginx中的基本概念:Keepalive
Nginx入门 -- 解析Nginx中的基本概念:Keepalive
148 0
|
3月前
|
开发框架 安全 应用服务中间件
【文件上传绕过】——解析漏洞_IIS7.0 | IIS7.5 | Nginx的解析漏洞
【文件上传绕过】——解析漏洞_IIS7.0 | IIS7.5 | Nginx的解析漏洞
182 9
|
2月前
|
存储 缓存 网络协议
搭建dns服务常见报错--查看/etc/named.conf没有错误日志信息却显示出错(/etc/named.conf:49: missing ‘;‘ before ‘include‘)及dns介绍
搭建dns服务常见报错--查看/etc/named.conf没有错误日志信息却显示出错(/etc/named.conf:49: missing ‘;‘ before ‘include‘)及dns介绍
210 0
|
4月前
|
应用服务中间件 nginx
nginx error日志 client intended to send too large body: 1434541 bytes 如何处理?
【8月更文挑战第27天】nginx error日志 client intended to send too large body: 1434541 bytes 如何处理?
395 6
|
4月前
|
应用服务中间件 Linux nginx
在Linux中,如何统计ip访问情况?分析 nginx 访问日志?如何找出访问页面数量在前十位的ip?
在Linux中,如何统计ip访问情况?分析 nginx 访问日志?如何找出访问页面数量在前十位的ip?
|
4月前
|
数据库 Java 监控
Struts 2 日志管理化身神秘魔法师,洞察应用运行乾坤,演绎奇幻篇章!
【8月更文挑战第31天】在软件开发中,了解应用运行状况至关重要。日志管理作为 Struts 2 应用的关键组件,记录着每个动作和决策,如同监控摄像头,帮助我们迅速定位问题、分析性能和使用情况,为优化提供依据。Struts 2 支持多种日志框架(如 Log4j、Logback),便于配置日志级别、格式和输出位置。通过在 Action 类中添加日志记录,我们能在开发过程中获取详细信息,及时发现并解决问题。合理配置日志不仅有助于调试,还能分析用户行为,提升应用性能和稳定性。
66 0
|
4月前
|
SQL 安全 测试技术
【数据守护者必备】SQL数据备份与恢复策略全解析:从全量到日志备份,手把手教你确保企业信息万无一失的实战技巧!
【8月更文挑战第31天】数据库是企业核心业务数据的基石,为防止硬件故障、软件错误或人为失误导致的数据丢失,制定可靠的备份与恢复策略至关重要。本文通过一个在线购物平台的案例,详细介绍了使用 SQL Server 进行全量备份、差异备份及事务日志备份的方法,并演示了如何利用 SQL Server Agent 实现自动化备份任务。此外,还提供了数据恢复的具体步骤和测试建议,确保数据安全与业务连续性。
223 0
|
1月前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
379 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板

推荐镜像

更多