关于HTTP协议中的保持连接
缘起
中午在群里讨论,用ab
测试 一台只提供静态文件服务, 不与其他任何系统交互的时候,为什么也会产生大量的TIME WAIT
状态的。
首先,我们可以简单的理解,在TCP连接的两端,谁主动断开连接(先发送FIN
包),谁进入TIME WAIT
,谁被动断开连接(后发送FIN
包),谁进入CLOSE WAIT
状态。
那么,由此可以推断,在这个场景中,server是主动断开连接的一方,那么server为什么会主动断开呢, 这就涉及到HTTP里关于keepalive的内容了。
我们常常听说keepalive
能提高webserver的性能, 但是为什么呢? 这里暂且不解释,说完下面的内容,就清楚了。
分析
在HTTP协议中, 除了需要服务器支持并打开keepalive之外, 还有一个重要的请求头Connection
需要注意。
我们来看下面一个请求:
GET /? HTTP/1.1
Accept: */*
Cache-Control: no-cache
Connection: close
Host: 127.0.0.1
User-Agent: Apache-HttpClient/4.3.2 (java 1.5)
Accept-Encoding: gzip,deflate
这是我通过Idea 的REST Client 插件发送的一个请求, 我们看到 Connection
头的值是close
,抓包看一下请求过程
可以看到, 在server响应完成后, 发送了FIN
包, 主动断开连接, 这很好理解。
在来看一个请求:
GET /? HTTP/1.1
Accept: */*
Cache-Control: no-cache
Connection: keep-alive
Keep-Alive: 5
Host: 127.0.0.1
User-Agent: Apache-HttpClient/4.3.2 (java 1.5)
Accept-Encoding: gzip,deflate
可以看到, 这个请求里, Connection
的值变成了keep-alive
, 并且多了一个Keep-Alive
头,值为5。再抓包看看这次请求:
可以看到, server在响应完成后,并没有发送FIN
包关闭连接, 而是一段时间后,客户端发送FIN
包,关闭连接, 如果你看第二列, time会发现,正好是大约5秒后,客户端发送了FIN
包, 这个数值正好是 Keep-Alive
头的值。事实上,Keep-Alive
头的语义就是客户端保持连接多少秒。
以上的测试, server配的keepalive都是65s
, 我们来把它0, 再来测试一遍看看。
客户端Connection
头为close
的情况:
客户端Connection
为keep-alive
, Keep-Alive
为5
的情况
可以看到,server主动断开连接。
最后一个场景, server配置keepalive
为3, client Connection
为keep-alive
, Keep-Alive
为5
的情况
可以看到,请求结束大约3
秒后(主要时间戳),server发送FIN
主动断开连接。
结论
说了这么多,是时候总结一下了,关于keepalive主要有以下几点:
-
Connection
头控制客户端是否开启,close
不开启,keep-alive
开启 -
Keep-Alive
头控制客户端保持连接的时间 - 在开启
keepalive
的时候, 谁先到保持连接的时间,谁先发FIN
包,主动关闭连接。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Spring-IOC-创建Bean-属性填充
- vi与vim如何修改tab为4个空格方法示例
- Linux使用Crontab定时访问某个路由地址的方法
- jmeter 在linux服务器的安装和运行教程图解
- Linux中改变文件权限的chmod命令详析
- Ubuntu常用指令及用法详解
- Linux 系统使用私钥登录的教程详解
- Ubuntu如何轻松编译openJDK详解
- 详解Linux下Tomcat开启查看GC信息
- Centos7.4 zabbix3.4.7源码安装的方法步骤
- CentOS7环境搭建python3以及与python2实现共存的方法
- centos7.0安装离线JDK1.8方法详解
- ubuntu中swap(虚拟内存)设置方法
- 详解Linux监控重要进程的实现方法
- CentOS环境下安装Redis3.0及phpredis扩展测试示例