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》