理解HTTP之keep-alive

在前面一篇文章中讲了TCP的keepalive,这篇文章再讲讲HTTP层面keep-alive。两种keepalive在拼写上面就是不一样的,只是发音一样,于是乎大家就都迷茫了。HTTP层面的keep-alive是我们接触比较多的,也是大家平时口头上的"keepalive"。下面我们就来谈谈HTTP的keep-alive

短连接&长连接&并行连接

再说keep-alive之前,先说说HTTP的短连接&长连接。

  • 短连接

    所谓短连接,就是每次请求一个资源就建立连接,请求完成后连接立马关闭。每次请求都经过“创建tcp连接->请求资源->响应资源->释放连接”这样的过程

  • 长连接

    所谓长连接(persistent connection),就是只建立一次连接,多次资源请求都复用该连接,完成后关闭。要请求一个页面上的十张图,只需要建立一次tcp连接,然后依次请求十张图,等待资源响应,释放连接。

  • 并行连接

    所谓并行连接(multiple connections),其实就是并发的短连接。

keep-alive

具体client和server要从短连接到长连接最简单演变需要做如下改进:

  1. client发出的HTTP请求头需要增加Connection:keep-alive字段
  2. Web-Server端要能识别Connection:keep-alive字段,并且在http的response里指定Connection:keep-alive字段,告诉client,我能提供keep-alive服务,并且"应允"client我暂时不会关闭socket连接

在HTTP/1.0里,为了实现client到web-server能支持长连接,必须在HTTP请求头里显示指定

Connection:keep-alive

在HTTP/1.1里,就默认是开启了keep-alive,要关闭keep-alive需要在HTTP请求头里显示指定

Connection:close

现在大多数浏览器都默认是使用HTTP/1.1,所以keep-alive都是默认打开的。一旦client和server达成协议,那么长连接就建立好了。

接下来client就给server发送http请求,继续上面的例子:请求十张图片。如果每次"请求->响应"都是独立的,那还好,10张图片的内容都是独立的。但是如果pipeline模式,上一个请求还没响应,下一个请求就发出,这样并发地发出10个请求,对于10个response client要怎么区分呢?而HTTP协议又是没有办法区分的,所以这种情况下必须要求server端地响应是顺序的,通过Conten-Length区分每次请求,这还只是针对静态资源,那对于动态资源无法预知页面大小的情况呢?我还没有深入研究,可以查看https://www.byvoid.com/blog/http-keep-alive-header

另外注意: 指定keep-alive是一种client和server端尽可能需要满足的约定,client和server可以在任意时刻都关闭keep-alive,彼此都不应该受影响。

Nginx keepa-alive配置

具体到Nginx的HTTP层的keepalive配置有

  • keepalive_timeout
    Syntax: keepalive_timeout timeout [header_timeout];
Default: keepalive_timeout 75s;
Context: http, server, location

The first parameter sets a timeout during which a keep-alive client connection will stay open on the server side. The zero value disables keep-alive client connections. The optional second parameter sets a value in the “Keep-Alive: timeout=time” response header field. Two parameters may differ.

  • keepalive_requests
    Syntax: keepalive_requests number;
Default: keepalive_requests 100;
Context: http, server, location

Sets the maximum number of requests that can be served through one keep-alive connection. After the maximum number of requests are made, the connection is closed.

可以看看Nginx的关于 keepalive_timeout 是实现


./src/http/ngx_http_request.c static void
ngx_http_finalize_connection(ngx_http_request_t *r){
...
if (!ngx_terminate
&& !ngx_exiting
&& r->keepalive
&& clcf->keepalive_timeout > 0)
{
ngx_http_set_keepalive(r);
return;
}
...
} static void
ngx_http_set_keepalive(ngx_http_request_t *r){ //如果发现是pipeline请求,判断条件是缓存区里有N和N+1个请求同时存在
if (b->pos < b->last) { /* the pipelined request */
}
// 本次请求已经结束,开始释放request对象资源
r->keepalive = 0; ngx_http_free_request(r, 0); c->data = hc; // 如果尝试读取keep-alive的socket返回值不对,可能是客户端close了。那么就关闭socket
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_close_connection(c);
return;
} //开始正式处理pipeline
... rev->handler = ngx_http_keepalive_handler;
...
// 设置了一个定时器,触发时间是keepalive_timeout的设置
ngx_add_timer(rev, clcf->keepalive_timeout); ... } static void
ngx_http_keepalive_handler(ngx_event_t *rev){ // 发现超时则关闭socket
if (rev->timedout || c->close) {
ngx_http_close_connection(c);
return;
} // 读取keep-alive设置从socket
n = c->recv(c, b->last, size);
if (n == NGX_AGAIN) {
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_close_connection(c);
return;
}
...
} //此处尚有疑惑?
ngx_reusable_connection(c, 0); c->data = ngx_http_create_request(c);
// 删除定时器
ngx_del_timer(rev);
// 重新开始处理请求
rev->handler = ngx_http_process_request_line;
ngx_http_process_request_line(rev);
}

参考资料

from: http://www.firefoxbug.com/index.php/archives/2805/

