Skip to content

Commit 4e2d72a

Browse files
author
yazhou.yang
committed
nginx http2 analyze
1 parent 92c61bb commit 4e2d72a

File tree

12 files changed

+82
-25
lines changed

12 files changed

+82
-25
lines changed

README.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,20 @@ nginx的以下功能模块的相关代码已经阅读,并对其源码及相关
144144
热启动reload、优雅退出quit、热升级代码分析注释
145145
subrequest重新分析注释
146146

147-
17.2.20
147+
17.3.15
148148
path http2代码到nginx-1.9.2
149-
nginx ssl tls握手协商流程分析
149+
nginx http2数据读取过程分析,ssl tls握手协商流程分析
150150
http2初始流程、setting帧处理过程、连接序言、header帧处理流程、HPACK实现方法分析、完善理解HTTP2调用过程的必要打印。
151151

152-
152+
17.3.21
153+
HTTP2 header帧处理流程、stream建立过程、伪request结构处理过程分析
154+
HTTP2 header帧处理完成后与NGINX phase框架衔接过程分析
155+
HTTP2 报文输出过程与nginx框架结合流程分析,DATA帧输出流程分析
156+
多sream同时请求,多流交互情况下DATA帧发送过程分析
157+
158+
159+
?????
160+
NGINX不支持PUSH、做反向代理情况下和后端为什么还是走HTTP1.X协议?
153161

154162

155163
===================================
@@ -159,6 +167,7 @@ nginx的以下功能模块的相关代码已经阅读,并对其源码及相关
159167
如果发往后端服务器数据大小很大,可能需要多次write,这时候会由write timeout来判断出后端出现问题。但是如果发往后端数据长度小,则不会添加write定时器,而是通过
160168
写定时器超时来判断,这样不能立刻判断出后端异常,因为读写定时器默认都是60s,参考ngx_http_upstream_send_request,
161169
2.[限流不准确分析](https://github.com/alibaba/tengine/issues/855)<br />
170+
3.
162171

163172

164173

35.1 KB
Loading
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
server {
2+
listen 443 ssl http2;
3+
ssl_certificate /usr/local/nginx/openssl-key/xx.crt;
4+
ssl_certificate_key /usr/local/nginx/openssl-key/xx.key;
5+
location / {
6+
proxy_pass http://106.186.112.116:80/$request_uri;
7+
}
8+
}
50.1 KB
Binary file not shown.
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
HPACK��ȫ����:http://www.jianshu.com/p/f44b930cfcac
22
HPACK https://imququ.com/post/header-compression-in-http2.html
3-
ʹ�� nghttp2 ���� HTTP/2 ���� https://imququ.com/post/intro-to-nghttp2.html
3+
ʹ�� nghttp2 ���� HTTP/2 ���� https://imququ.com/post/intro-to-nghttp2.html
4+
NGINX HTTP2�ٷ�˵��:https://www.nginx.com/blog/http2-r7/
5+
Rules of Thumb for HTTP/2 Push:https://docs.google.com/document/d/1K0NykTXBbbbTlv60t5MyJvXjqKGsCVNYHyLEXIxYMv0/edit#

nginx-1.9.2/objs/nginx

-15 Bytes
Binary file not shown.

nginx-1.9.2/src/event/ngx_event_openssl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1506,7 +1506,7 @@ ngx_ssl_write_handler(ngx_event_t *wev)
15061506
* Besides for protocols such as HTTP it is possible to always buffer
15071507
* the output to decrease a SSL overhead some more.
15081508
*/
1509-
1509+
//发送in链中的数据到c,如果发送in没有全部发送成功,则剩余的部分数据通过in返回
15101510
ngx_chain_t *
15111511
ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
15121512
{

nginx-1.9.2/src/http/modules/ngx_http_proxy_module.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2621,8 +2621,7 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
26212621
ngx_log_debugall(r->connection->log, 0,
26222622
"upstream header recv ok, u->keepalive:%d", keepalive_t);
26232623

2624-
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2625-
"yang test .... body:%*s", (size_t) (r->upstream->buffer.last - r->upstream->buffer.pos), r->upstream->buffer.pos);
2624+
//ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "yang test .... body:%*s", (size_t) (r->upstream->buffer.last - r->upstream->buffer.pos), r->upstream->buffer.pos);
26262625
return NGX_OK;
26272626
}
26282627

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

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,11 @@ ngx_http_v2_write_handler(ngx_event_t *wev)
454454
}
455455

