长连接优点
HTTP为什么要开启长连接呢?
主要是为了节省建立的时间,请求可以复用同一条TCP链路,不用重复进行三握+四挥
如果没有长连接,每次请求都做三握+四挥
如果有长链接,在一个 TCP 连接中可以持续发送多份数据而不会断开连接,即请求可以复用TCP链路
长连接缺点
长连接不是万能的,存在队头阻塞
队头阻塞
如果仅仅使用一个连接,它需要发起请求、等待响应,之后才能发起下一个请求。
在请求应答过程中,如果出现任何状况,剩下所有的工作都会被阻塞在那次请求应答之后。
这就是“队头阻塞”,它会阻碍网络传输和Web页面渲染,直至失去响应。
为了防止这种问题,现代浏览器会针对单个域名开启6个连接,通过各个连接分别发送请求。
它实现了某种程度上的并行,但是每个连接仍会受到“队头阻塞”的影响
pipline
为解决队头阻塞,提出 pipline 方案
虽然在一个 tcp 链路中实现多个 http 并发,但因为该方案有缺陷,大部分浏览器默认关闭 pipeline
其一:是因为返回时会阻塞,谁先发送,谁先返回,顺序绝对不能乱
其二:只能是请求(get、head等)才能应用 pipeline
HTTP开启长连接
C
开启 HTTP 长连接,对前端很简单,方式如下:
协议 开启 关闭
HTTP1.0 Connection: keep-alive 默认
HTTP1.1 默认 Connection: close
S
Keep-Alive 需要服务端支持:
Httpd 守护进程,如 nginx 需要设置 keepalive_timeout
keepalive_timout 时间值:一个 http 产生的 tcp 连接在传送完最后一个响应后,还需要 hold 住 keepalive_timeout 秒后,才开始关闭连接
- keepalive_timeout=0:建立tcp连接 + 传送http请求 + 执行时间 + 传送http响应 + 关闭tcp连接 + 2MSL
- keepalive_timeout>0:建立tcp连接 + (最后一个响应时间 – 第一个请求时间) + 关闭tcp连接 + 2MSL
代码
HTTP1.1 开启 keepalive 长连接
// clients
func doGet(client *http.Client, url string, id int) {
resp, err := client.Get