1111#include <ngx_http_v2_module.h>
1212
1313
14+ /*
15+ NO_ERROR (0) : 相关的条件并不是错误的结果。例如超时帧可以携带此错误码指示连接的平滑关闭。
16+ PROTOCOL_ERROR (1) : 终端检测到一个不确定的协议错误。这个错误用在一个更具体的错误码不可用的时候。
17+ INTERNAL_ERROR (2) : 终端遇到意外的内部错误。
18+ FLOW_CONTROL_ERROR (3) : 终端检测到对等端违反了流量控制协议。
19+ SETTINGS_TIMEOUT (4) : 终端发送了设置帧,但是没有及时收到响应。见Settings Synchronization。
20+ STREAM_CLOSED (5) : 终端在流半封闭的时候收到帧。
21+ FRAME_SIZE_ERROR (6) : 终端收到大小超过最大尺寸的帧。
22+ REFUSED_STREAM (7) : 终端拒绝流在它执行任何应用处理之前,详见Reliability(章节 8.1.4)
23+ CANCEL (8) : 终端使用这个标示某个流不再需要。
24+ COMPRESSION_ERROR (9) : 终端无法维持报头压缩上下文的连接
25+ CONNECT_ERROR (10) : 响应某个连接请求建立的连接被服为异常关闭。
26+ ENHANCE_YOUR_CALM (11) : 终端检测出对等端在表现出可能会产生过大负荷的行为。
27+ INADEQUATE_SECURITY (12) : 基础传输包含属性不满足文档或者终端申明的最小要求。
28+ */
1429/* errors */
1530#define NGX_HTTP_V2_NO_ERROR 0x0
1631#define NGX_HTTP_V2_PROTOCOL_ERROR 0x1
5469#define NGX_HTTP_V2_MAX_WINDOW ((1U << 31) - 1)
5570#define NGX_HTTP_V2_DEFAULT_WINDOW 65535
5671
72+
73+ /*
74+ NGX_HTTP_V2_ROOT
75+ /|\ /|\
76+ / \
77+ / \parent
78+ / \
79+ (代表一个连接)h2c->dependencies h2c->dependencies(代表一个连接)
80+ | |
81+ | |
82+ | |children
83+ | |
84+ queue \|/ \|/ queue queue (A先依赖parent,过后B又依赖parent,过后C又依赖parent)
85+ nodeA<--------nodeB nodeC-------->nodeB------->nodeA (同一个父节点下的子节点,例如某个A B C都依赖于节点dependencies)
86+
87+
88+ 所有的ngx_http_v2_node_t节点最终都挂接到root下面组成树形结构,见ngx_http_v2_set_dependency
89+ */
5790#define NGX_HTTP_V2_ROOT (void *) -1
5891
5992
@@ -397,6 +430,16 @@ ngx_http_v2_read_handler(ngx_event_t *rev)
397430}
398431
399432
433+ /*
434+ 客户端一次uri请求发送过来header帧后,nginx应答给客户端的header帧和数据帧的stream id就是客户端请求header帧的id信息
435+
436+ HEADER帧发送流程:ngx_http_v2_filter_send->ngx_http_v2_send_output_queue
437+ DATA帧发送流程:ngx_http_v2_send_chain->ngx_http_v2_send_output_queue
438+ 一次发送不完(例如协议栈写满返回AGAIN)则下次通过ngx_http_v2_write_handler->ngx_http_v2_send_output_queue再次发送
439+
440+ 例如通过同一个connect来下载两个文件,则2个文件的相关信息会被组成一个一个交替的帧挂载到该链表上,通过该函数进行交替发送
441+ 发送队列last_out中的数据
442+ */
400443static void
401444ngx_http_v2_write_handler (ngx_event_t * wev )
402445{
@@ -454,12 +497,18 @@ ngx_http_v2_write_handler(ngx_event_t *wev)
454497}
455498
456499/*
457- EADER帧发送流程:ngx_http_v2_filter_send->ngx_http_v2_send_output_queue
500+ 客户端一次uri请求发送过来header帧后,nginx应答给客户端的header帧和数据帧的stream id就是客户端请求header帧的id信息
501+
502+ 客户端一次uri请求发送过来header帧后,nginx应答给客户端的header帧和数据帧的stream id就是客户端请求header帧的id信息
503+
504+ HEADER帧发送流程:ngx_http_v2_filter_send->ngx_http_v2_send_output_queue
458505DATA帧发送流程:ngx_http_v2_send_chain->ngx_http_v2_send_output_queue
459506一次发送不完(例如协议栈写满返回AGAIN)则下次通过ngx_http_v2_write_handler->ngx_http_v2_send_output_queue再次发送
460507
461508例如通过同一个connect来下载两个文件,则2个文件的相关信息会被组成一个一个交替的帧挂载到该链表上,通过该函数进行交替发送
462509发送队列last_out中的数据
510+
511+ ngx_http_v2_queue_frame对需要发送的帧进行优先级控制,权限高的放入队列首部,低的放入尾部,真正发送在ngx_http_v2_send_output_queue
463512*/
464513ngx_int_t
465514ngx_http_v2_send_output_queue (ngx_http_v2_connection_t * h2c )
@@ -1874,9 +1923,18 @@ ngx_http_v2_state_priority(ngx_http_v2_connection_t *h2c, u_char *pos,
18741923 ngx_http_v2_state_priority );
18751924 }
18761925
1926+ /* stream流依赖参考http://www.blogjava.net/yongboy/archive/2015/03/19/423611.aspx */
18771927 dependency = ngx_http_v2_parse_uint32 (pos );
18781928
18791929 depend = dependency & 0x7fffffff ;
1930+ /*
1931+ 独家专属标志(exclusive flag)将为现有依赖插入一个水平的依赖关系,其父级流只能被插入的新流所依赖。比如流D设置专属标志并依赖于流A:
1932+ A
1933+ A |
1934+ / \ ==> D
1935+ B C / \
1936+ B C
1937+ */
18801938 excl = dependency >> 31 ;
18811939 weight = pos [4 ] + 1 ;
18821940
@@ -1886,7 +1944,7 @@ ngx_http_v2_state_priority(ngx_http_v2_connection_t *h2c, u_char *pos,
18861944 "http2 PRIORITY frame sid:%ui on %ui excl:%ui weight:%ui" ,
18871945 h2c -> state .sid , depend , excl , weight );
18881946
1889- if (h2c -> state .sid == 0 ) {
1947+ if (h2c -> state .sid == 0 ) { //stream id为0的不能设置依赖
18901948 ngx_log_error (NGX_LOG_INFO , h2c -> connection -> log , 0 ,
18911949 "client sent PRIORITY frame with incorrect identifier" );
18921950
@@ -2658,7 +2716,6 @@ ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c, ngx_uint_t ack)
26582716 return NGX_OK ;
26592717}
26602718
2661-
26622719static ngx_int_t
26632720ngx_http_v2_settings_frame_handler (ngx_http_v2_connection_t * h2c ,
26642721 ngx_http_v2_out_frame_t * frame )
@@ -2960,7 +3017,7 @@ ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c)
29603017 return stream ;
29613018}
29623019
2963- /* 根据sid查找对应的node,如果找到直接返回,找不到则创建一个node节点 */
3020+ /* 根据sid查找对应的node,如果找到直接返回,找不到并在alloc=1(允许开辟新的空间创建新的node节点)则创建一个node节点 */
29643021static ngx_http_v2_node_t *
29653022ngx_http_v2_get_node_by_id (ngx_http_v2_connection_t * h2c , ngx_uint_t sid ,
29663023 ngx_uint_t alloc )
@@ -4096,23 +4153,49 @@ static ngx_int_t
40964153}
40974154
40984155
4156+ /*
4157+ exclusive:独家专属标志(exclusive flag)将为现有依赖插入一个水平的依赖关系,其父级流只能被插入的新流所依赖。比如流D设置专属标志并依赖于流A:
4158+ A
4159+ A |
4160+ / \ ==> D
4161+ B C / \
4162+ B C
4163+ 流依赖可以参考:http://www.blogjava.net/yongboy/archive/2015/03/19/423611.aspx
4164+
4165+ NGX_HTTP_V2_ROOT
4166+ /|\ /|\
4167+ / \
4168+ / \parent
4169+ / \
4170+ (代表一个连接)h2c->dependencies h2c->dependencies(代表一个连接)
4171+ | |
4172+ | |
4173+ | |children
4174+ | |
4175+ queue \|/ \|/ queue queue (A先依赖parent,过后B又依赖parent,过后C又依赖parent)
4176+ nodeA<--------nodeB nodeC-------->nodeB------->nodeA (同一个父节点下的子节点,例如某个A B C都依赖于节点dependencies)
4177+
4178+ */
40994179static void
41004180ngx_http_v2_set_dependency (ngx_http_v2_connection_t * h2c ,
41014181 ngx_http_v2_node_t * node , ngx_uint_t depend , ngx_uint_t exclusive )
41024182{
41034183 ngx_queue_t * children ;
41044184 ngx_http_v2_node_t * parent , * next ;
41054185
4186+ /* 根据depend查找parent对应的node节点,如果depend为0,则parent=NGX_HTTP_V2_ROOT */
41064187 parent = depend ? ngx_http_v2_get_node_by_id (h2c , depend , 0 ) : NULL ;
41074188
41084189 if (parent == NULL ) {
4190+ //这里可以看出所有连接是公用了同一个ROOT跟节点,而且权重也是共用的
41094191 parent = NGX_HTTP_V2_ROOT ;
41104192
41114193 if (depend != 0 ) {
41124194 exclusive = 0 ;
41134195 }
41144196
4115- node -> rank = 1 ;
4197+ node -> rank = 1 ; //跟ROOT下的第一层节点
4198+ //该node权重占总权重256的百分之多少呢
41164199 node -> rel_weight = (1.0 / 256 ) * node -> weight ;
41174200
41184201 children = & h2c -> dependencies ;
@@ -4152,6 +4235,7 @@ ngx_http_v2_set_dependency(ngx_http_v2_connection_t *h2c,
41524235 }
41534236
41544237 node -> rank = parent -> rank + 1 ;
4238+ //占整个父节点权重的百分比,例如父节点权重比为0.5,本节点weight为128,则本节点真实权重为0.5*0.5也就是0.25
41554239 node -> rel_weight = (parent -> rel_weight / 256 ) * node -> weight ;
41564240
41574241 if (parent -> stream == NULL ) {
@@ -4162,23 +4246,49 @@ ngx_http_v2_set_dependency(ngx_http_v2_connection_t *h2c,
41624246 children = & parent -> children ;
41634247 }
41644248
4249+ /*
4250+ 一旦设置独家专属标志(exclusive flag)将为现有依赖插入一个水平的依赖关系,其父级流只能被插入的新流所依赖。比如流D设置专属标志并依赖于流A:
4251+ A
4252+ A |
4253+ / \ ==> D
4254+ B C / \
4255+ B C
4256+ */
41654257 if (exclusive ) {
41664258 ngx_queue_add (& node -> children , children );
41674259 ngx_queue_init (children );
41684260 }
41694261
4170- if (node -> parent != NULL ) {
4262+ if (node -> parent != NULL ) { //之前node依赖A,现在改为依赖D了,则先清除依赖关系
41714263 ngx_queue_remove (& node -> queue );
41724264 }
41734265
4266+ //把children(也就是父节点的children节点)指向node节点,如果有多个node依赖parent节点,则这多个node节点通过queue连接在一起,如下图:
4267+ /*
4268+ parent
4269+ |
4270+ |children
4271+ |
4272+ | queue queue
4273+ nodeC--------nodeB-------nodeA (A先依赖parent,过后B又依赖parent,过后C又依赖parent)
4274+ */
41744275 ngx_queue_insert_tail (children , & node -> queue );
41754276
4176- node -> parent = parent ;
4277+ node -> parent = parent ; //指定父节点
41774278
4178- ngx_http_v2_node_children_update (node );
4279+ ngx_http_v2_node_children_update (node ); //例如上面exclusive置1的时候,就需要从新计算D下面B C的真实权重
41794280}
41804281
4181-
4282+ /*
4283+ children权重更新,例如如下情况:
4284+
4285+ 一旦设置独家专属标志(exclusive flag)将为现有依赖插入一个水平的依赖关系,其父级流只能被插入的新流所依赖。比如流D设置专属标志并依赖于流A:
4286+ A
4287+ A |
4288+ / \ ==> D
4289+ B C / \
4290+ B C
4291+ */
41824292static void
41834293ngx_http_v2_node_children_update (ngx_http_v2_node_t * node )
41844294{
0 commit comments