456456
/*
457+
EADER帧发送流程:ngx_http_v2_filter_send->ngx_http_v2_send_output_queue
458+
DATA帧发送流程:ngx_http_v2_send_chain->ngx_http_v2_send_output_queue
459+
一次发送不完(例如协议栈写满返回AGAIN)则下次通过ngx_http_v2_write_handler->ngx_http_v2_send_output_queue再次发送
460+
461+
例如通过同一个connect来下载两个文件,则2个文件的相关信息会被组成一个一个交替的帧挂载到该链表上,通过该函数进行交替发送
457462
发送队列last_out中的数据
458463
*/
459464
ngx_int_t
@@ -481,6 +486,7 @@ ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c)
481486
cl = NULL;
482487
out = NULL;
483488

489+
//从输出队列取出来连接到cl链中
484490
for (frame = h2c->last_out; frame; frame = fn) {
485491
frame->last->next = cl;
486492
cl = frame->first;
@@ -496,7 +502,7 @@ ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c)
496502
}
497503

498504
/* 如果启用了ssl,则发送和接收数据在ngx_ssl_recv ngx_ssl_write ngx_ssl_recv_chain ngx_ssl_send_chain */
499-
cl = c->send_chain(c, cl, 0);
505+
cl = c->send_chain(c, cl, 0); //发送cl链中的数据,如果cl链中数据没有发送完成,则这部分没有发送完成的数据还保存在cl链中
500506

501507
if (cl == NGX_CHAIN_ERROR) {
502508
goto error;
@@ -559,6 +565,7 @@ ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c)
559565
for ( /* void */ ; out; out = fn) {
560566
fn = out->next;
561567

568+
/* 一般HEADER帧ngx_http_v2_headers_frame_handler DATA帧handler为ngx_http_v2_data_frame_handler */
562569
if (out->handler(h2c, out) != NGX_OK) {
563570
out->blocked = 1;
564571
break;
@@ -578,7 +585,7 @@ ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c)
578585
frame = out;
579586
}
580587

581-
/* */
588+
/* 把该函数没有发送完成的帧重新加入到last_out链表 */
582589
h2c->last_out = frame;
583590

584591
return NGX_OK;
@@ -2805,7 +2812,6 @@ ngx_http_v2_frame_handler(ngx_http_v2_connection_t *h2c,
28052812
return NGX_OK;
28062813
}
28072814

2808-
28092815
static ngx_http_v2_stream_t *
28102816
ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c)
28112817
{
@@ -2889,6 +2895,7 @@ ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c)
28892895
return NULL;
28902896
}
28912897

2898+
ngx_str_set(&r->http_protocol, "HTTP/2.0");
28922899
r->http_version = NGX_HTTP_VERSION_20;
28932900
r->valid_location = 1;
28942901

@@ -3154,6 +3161,7 @@ ngx_http_v2_pseudo_header(ngx_http_request_t *r, ngx_http_v2_header_t *header)
31543161
return ngx_http_v2_parse_method(r, header);
31553162
}
31563163

