ngixn mirror及子请求源码分析
字数 808 2025-08-15 21:32:49
Nginx Mirror及子请求源码深度解析
1. 核心数据结构
Nginx处理mirror和子请求时主要依赖两个核心数据结构:
1.1 postponed链表
struct ngx_http_postponed_request_s {
ngx_http_request_t *request; // 指向请求对象
ngx_chain_t *out; // 输出链
ngx_http_postponed_request_t *next; // 下一个节点
};
- 每个请求都有一个postponed链表
- 一般情况下每个链表节点保存了该请求的一个子请求
- 用于控制请求处理的顺序和输出顺序
1.2 posted_requests链表
struct ngx_http_posted_request_s {
ngx_http_request_t *request; // 指向请求对象
ngx_http_posted_request_t *next; // 下一个节点
};
- 挂载当前需要遍历的请求
- 保存在主请求(根节点)的posted_requests字段
- 用于异步处理请求队列
2. Mirror模块配置
典型mirror配置示例:
server {
listen 10.10.10.10:8080;
location / {
mirror /mirror; # 指定mirror路径
proxy_pass http://vedio_play_support;
session_sticky_hide_cookie upstream=vedio_play_support;
}
location = /mirror {
internal; # 内部location
proxy_pass http://backend$request_uri;
}
}
3. Mirror处理流程
3.1 处理入口
mirror handler处于precontent阶段:
static ngx_int_t ngx_http_mirror_handler(ngx_http_request_t *r)
{
mlcf = ngx_http_get_module_loc_conf(r, ngx_http_mirror_module);
// 如果需要接收请求体
if (mlcf->request_body) {
rc = ngx_http_read_client_request_body(r, ngx_http_mirror_body_handler);
}
return ngx_http_mirror_handler_internal(r);
}
3.2 请求体处理回调
当请求体接收完成后调用的回调函数:
static void ngx_http_mirror_body_handler(ngx_http_request_t *r)
{
ngx_http_mirror_ctx_t *ctx;
ctx = ngx_http_get_module_ctx(r, ngx_http_mirror_module);
// 创建子请求并与主请求关联
ctx->status = ngx_http_mirror_handler_internal(r);
r->preserve_body = 1;
// 主请求继续执行处理阶段
r->write_event_handler = ngx_http_core_run_phases;
ngx_http_core_run_phases(r);
}
3.3 创建子请求
static ngx_int_t ngx_http_mirror_handler_internal(ngx_http_request_t *r)
{
// 遍历mirror数组,生成subrequest
for (i = 0; i < mlcf->mirror->nelts; i++) {
if (ngx_http_subrequest(r, &name[i], &r->args, &sr, NULL,
NGX_HTTP_SUBREQUEST_BACKGROUND) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
sr->header_only = 1;
sr->method = r->method;
sr->method_name = r->method_name;
}
return NGX_DECLINED;
}
4. 子请求处理机制
4.1 创建子请求
ngx_int_t ngx_http_subrequest(ngx_http_request_t *r, ngx_str_t *uri,
ngx_str_t *args, ngx_http_request_t **psr,
ngx_http_post_subrequest_t *ps, ngx_uint_t flags)
{
// 申请新的request结构
sr = ngx_pcalloc(r->pool, sizeof(ngx_http_request_t));
// 如果不是background模式(mirror默认使用background模式)
if (!sr->background) {
if (c->data == r && r->postponed == NULL) {
c->data = sr;
}
// 申请postponed_request结构体包装子请求
pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
pr->request = sr;
pr->out = NULL;
pr->next = NULL;
// 将pr挂到r->postponed链表里
if (r->postponed) {
for (p = r->postponed; p->next; p = p->next) { /* void */ }
p->next = pr;
} else {
r->postponed = pr;
}
}
sr->internal = 1;
sr->method = NGX_HTTP_GET;
sr->read_event_handler = ngx_http_request_empty_handler;
sr->write_event_handler = ngx_http_handler;
r->main->count++;
*psr = sr;
// 将子请求挂到main request的posted_requests中
return ngx_http_post_request(sr, NULL);
}
4.2 将请求加入posted队列
ngx_int_t ngx_http_post_request(ngx_http_request_t *r,
ngx_http_posted_request_t *pr)
{
if (pr == NULL) {
pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t));
pr->request = r;
pr->next = NULL;
// 找到main request的posted_requests,放到末尾
for (p = &r->main->posted_requests; *p; p = &(*p)->next) { /* void */ }
*p = pr;
}
// ...
}
4.3 运行posted请求
void ngx_http_run_posted_requests(ngx_connection_t *c)
{
ngx_http_request_t *r;
ngx_http_posted_request_t *pr;
r = c->data;
// 从main开始遍历所有子请求
pr = r->main->posted_requests;
if (pr == NULL) {
return;
}
r->main->posted_requests = pr->next;
r = pr->request;
// 调用write event handler,mirror的handler是ngx_http_handler
r->write_event_handler(r);
}
5. 请求处理阶段
5.1 请求处理器
void ngx_http_handler(ngx_http_request_t *r)
{
if (!r->internal) {
// 处理外部请求的连接类型
switch (r->headers_in.connection_type) {
// ...处理各种连接类型...
}
r->phase_handler = 0; // 从第一个阶段开始
} else {
// 对于mirror等内部请求,从server_rewrite阶段开始
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
r->phase_handler = cmcf->phase_engine.server_rewrite_index;
}
// 执行处理阶段
r->write_event_handler = ngx_http_core_run_phases;
ngx_http_core_run_phases(r);
}
5.2 请求头处理
static void ngx_http_process_request_headers(ngx_event_t *rev)
{
// 成功解析完整个header后
rc = ngx_http_process_request_header(r);
if (rc != NGX_OK) {
break;
}
ngx_http_process_request(r);
// 运行子请求
ngx_http_run_posted_requests(c);
}
6. 请求终结处理
6.1 终结请求函数
void ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
{
// 如果是子请求且有回调函数
if (r != r->main && r->post_subrequest) {
rc = r->post_subrequest->handler(r, r->post_subrequest->data, rc);
}
// 处理子请求
if (r != r->main) {
// background模式直接关闭request
if (r->background) {
r->done = 1;
ngx_http_finalize_connection(r);
return;
}
// 还有未处理完的数据或子请求
if (r->buffered || r->postponed) {
// 添加写事件以便下次继续处理
if (ngx_http_set_write_handler(r) != NGX_OK) {
ngx_http_terminate_request(r, 0);
}
return;
}
pr = r->parent;
// 子请求处理完毕
if (r == c->data) {
r->main->count--;
r->done = 1;
// 从父请求的postponed链表中删除
if (pr->postponed && pr->postponed->request == r) {
pr->postponed = pr->postponed->next;
}
// 将c->data指向parent
c->data = pr;
} else {
// 子请求提前完成且没有产生数据
r->write_event_handler = ngx_http_request_finalizer;
if (r->waited) {
r->done = 1;
// 将父请求加入posted_request队尾
if (ngx_http_post_request(pr, NULL) != NGX_OK) {
r->main->count++;
ngx_http_terminate_request(r, 0);
return;
}
}
}
}
// 处理主请求结束逻辑
if (r->buffered || c->buffered || r->postponed || r->blocked) {
// 添加写事件以便下次继续处理
if (ngx_http_set_write_handler(r) != NGX_OK) {
ngx_http_terminate_request(r, 0);
}
return;
}
// ...
}
7. 响应处理逻辑
7.1 upstream响应处理
static void ngx_http_upstream_process_header(ngx_http_request_t *r,
ngx_http_upstream_t *u)
{
ngx_http_upstream_send_response(r, u);
}
static void ngx_http_upstream_send_response(ngx_http_request_t *r,
ngx_http_upstream_t *u)
{
rc = ngx_http_send_header(r);
p->output_filter = ngx_http_upstream_output_filter;
}
static ngx_int_t ngx_http_upstream_output_filter(void *data, ngx_chain_t *chain)
{
rc = ngx_http_output_filter(r, chain);
}
7.2 输出过滤器链
ngx_int_t ngx_http_send_header(ngx_http_request_t *r)
{
return ngx_http_top_header_filter(r);
}
ngx_int_t ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
rc = ngx_http_top_body_filter(r, in);
}
7.3 延迟过滤器
static ngx_int_t ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
ngx_connection_t *c;
ngx_http_postponed_request_t *pr;
c = r->connection;
// 如果r不等于c->data,说明是需要保存数据的父request
if (r != c->data) {
if (in) {
// 保存数据
ngx_http_postpone_filter_add(r, in);
return NGX_OK;
}
return NGX_OK;
}
// 如果r->postponed为空,说明是最后一个sub request
if (r->postponed == NULL) {
// 发送数据
if (in || c->buffered) {
return ngx_http_next_filter(r->main, in);
}
return NGX_OK;
}
// ...
}
8. 关键点总结
-
子请求特性:
- 子请求不存在响应头部的概念
- 子请求读事件设置为空,不受前端控制
- 默认从server_rewrite阶段开始处理
-
处理顺序控制:
- postponed链表控制子请求的处理顺序
- posted_requests链表管理待处理请求队列
-
Mirror模块特点:
- 使用background模式创建子请求
- 主请求和mirror请求并行处理
- mirror请求默认header_only=1
-
输出控制:
- 通过postpone_filter控制响应输出顺序
- 子请求的输出会被缓存直到轮到它发送
-
请求生命周期:
- 通过finalize_request函数统一处理请求终结
- 主请求和子请求有不同的终结路径