Skip to content

Commit 92c61bb

Browse files
author
yazhou.yang
committed
http v2 analyze
1 parent 8229d68 commit 92c61bb

File tree

6 files changed

+50
-19
lines changed

6 files changed

+50
-19
lines changed

nginx-1.9.2/objs/nginx

139 Bytes
Binary file not shown.

nginx-1.9.2/src/core/ngx_connection.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,14 +248,16 @@ typedef enum {
248248
ngx_event_t *write; //连接对应的写事件 赋值在ngx_event_process_init 一般在ngx_handle_write_event中添加些事件,空间是从ngx_cycle_t->read_event池子中获取的
249249

250250
ngx_socket_t fd;//套接字句柄
251-
251+
/* 如果启用了ssl,则发送和接收数据在ngx_ssl_recv ngx_ssl_write ngx_ssl_recv_chain ngx_ssl_send_chain */
252252
//服务端通过ngx_http_wait_request_handler读取数据
253253
ngx_recv_pt recv; //直接接收网络字符流的方法 见ngx_event_accept或者ngx_http_upstream_connect 赋值为ngx_os_io 在接收到客户端连接或者向上游服务器发起连接后赋值
254254
ngx_send_pt send; //直接发送网络字符流的方法 见ngx_event_accept或者ngx_http_upstream_connect 赋值为ngx_os_io 在接收到客户端连接或者向上游服务器发起连接后赋值
255255

256+
/* 如果启用了ssl,则发送和接收数据在ngx_ssl_recv ngx_ssl_write ngx_ssl_recv_chain ngx_ssl_send_chain */
256257
//以ngx_chain_t链表为参数来接收网络字符流的方法 ngx_recv_chain
257258
ngx_recv_chain_pt recv_chain; //赋值见ngx_event_accept ngx_event_pipe_read_upstream中执行
258259
//以ngx_chain_t链表为参数来发送网络字符流的方法 ngx_send_chain
260+
//当http2头部帧发送的时候,会在ngx_http_v2_header_filter把ngx_http_v2_send_chain.send_chain=ngx_http_v2_send_chain
259261
ngx_send_chain_pt send_chain; //赋值见ngx_event_accept ngx_http_write_filter和ngx_chain_writer中执行
260262

261263
//这个连接对应的ngx_listening_t监听对象,通过listen配置项配置,此连接由listening监听端口的事件建立,赋值在ngx_event_process_init

nginx-1.9.2/src/http/ngx_http_request.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,7 @@ name=Professional%20Ajax&publisher=Wiley
15311531
//如果后端带有Transfer-Encoding: chunked会置1
15321532
unsigned chunked:1; //chunk编码方式组包实际组包过程参考ngx_http_chunked_body_filter
15331533
//当下游的r->method == NGX_HTTP_HEAD请求方法只请求头部行,则会在ngx_http_header_filter中置1
1534+
//HTTP2头部帧发送在ngx_http_v2_header_filter中置1
15341535
unsigned header_only:1; //表示是否只有行、头部,没有包体 ngx_http_header_filter中置1
15351536
//在1.0以上版本默认是长连接,1.0以上版本默认置1,如果在请求头里面没有设置连接方式,见ngx_http_handler
15361537
//标志位,为1时表示当前请求是keepalive请求 1长连接 0短连接 长连接时间通过请求头部的Keep-Alive:设置,参考ngx_http_headers_in_t

nginx-1.9.2/src/http/v2/ngx_http_v2.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,7 @@ ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c)
495495
out->blocked, out->length);
496496
}
497497

498+
/* 如果启用了ssl,则发送和接收数据在ngx_ssl_recv ngx_ssl_write ngx_ssl_recv_chain ngx_ssl_send_chain */
498499
cl = c->send_chain(c, cl, 0);
499500

500501
if (cl == NGX_CHAIN_ERROR) {
@@ -577,6 +578,7 @@ ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c)
577578
frame = out;
578579
}
579580

581+
/* */
580582
h2c->last_out = frame;
581583