3164+
//取值只能为http或者https
31573165
if (ngx_memcmp(header->name.data, "scheme", sizeof("scheme") - 1)
31583166
== 0)
31593167
{
@@ -3564,7 +3572,7 @@ ngx_http_v2_construct_cookie_header(ngx_http_request_t *r)
35643572
static void
35653573
ngx_http_v2_run_request(ngx_http_request_t *r)
35663574
{
3567-
/* 组件HTTP2头部行,如GET /abc/xx.txt HTTP/2.0 */
3575+
/* 组HTTP2头部行,如GET /abc/xx.txt HTTP/2.0 */
35683576
if (ngx_http_v2_construct_request_line(r) != NGX_OK) {
35693577
return;
35703578
}

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

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,7 @@ Frame Types vs Flags and Stream ID
468468

469469
#define NGX_HTTP_V2_FRAME_HEADER_SIZE 9 //HTTP2头部长度9字节
470470

471+
/* 接收到对应帧的时候回调见ngx_http_v2_frame_states */
471472
/* frame types HTTP2报文头部的type字段 针对时间敏感的帧,比如RST_STREAM, WINDOW_UPDATE, PRIORITY,需要快速发送出去 */
472473
#define NGX_HTTP_V2_DATA_FRAME 0x0
473474
#define NGX_HTTP_V2_HEADERS_FRAME 0x1
@@ -592,7 +593,7 @@ struct ngx_http_v2_connection_s {
592593
ngx_connection_t *connection;//对应的客户端连接,赋值见ngx_http_v2_init
593594
ngx_http_connection_t *http_connection;
594595

595-
/* ngx_http_v2_create_stream中自增,表示创建的流的数量,ngx_http_v2_close_stream自减 */
596+
/* ngx_http_v2_create_stream中自增,表示创建的流的数量,当前正在使用的流数量,ngx_http_v2_close_stream自减 */
596597
ngx_uint_t processing;
597598

598599
/* 注意ngx_http_v2_connection_s的send_window、recv_window、init_window与ngx_http_v2_stream_s的send_window、recv_window的区别 */
@@ -611,16 +612,16 @@ struct ngx_http_v2_connection_s {
611612
ngx_http_v2_hpack_t hpack;
612613

613614
ngx_pool_t *pool;
614-
/* frame通过该free链表来实现重复利用,可以参考ngx_http_v2_get_frame */
615+
/* frame通过该free链表来实现重复利用,可以参考ngx_http_v2_get_frame ngx_http_v2_frame_handler*/
615616
ngx_http_v2_out_frame_t *free_frames;
616617
/* 创建空间和赋值见ngx_http_v2_create_stream,根据客户端连接伪造的一个连接 */
617618
ngx_connection_t *free_fake_connections;
618619

619620
/* ngx_http_v2_node_t类型的数组指针,ngx_http_v2_init中创建空间和赋值,真正的ngx_http_v2_node_t赋值见ngx_http_v2_get_node_by_id */
620621
ngx_http_v2_node_t **streams_index;
621622
/* 在ngx_http_v2_queue_blocked_frame中把帧加入该链表,在ngx_http_v2_send_output_queue中发送队列中的数据 */
622-
ngx_http_v2_out_frame_t *last_out;
623-
623+
//例如通过同一个connect来下载两个文件,则2个文件的相关信息会被组成一个一个交替的帧挂载到该链表上进行交替发送
624+
ngx_http_v2_out_frame_t *last_out; /* http2 header帧和data帧都挂载到该链表中 */
624625
ngx_queue_t posted;
625626
ngx_queue_t dependencies;
626627
/* 队列成员为ngx_http_v2_node_t,赋值见ngx_http_v2_state_priority */
@@ -702,21 +703,24 @@ struct ngx_http_v2_stream_s {
702703

703704

704705
/* 创建空间和赋值见ngx_http_v2_send_settings,对应一种setting、HEADER等帧,每个帧对应一个该结构,最终加入ngx_http_v2_connection_t->last_out */
705-
struct ngx_http_v2_out_frame_s {
706+
struct ngx_http_v2_out_frame_s {//该结构stream->free_frames会进行重复利用
706707
ngx_http_v2_out_frame_t *next;
707708
ngx_chain_t *first;
708709
ngx_chain_t *last;
709710

710711
/*
711712
赋值:ngx_http_v2_settings_frame_handler ngx_http_v2_data_frame_handler ngx_http_v2_headers_frame_handler ngx_http_v2_frame_handler
712713
执行在ngx_http_v2_send_output_queue
713-
*/
714+
*/ //每个帧发送到对端成功后都会调用对应的handler
714715
ngx_int_t (*handler)(ngx_http_v2_connection_t *h2c,
715716
ngx_http_v2_out_frame_t *frame);
716717

717718
ngx_http_v2_stream_t *stream;
718719
size_t length;
719720

721+
/* 说明该帧在ngx_http_v2_send_output_queue调用的时候还没有发送出去,当数据发送出去后ngx_http_v2_out_frame_t会被
722+
stream->free_frames回收,这时候还是为1,下次get重复利用的时候就是0了
723+
*/
720724
unsigned blocked:1;
721725
unsigned fin:1;
722726
};
@@ -746,6 +750,7 @@ ngx_http_v2_queue_frame(ngx_http_v2_connection_t *h2c,
746750
*out = frame;
747751
}
748752

753+
//例如通过同一个connect来下载两个文件,则2个文件的相关信息(包括header帧和DATA帧)会被组成一个一个交替的帧挂载到该链表上进行交替发送
749754
/* 添加frame到last_out链表 */
750755
static ngx_inline void
751756
ngx_http_v2_queue_blocked_frame(ngx_http_v2_connection_t *h2c,

0 commit comments

Comments
 (0)