现在,我跟踪分析了 NGINX 代码。
当断点设置在ngx_http_request_body_filter_by_em 时,其回调如下所示:
ngx_http_em_module.dll!ngx_http_request_body_filter_by_em(ngx_http_request_s * req, ngx_chain_s * in) Line 2637 C++
NGINX.exe!ngx_http_request_body_length_filter(ngx_http_request_s * r, ngx_chain_s * in) Line 987 C
NGINX.exe!ngx_http_request_body_filter(ngx_http_request_s * r, ngx_chain_s * in) Line 923 C
NGINX.exe!ngx_http_read_client_request_body(ngx_http_request_s * r, void(*)(ngx_http_request_s *) post_handler) Line 102 C
NGINX.exe!ngx_http_proxy_handler(ngx_http_request_s * r) Line 937 C
NGINX.exe!ngx_http_core_content_phase(ngx_http_request_s * r, ngx_http_phase_handler_s * ph) Line 1247 C
NGINX.exe!ngx_http_core_run_phases(ngx_http_request_s * r) Line 868 C
> NGINX.exe!ngx_http_run_posted_requests(ngx_connection_s * c) Line 2408 C
NGINX.exe!ngx_http_upstream_handler(ngx_event_s * ev) Line 1287 C
NGINX.exe!ngx_event_process_posted(ngx_cycle_s * cycle, ngx_queue_s * posted) Line 35 C
NGINX.exe!ngx_process_events_and_timers(ngx_cycle_s * cycle) Line 265 C
NGINX.exe!ngx_worker_thread(void * data) Line 795 C
NGINX 代码 sn-p:
ngx_int_t ngx_http_request_body_filter_by_em(ngx_http_request_t *req, ngx_chain_t *in) {
// u->read_event_handler = 0x00007ff7b74cf3f0 {NGINX.exe!ngx_http_upstream_process_upstream(ngx_http_request_s *, ngx_http_upstream_s *)}
//req->main->posted_requests 0x0000000000000000 <NULL> ngx_http_posted_request_s *
//req->connection 0x0000029cc2080270 {data=0x0000029cc03e2e60 read=0x0000029cc20b8210 {data=0x0000029cc2080270 write=0 ...} ...} ngx_connection_s *
//req->main->write_event_handler 0x00007ff7b742c3ec {NGINX.exe!ngx_http_request_empty_handler} void(*)(ngx_http_request_s *)
}
static ngx_int_t ngx_http_proxy_handler(ngx_http_request_t *r) {
//...
rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
return rc;
}
return NGX_DONE;
}
ngx_int_t ngx_http_core_content_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph) {
//...
if (r->content_handler) {
r->write_event_handler = ngx_http_request_empty_handler;
ngx_http_finalize_request(r, r->content_handler(r));
return NGX_OK;
}
//...
}
void ngx_http_core_run_phases(ngx_http_request_t *r) {
//...
while (ph[r->phase_handler].checker) {
rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler]);
if (rc == NGX_OK) {
return;
}
}
}
void ngx_http_handler(ngx_http_request_t *r) {
//...
r->write_event_handler = ngx_http_core_run_phases;
ngx_http_core_run_phases(r);
}
void ngx_http_run_posted_requests(ngx_connection_t *c) {
// https://english.stackexchange.com/questions/23023/iterate-vs-iterate-over
//... Iterates ((ngx_http_request_t*)(c->data))->main->posted_requests
for ( ;; ) {
r->write_event_handler(r);
}
}
在ngx_http_run_posted_requests,我发现r->write_event_handler可能是以下函数之一:
0x00007ff7b742baf0 {NGINX.exe!ngx_http_handler}
0x00007ff7b742c3ec {NGINX.exe!ngx_http_request_empty_handler}
0x00007ff7b74d42f0 {NGINX.exe!ngx_http_upstream_wr_check_broken_connection(ngx_http_request_s *)}
0x00007ff7b74cc5c0 {NGINX.exe!ngx_http_upstream_process_downstream(ngx_http_request_s *)}
0x00007ff7b742bf19 {NGINX.exe!ngx_http_core_run_phases} void(*)(ngx_http_request_s *)
结果发现ngx_http_upstream_init在ngx_http_em_subrequest_sp_list_done之后没有被调用。
此外,我还检查并记录了req->write_event_handler、req->main->posted_requests 和req->main->write_event_handler 在调用这些ngx_http_post_subrequest_pt 处理程序时的值:
req->write_event_handler 0x00007ff7b742bf19 {NGINX.exe!ngx_http_core_run_phases} void(*)(ngx_http_request_s *)
req->main->posted_requests 0x0000000000000000 <NULL> ngx_http_posted_request_s *
req->main->write_event_handler 0x00007ff7b742bf19 {NGINX.exe!ngx_http_core_run_phases} void(*)(ngx_http_request_s *)
> ngx_http_em_module.dll!ngx_http_em_subrequest_attributes_done(ngx_http_request_s * req, void * data, __int64 rc) Line 1684 C++
NGINX.exe!ngx_http_finalize_request(ngx_http_request_s * r, __int64 rc) Line 2465 C
NGINX.exe!ngx_http_core_rewrite_phase(ngx_http_request_s * r, ngx_http_phase_handler_s * ph) Line 937 C
NGINX.exe!ngx_http_core_run_phases(ngx_http_request_s * r) Line 868 C
NGINX.exe!ngx_http_handler(ngx_http_request_s * r) Line 852 C
NGINX.exe!ngx_http_run_posted_requests(ngx_connection_s * c) Line 2408 C
NGINX.exe!ngx_http_process_request_headers(ngx_event_s * rev) Line 1502 C
NGINX.exe!ngx_http_process_request_line(ngx_event_s * rev) Line 1153 C
NGINX.exe!ngx_http_wait_request_handler(ngx_event_s * rev) Line 501 C
NGINX.exe!ngx_event_process_posted(ngx_cycle_s * cycle, ngx_queue_s * posted) Line 35 C
NGINX.exe!ngx_process_events_and_timers(ngx_cycle_s * cycle) Line 265 C
NGINX.exe!ngx_worker_thread(void * data) Line 795 C
req->write_event_handler 0x00007ff7b74cc5c0 {NGINX.exe!ngx_http_upstream_process_downstream(ngx_http_request_s *)} void(*)(ngx_http_request_s *)
req->main->posted_requests 0x0000000000000000 <NULL> ngx_http_posted_request_s *
req->main->write_event_handler 0x00007ff7b742bf19 {NGINX.exe!ngx_http_core_run_phases} void(*)(ngx_http_request_s *)
> ngx_http_em_module.dll!ngx_http_em_subrequest_token_done(ngx_http_request_s * req, void * data, __int64 rc) Line 1295 C++
NGINX.exe!ngx_http_finalize_request(ngx_http_request_s * r, __int64 rc) Line 2465 C
NGINX.exe!ngx_http_upstream_finalize_request(ngx_http_request_s * r, ngx_http_upstream_s * u, __int64 rc) Line 4495 C
NGINX.exe!ngx_http_upstream_process_request(ngx_http_request_s * r, ngx_http_upstream_s * u) Line 4051 C
NGINX.exe!ngx_http_upstream_process_upstream(ngx_http_request_s * r, ngx_http_upstream_s * u) Line 3963 C
NGINX.exe!ngx_http_upstream_send_response(ngx_http_request_s * r, ngx_http_upstream_s * u) Line 3241 C
NGINX.exe!ngx_http_upstream_process_header(ngx_http_request_s * r, ngx_http_upstream_s * u) Line 2435 C
NGINX.exe!ngx_http_upstream_handler(ngx_event_s * ev) Line 1286 C
NGINX.exe!ngx_event_process_posted(ngx_cycle_s * cycle, ngx_queue_s * posted) Line 35 C
NGINX.exe!ngx_process_events_and_timers(ngx_cycle_s * cycle) Line 265 C
NGINX.exe!ngx_worker_thread(void * data) Line 795 C
req->write_event_handler 0x00007ff7b742bf19 {NGINX.exe!ngx_http_core_run_phases} void(*)(ngx_http_request_s *)
req->main->posted_requests 0x0000000000000000 <NULL> ngx_http_posted_request_s *
req->main->write_event_handler 0x00007ff7b742bf19 {NGINX.exe!ngx_http_core_run_phases} void(*)(ngx_http_request_s *)
> ngx_http_em_module.dll!ngx_http_em_subrequest_evaluation_done(ngx_http_request_s * req, void * data, __int64 rc) Line 1368 C++
NGINX.exe!ngx_http_finalize_request(ngx_http_request_s * r, __int64 rc) Line 2465 C
NGINX.exe!ngx_http_core_rewrite_phase(ngx_http_request_s * r, ngx_http_phase_handler_s * ph) Line 937 C
NGINX.exe!ngx_http_core_run_phases(ngx_http_request_s * r) Line 868 C
NGINX.exe!ngx_http_handler(ngx_http_request_s * r) Line 852 C
NGINX.exe!ngx_http_run_posted_requests(ngx_connection_s * c) Line 2408 C
NGINX.exe!ngx_http_upstream_handler(ngx_event_s * ev) Line 1287 C
NGINX.exe!ngx_event_process_posted(ngx_cycle_s * cycle, ngx_queue_s * posted) Line 35 C
NGINX.exe!ngx_process_events_and_timers(ngx_cycle_s * cycle) Line 265 C
NGINX.exe!ngx_worker_thread(void * data) Line 795 C
req->write_event_handler 0x00007ff7b742bf19 {NGINX.exe!ngx_http_core_run_phases} void(*)(ngx_http_request_s *)
req->main->posted_requests 0x0000000000000000 <NULL> ngx_http_posted_request_s *
req->main->write_event_handler 0x00007ff7b74d42f0 {NGINX.exe!ngx_http_upstream_wr_check_broken_connection(ngx_http_request_s *)} void(*)(ngx_http_request_s *)
> ngx_http_em_module.dll!ngx_http_em_subrequest_sp_list_done(ngx_http_request_s * req, void * data, __int64 rc) Line 1896 C++
NGINX.exe!ngx_http_finalize_request(ngx_http_request_s * r, __int64 rc) Line 2465 C
NGINX.exe!ngx_http_core_rewrite_phase(ngx_http_request_s * r, ngx_http_phase_handler_s * ph) Line 937 C
NGINX.exe!ngx_http_core_run_phases(ngx_http_request_s * r) Line 868 C
NGINX.exe!ngx_http_handler(ngx_http_request_s * r) Line 852 C
NGINX.exe!ngx_http_run_posted_requests(ngx_connection_s * c) Line 2408 C
NGINX.exe!ngx_http_upstream_handler(ngx_event_s * ev) Line 1287 C
NGINX.exe!ngx_event_process_posted(ngx_cycle_s * cycle, ngx_queue_s * posted) Line 35 C
NGINX.exe!ngx_process_events_and_timers(ngx_cycle_s * cycle) Line 265 C
NGINX.exe!ngx_worker_thread(void * data) Line 795 C
现在,在我添加ngx_http_em_subrequest_sp_list_done 后,curl 客户端可以收到响应。
// assert(ngx_http_upstream_wr_check_broken_connection == req->parent->write_event_handler);
// assert(ngx_http_request_empty_handler == req->parent->write_event_handler);
req->parent->write_event_handler = ngx_http_core_run_phases;