理解TCP之Keepalive
理解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要从短连接到长连接最简单演变需要做如下改进:
- client发出的HTTP请求头需要增加Connection:keep-alive字段
- 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的更多相关文章
- 理解HTTP之keep-alive
理解HTTP之keep-alive 在前面一篇文章中讲了TCP的keepalive,这篇文章再讲讲HTTP层面keep-alive.两种keepalive在拼写上面就是不一样的,只是发音一样,于是乎大 ...
- 理解HTTP之keep-alive(转)
理解HTTP之keep-alive 在前面一篇文章中讲了TCP的keepalive,这篇文章再讲讲HTTP层面keep-alive.两种keepalive在拼写上面就是不一样的,只是发音一样,于是乎大 ...
- 浅谈Http长连接和Keep-Alive以及Tcp的Keepalive
原文:https://blog.csdn.net/weixin_37672169/article/details/80283935 Keep-Alive模式: 我们知道Http协议采用“请求-应答”模 ...
- 结合Wireshark捕获分组深入理解TCP/IP协议栈
摘要: 本文剖析了浏览器输入URL到整个页面显示的整个过程,以百度首页为例,结合Wireshark俘获分组进行详细分析整个过程,从而更好地了解TCP/IP协议栈. 一.俘获分组 1.1 准 ...
- TCP的keepalive和应用层的heart
从长链接说起 TCP是长链接的,也就是说连接建立后,及时数年没有通信连接仍然存在.这样做的好处是:免去了DNS解析的时间,连接建立等时间,大大加快了请求的速度,同时也有利于接受服务器的实时消息.但前提 ...
- 简单理解TCP/IP协议
一.什么是TCP/IP TCP/IP是一个协议族,是因为TCP/IP协议包括TCP.IP.UDP.ICMP.RIP.TELNETFTP.SMTP.ARP.TFTP等许多协议,这些协议一起称为TCP/I ...
- 如何理解TCP的三次握手协议?
• TCP是一个面向链接的协议,任何一个面向连接的协议,我们都可以将其类比为我们最熟悉的打电话模型. 如何类比呢?我们可以从建立和销毁两个阶段分别来看这件事情. 建立连接阶段 首先,我们来看看TCP中 ...
- 深入理解TCP建立和关闭连接
建立连接: 理解:窗口和滑动窗口TCP的流量控制TCP使用窗口机制进行流量控制什么是窗口?连接建立时,各端分配一块缓冲区用来存储接收的数据,并将缓冲区的尺寸发送给另一端 接收方发送的确认信息中包含了自 ...
- TCP 的 Keepalive 和 HTTP 的 Keep-Alive 是一个东西吗?
大家好,我是小林. TCP 的 Keepalive 和 HTTP 的 Keep-Alive 是一个东西吗? 这是个好问题,应该有不少人都会搞混,因为这两个东西看上去太像了,很容易误以为是同一个东西. ...
随机推荐
- oracle进阶之connect by笔记
本博客是自己在学习和工作途中的积累与总结,仅供自己参考,也欢迎大家转载,转载时请注明出处. http://www.cnblogs.com/king-xg/p/6794562.html 如果觉得对您有帮 ...
- CCF2016093炉石传说(C语言版)
问题描述 <炉石传说:魔兽英雄传>(Hearthstone: Heroes of Warcraft,简称炉石传说)是暴雪娱乐开发的一款集换式卡牌游戏(如下图所示).游戏在一个战斗棋盘上进行 ...
- 使用mybatis-spring-boot-starter如何打印sql语句
只需要将接口文件的日志设置为debug即可. 例如你的mapper接口所在的文件夹是 com.demo.mapper 那么在application.properties配置文件中添加 logging. ...
- 利用js键盘事件制作会移动效果
会移动的方块 描述 按键盘上的方向键方块会移动,按住alt键和方向键进行大幅度移动 <!DOCTYPE html> <html lang="en"> < ...
- jmeter参数化、添加变量、生成随机数和导入csv文件数据
Remarks:本次使用jmeter版本为4.0 以下数据都在必应中演示: 添加普通变量 1.添加 User Defined Variables(用户自定义变量) 2.设置变量 3.使用变量 4.查看 ...
- 胖哈勃杯Pwn400、Pwn500详解
概述 这次的胖哈博杯我出了Pwn400.Pwn500两道题目,这里讲一下出题和解题的思路.我个人感觉前两年的Pwn题更多的是考察单一的利用技巧,比我这有个洞怎么利用它拿到权限.但是我研究了一些最近的题 ...
- 《剑指offer》-青蛙跳台阶II
一只青蛙一次可以跳上1级台阶,也可以跳上2级--它也可以跳上n级.求该青蛙跳上一个n级的台阶总共有多少种跳法. 其实题目很水...就是一个等比数列通项公式嘛 f(0)=1 f(1)=1 f(n)=f( ...
- Spring之hello world(Spring入门)
spring各个版本中: 在3.0以下的版本,源码有spring中相关的所有包[spring功能 + 依赖包] 如2.5版本: 在3.0以上的版本,源码中只有spring的核心功能包[没有依赖包] ( ...
- java里获取uuid
//获取32位uuid工具类 ,此类事java自带的,不需要导包public static String get32UUID() { String uuid = UUID.randomUUID().t ...
- 【Java】 剑指offer(28) 对称的二叉树
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 请实现一个函数,用来判断一棵二叉树是不是对称的.如果一棵二叉树和它 ...