理解TCP之Keepalive的更多相关文章

  1. 理解HTTP之keep-alive

    理解HTTP之keep-alive 在前面一篇文章中讲了TCP的keepalive,这篇文章再讲讲HTTP层面keep-alive.两种keepalive在拼写上面就是不一样的,只是发音一样,于是乎大 ...

  2. 理解HTTP之keep-alive(转)

    理解HTTP之keep-alive 在前面一篇文章中讲了TCP的keepalive,这篇文章再讲讲HTTP层面keep-alive.两种keepalive在拼写上面就是不一样的,只是发音一样,于是乎大 ...

  3. 浅谈Http长连接和Keep-Alive以及Tcp的Keepalive

    原文:https://blog.csdn.net/weixin_37672169/article/details/80283935 Keep-Alive模式: 我们知道Http协议采用“请求-应答”模 ...

  4. 结合Wireshark捕获分组深入理解TCP/IP协议栈

    摘要:     本文剖析了浏览器输入URL到整个页面显示的整个过程,以百度首页为例,结合Wireshark俘获分组进行详细分析整个过程,从而更好地了解TCP/IP协议栈.   一.俘获分组 1.1 准 ...

  5. TCP的keepalive和应用层的heart

    从长链接说起 TCP是长链接的,也就是说连接建立后,及时数年没有通信连接仍然存在.这样做的好处是:免去了DNS解析的时间,连接建立等时间,大大加快了请求的速度,同时也有利于接受服务器的实时消息.但前提 ...

  6. 简单理解TCP/IP协议

    一.什么是TCP/IP TCP/IP是一个协议族,是因为TCP/IP协议包括TCP.IP.UDP.ICMP.RIP.TELNETFTP.SMTP.ARP.TFTP等许多协议,这些协议一起称为TCP/I ...

  7. 如何理解TCP的三次握手协议?

    • TCP是一个面向链接的协议,任何一个面向连接的协议,我们都可以将其类比为我们最熟悉的打电话模型. 如何类比呢?我们可以从建立和销毁两个阶段分别来看这件事情. 建立连接阶段 首先,我们来看看TCP中 ...

  8. 深入理解TCP建立和关闭连接

    建立连接: 理解:窗口和滑动窗口TCP的流量控制TCP使用窗口机制进行流量控制什么是窗口?连接建立时,各端分配一块缓冲区用来存储接收的数据,并将缓冲区的尺寸发送给另一端 接收方发送的确认信息中包含了自 ...

  9. TCP 的 Keepalive 和 HTTP 的 Keep-Alive 是一个东西吗?

    大家好,我是小林. TCP 的 Keepalive 和 HTTP 的 Keep-Alive 是一个东西吗? 这是个好问题,应该有不少人都会搞混,因为这两个东西看上去太像了,很容易误以为是同一个东西. ...

随机推荐

  1. 深入理解JS中的变量及变量作用域

    JS的变量有两种,“全局变量”和“局部变量”. “全局变量”声明在函数外部,可供所有函数使用,(全局变量属于window)而“局部变量”声明在函数体内部,只能在定义该变量的函数体内使用. 1.全局变量 ...

  2. php中常用的正则表达式函数

    php中常用的正则表达式函数 * preg_match() * preg_match_all() * preg_replace() * preg_filter() * preg_grep() * pr ...

  3. django----数据库表设计

    设计表时注意的几点: 1. nid = models.AutoField(primary_key=True)        #如果不指定django会默认加上id的 nid = models.BigA ...

  4. python 全栈开发,Day125(HTML5+ 初识,HBuilder,夜神模拟器,Webview)

    昨日内容回顾 1.增删改查: 增: db.collections.insert({a:1}) // 官方不推荐了 db.collections.insertMany([{a:1},{b:1}]) in ...

  5. 大数据统计分析平台之二、ElasticSearch 6.2.1的安装与使用

    # 下载文件cd /usr/local/software wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch ...

  6. JQuery框架2.位置属性|筛选方法|事件

    1.位置属性 jquery的css position获取匹配元素相对父元素的偏移位置:offset获取匹配元素在当前视口的相对偏移,返回的对象包含两个整型属性:top 和 left $("p ...

  7. 【Java】 剑指offer(48) 最长不含重复字符的子字符串

    本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字 ...

  8. 024 IDEA不能新建spring下的配置文件xml

    这个问题以前就遇到过,一直懒得解决,现在必须要用了,解决了一下,发现网上的解决方式果然不错. 1.现象 2.解决方式 需要添加一下spring context的依赖即可

  9. 063 日志分析(pv  uv  登录人数  游客人数  平均访问时间  二跳率  独立IP)

    1.需求分析 分析指标 pv uv 登录人数 游客人数 平均访问时间 二跳率 独立IP 2.使用的日志(一号店),会话信息 3.创建数据库 4.创建源表,存储源数据 5.创建我们需要的use表 6.创 ...

  10. QT5入门之23 -QT串口编程(转)

    QT5入门之23 -QT串口编程   QT5有专门的串口类: QSerialPort:提供访问串口的功能 QSerialPortInfo:提供系统中存在的串口的信息 具体使用方法: 1.在pro文件中 ...