Nginx超时检测主流程

请求不能在指定时间内完成时触发Nginx的超时机制。
定时器由红黑树实现,红黑树中最左边的节点代表最有可能的超时事件。

timer_resolution

Nginx提供2种超时检测方案:
1. 设置定时器,每过固定间隔时间进行超时检测扫描,缺点是超时事件可能得不到及时处理。
2. 等待当前时间与最有可能的超时事件时间差值后,再进行超时检测扫描。

src/event/ngx_event.c中

ngx_timer_resolution = ccf->timer_resolution;

打印日志确认timer_resolution默认值

printf("%s:%d ngx_timer_resolution is %ld\n", __FILE__, __LINE__, ngx_timer_resolution);

工作进程的核心处理函数ngx_process_events_and_timers
采用方案1还是方案2由timer_resolution决定,timer_resolution默认值是0,说明默认采用方案2。

请求处理相关参数

keepalive_timeout
HTTP长连接的最长存活时间
proxy_read_timeout
Nginx在连续的proxy_read_timeout秒内没有从上游server收到数据时连接关闭
proxy_send_timeout
Nginx在连续的proxy_send_timeout秒内没有向上游server发送数据时连接关闭
client_header_timeout
Nginx等待客户端发送请求头的超时时间
client_body_timeout
Nginx读取客户端请求体的超时时间
proxy_connect_timeout
Nginx与上游服务器尝试建立连接的超时时间

根据日志分析流程

修改Nginx配置文件

go应用—http等待3s返回

package main

import (
	"fmt"
	"io"
	"net/http"
	"time"
)

func main() {
	// 注册路由
	http.HandleFunc("/test", func(writer http.ResponseWriter, request *http.Request) {
		// 构造超时
		time.Sleep(3 * time.Second)
		_, _ = io.WriteString(writer, "ok\n")
	})

	if err := http.ListenAndServe("localhost:1000", nil); err != nil {
		fmt.Printf("服务启动失败, err is %v\n", err)
	}
}

curl请求

根据ngx_cached_err_log_time.data来打印当前时间,输出一次请求处理日志

等待客户端发送请求头 -> 等待与上游服务器建立连接 -> 等待上游服务器响应数据 -> 非HTTP长连接时关闭连接

1.src/event/ngx_event.c中ngx_process_events_and_timers函数(处理事件和定时器)
2.src/event/ngx_event_timer.c中ngx_event_expire_timers函数(获取最左边节点的超时事件并移出红黑树,直到红黑树是空树或者没有超时事件)
3.src/os/unix/ngx_process_cycle.c中ngx_worker_process_cycle函数
4.src/event/modules/ngx_epoll_module.c中ngx_epoll_process_events函数(epoll_wait阻塞等待后更新当前时间)
src/event/ngx_event.c中ngx_process_events_and_timers函数

epoll_wait等待当前时间与红黑树最左边节点时间的差值。

参考资料

《深入剖析Nginx》

posted on 2022-11-26 23:00  王景迁  阅读(418)  评论(0编辑  收藏  举报

导航