582584
return NGX_OK;
@@ -1321,6 +1323,8 @@ ngx_http_v2_state_header_block(ngx_http_v2_connection_t *h2c, u_char *pos,
13211323
| Value String (Length octets) |
13221324
+-------------------------------+
13231325
*/
1326+
1327+
/* NGINX在ngx_http_v2_state_header_block对接收到的头部帧进行解码解包,在ngx_http_v2_header_filter中对头部帧进行编码组包 */
13241328
if (ch >= (1 << 7)) { /* 128 ~ 256的时候prefix为bit:0111 1111 */
13251329
//在预定的头字段静态映射表 中已经有预定义的 Header Name 和 Header Value值
13261330
/* indexed header field */ //说明索引表中已经存在该请求行信息,见ngx_http_v2_static_table
@@ -1347,8 +1351,9 @@ ngx_http_v2_state_header_block(ngx_http_v2_connection_t *h2c, u_char *pos,
13471351
prefix = ngx_http_v2_prefix(3);
13481352
}
13491353

1354+
//这里的value索引解码过程和ngx_http_v2_indexed对应
13501355
value = ngx_http_v2_parse_int(h2c, &pos, end, prefix);
1351-
1356+
13521357
if (value < 0) {
13531358
if (value == NGX_AGAIN) {
13541359
return ngx_http_v2_state_save(h2c, pos, end,
@@ -2485,7 +2490,7 @@ ngx_http_v2_connection_error(ngx_http_v2_connection_t *h2c,
24852490
return NULL;
24862491
}
24872492

2488-
2493+
//这里的index索引解码过程和ngx_http_v2_indexed对应
24892494
static ngx_int_t
24902495
ngx_http_v2_parse_int(ngx_http_v2_connection_t *h2c, u_char **pos, u_char *end,
24912496
ngx_uint_t prefix)

nginx-1.9.2/src/http/v2/ngx_http_v2.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ typedef struct {
526526
/* 如果收到的value不在压缩表中,需要直接从报文读取,见ngx_http_v2_state_header_block ngx_http_v2_state_process_header */
527527
unsigned parse_value:1;
528528
/* ngx_http_v2_state_header_block中置1,表示需要把name:value通过ngx_http_v2_add_header加入动态表中,然后置0 */
529-
unsigned index:1; //需要添加name:value到动态表中
529+
unsigned index:1; //需要添加name:value到映射表中
530530
ngx_http_v2_header_t header; //赋值见ngx_http_v2_get_indexed_header
531531
/* header内容中的所有name+value之和长度最大值,生效见ngx_http_v2_state_process_header
532532
限制经过HPACK压缩后完整请求头的最大尺寸。
@@ -594,7 +594,8 @@ struct ngx_http_v2_connection_s {
594594

595595
/* ngx_http_v2_create_stream中自增,表示创建的流的数量,ngx_http_v2_close_stream自减 */
596596
ngx_uint_t processing;
597-
597+
598+
/* 注意ngx_http_v2_connection_s的send_window、recv_window、init_window与ngx_http_v2_stream_s的send_window、recv_window的区别 */
598599
size_t send_window;//默认NGX_HTTP_V2_DEFAULT_WINDOW
599600
size_t recv_window;//默认NGX_HTTP_V2_MAX_WINDOW
600601
// 接收到对端的setting帧后,会做调整,见ngx_http_v2_state_settings_params
@@ -665,14 +666,16 @@ struct ngx_http_v2_stream_s {
665666
ngx_http_v2_node_t *node;
666667

667668
ngx_uint_t header_buffers;
669+
//1表示数据已经入队,还没有发送,在ngx_http_v2_finalize_connection清0
668670
ngx_uint_t queued;
669671

670672
/*
671673
* A change to SETTINGS_INITIAL_WINDOW_SIZE could cause the
672674
* send_window to become negative, hence it's signed.
673675
*/
674-
ssize_t send_window;
675-
size_t recv_window;
676+
/* 注意ngx_http_v2_connection_s的send_window、recv_window、init_window与ngx_http_v2_stream_s的send_window、recv_window的区别 */
677+
ssize_t send_window; //默认值NGX_HTTP_V2_DEFAULT_WINDOW
678+
size_t recv_window; //默认值NGX_HTTP_V2_MAX_WINDOW
676679

677680
ngx_http_v2_out_frame_t *free_frames;
678681
ngx_chain_t *free_data_headers;

nginx-1.9.2/src/http/v2/ngx_http_v2_filter_module.c

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,17 @@
1111
#include <nginx.h>
1212
#include <ngx_http_v2_module.h>
1313

14-
14+
//这里的ngx_http_v2_integer_octets ngx_http_v2_integer_octets index索引编码过程和ngx_http_v2_state_header_block中的解码过程对应
15+
//ngx_http_v2_integer_octets ngx_http_v2_indexed进行整数编码,ngx_http_v2_literal_size进行字符串编码
1516
#define ngx_http_v2_integer_octets(v) (((v) + 127) / 128)
16-
1717
#define ngx_http_v2_literal_size(h) \
1818
(ngx_http_v2_integer_octets(sizeof(h) - 1) + sizeof(h) - 1)
1919

20+
/* 128也就是位操作1000 0000,也就是该index在索引表中,如果i为1表示索引表的0,i=2对应索引表的1,i=3对应索引表的2,i=4对应索引表的3 */
2021
#define ngx_http_v2_indexed(i) (128 + (i))
2122
#define ngx_http_v2_inc_indexed(i) (64 + (i))
2223

23-
24+
/* 和ngx_http_v2_static_table数组下表对应,相差1 */
2425
#define NGX_HTTP_V2_STATUS_INDEX 8
2526
#define NGX_HTTP_V2_STATUS_200_INDEX 8
2627
#define NGX_HTTP_V2_STATUS_204_INDEX 9
@@ -230,7 +231,9 @@ ngx_http_v2_header_filter(ngx_http_request_t *r)
230231
}
231232
}
232233

233-
/* NGINX在ngx_http_v2_state_header_block对接收到的头部帧进行解码解包,在ngx_http_v2_header_filter中对头部帧进行编码组包 */
234+
/* NGINX在ngx_http_v2_state_header_block对接收到的头部帧进行解码解包,在ngx_http_v2_header_filter中对头部帧进行编码组包
235+
静态映射表在ngx_http_v2_static_table
236+
*/
234237

235238
/* 头部9字节 + status响应长度(1字节为什么可以表示status响应码,因为一个字节就可以表示静态表的那个成员,见ngx_http_v2_static_table) */
236239
len = NGX_HTTP_V2_FRAME_HEADER_SIZE
@@ -379,6 +382,7 @@ ngx_http_v2_header_filter(ngx_http_request_t *r)
379382
part = &r->headers_out.headers.part;
380383
header = part->elts;
381384

385+
/* header_out数组列表中的所有NAME:VALUE长度加进来 */
382386
for (i = 0; /* void */; i++) {
383387

384388
if (i >= part->nelts) {
@@ -415,6 +419,7 @@ ngx_http_v2_header_filter(ngx_http_request_t *r)
415419

416420
stream = r->stream;
417421

422+
/* 如果整个头部帧内容超过了最大frame_size大小,则可能需要拆分到多个帧 */
418423
len += NGX_HTTP_V2_FRAME_HEADER_SIZE
419424
* (len / stream->connection->frame_size);
420425

@@ -429,7 +434,6 @@ ngx_http_v2_header_filter(ngx_http_request_t *r)
429434

430435
if (status) {
431436
*b->last++ = status;
432-
433437
} else {
434438
*b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_STATUS_INDEX);
435439
*b->last++ = 3;
@@ -617,13 +621,15 @@ ngx_http_v2_header_filter(ngx_http_request_t *r)
617621
cl->buf = b;
618622
cl->next = NULL;
619623

624+
/* 针对前面的header帧封包,组一个frame结构,挂到h2c->last_out队列,通过ngx_http_v2_filter_send触发发送出去 */
620625
frame = ngx_palloc(r->pool, sizeof(ngx_http_v2_out_frame_t));
621626
if (frame == NULL) {
622627
return NGX_ERROR;
623628
}
624629

625630
frame->first = cl;
626631
frame->last = cl;
632+
//该frame上对应的数据发送完毕后,会调用ngx_http_v2_headers_frame_handler
627633
frame->handler = ngx_http_v2_headers_frame_handler;
628634
frame->stream = stream;
629635
frame->length = b->last - b->pos - NGX_HTTP_V2_FRAME_HEADER_SIZE;
@@ -641,11 +647,14 @@ ngx_http_v2_header_filter(ngx_http_request_t *r)
641647
return NGX_ERROR;
642648
}
643649

650+
644651
cln->handler = ngx_http_v2_filter_cleanup;
645652
cln->data = stream;
646653

647654
stream->queued = 1;
648655

656+
//把ngx_http_v2_send_chain.send_chain=ngx_http_v2_header_filter,后面的数据帧就通过该函数发送,
657+
//在读取到后端数据后开始走out filter流程,然后调用ngx_http_output_filter,最终执行该ngx_http_v2_send_chain
649658
fc->send_chain = ngx_http_v2_send_chain;
650659
fc->need_last_buf = 1;
651660

@@ -711,7 +720,12 @@ ngx_http_v2_write_continuation_head(u_char *pos, size_t length, ngx_uint_t sid,
711720
(void) ngx_http_v2_write_sid(pos, sid);
712721
}
713722

723+
/*
724+
当http2头部帧发送的时候,会在ngx_http_v2_header_filter把ngx_http_v2_send_chain.send_chain=ngx_http_v2_send_chain
714725
726+
该函数发送数据帧
727+
在读取到后端数据后开始走out filter流程,然后调用ngx_http_output_filter,最终执行该ngx_http_v2_send_chain
728+
*/
715729
static ngx_chain_t *
716730
ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit)
717731
{
@@ -726,6 +740,8 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit)
726740

727741
r = fc->data;
728742
stream = r->stream;
743+
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
744+
"ngx_http_v2_send_chain");
729745

730746
#if (NGX_SUPPRESS_WARN)
731747
size = 0;
@@ -741,7 +757,7 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit)
741757
in = in->next;
742758
}
743759

744-
if (in == NULL) {
760+
if (in == NULL) { /* chain链上没有要发送的数据 */
745761

746762
if (stream->queued) {
747763
fc->write->delayed = 1;
@@ -754,6 +770,7 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit)
754770

755771
h2c = stream->connection;
756772

773+
/* 窗口 */
757774
if (size && ngx_http_v2_flow_control(h2c, stream) == NGX_DECLINED) {
758775
fc->write->delayed = 1;
759776
return in;
@@ -779,31 +796,33 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit)
779796
offset = 0;
780797
}
781798

799+
/* 发送limit不能超过h2c->send_window和stream->send_window的最小值 */
782800
if (limit == 0 || limit > (off_t) h2c->send_window) {
783801
limit = h2c->send_window;
784802
}
785-
786803
if (limit > stream->send_window) {
787804
limit = (stream->send_window > 0) ? stream->send_window : 0;
788805
}
789806

790807
h2lcf = ngx_http_get_module_loc_conf(r, ngx_http_v2_module);
791808

809+
/* frame_size为本地配置chunk_size和对端通知的frame_size的最小值 */
792810
frame_size = (h2lcf->chunk_size < h2c->frame_size)
793811
? h2lcf->chunk_size : h2c->frame_size;
794812

795813
#if (NGX_SUPPRESS_WARN)
796814
cl = NULL;
797815
#endif
798816

799-
for ( ;; ) {
817+
for ( ;; ) {
800818
if ((off_t) frame_size > limit) {
801819
frame_size = (size_t) limit;
802820
}
803821

804822
ln = &out;
805823
rest = frame_size;
806824

825+
/* 把chain链中的buf组包到新的cl chain(即out链)链中,但是数据总大小不能超过rest限制 */
807826
while ((off_t) rest >= size) {
808827

809828
if (offset) {
@@ -831,8 +850,8 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit)
831850
in = in->next;
832851

833852
if (in == NULL) {
834-
frame_size -= rest;
835-
rest = 0;
853+
frame_size -= rest; //in链中的数据已经全部移到out链,这时候的frame_size就是out中的数据大小
854+
rest = 0; //清0,说明所有的in链中的数据都可以全部发送出去
836855
break;
837856
}
838857

@@ -861,6 +880,7 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit)
861880

862881
ngx_http_v2_queue_frame(h2c, frame);
863882

883+
/* 发送了这么多数据,则窗口减少 */
864884
h2c->send_window -= frame_size;
865885

866886
stream->send_window -= frame_size;
@@ -931,7 +951,7 @@ ngx_http_v2_filter_get_shadow(ngx_http_v2_stream_t *stream, ngx_buf_t *buf,
931951
return cl;
932952
}
933953

934-
954+
//获取data帧frame结构
935955
static ngx_http_v2_out_frame_t *
936956
ngx_http_v2_filter_get_data_frame(ngx_http_v2_stream_t *stream,
937957
size_t len, ngx_chain_t *first, ngx_chain_t *last)
@@ -1031,7 +1051,7 @@ ngx_http_v2_filter_send(ngx_connection_t *fc, ngx_http_v2_stream_t *stream)
10311051
return NGX_OK;
10321052
}
10331053

1034-
1054+
/* 查看发送窗口是不是大于0,大于0则发送 */
10351055
static ngx_inline ngx_int_t
10361056
ngx_http_v2_flow_control(ngx_http_v2_connection_t *h2c,
10371057
ngx_http_v2_stream_t *stream)

0 commit comments

Comments
 (0)