[转帖]HTTP 的 keep-alive 和 chunk

http,keep,alive,chunk · 浏览次数 : 0

小编点评

**问题一:http的keep-alive和tcp的keepalive,有没有关系?** 答案是没有关系。 **问题二: TCP 的 keepalive 是什么意思,用途是什么?** TCP 的 keepalive 是一个机制,用于探测连接的死活,以及保持连接的活动。当一条 TCP 没有数据流通时,定时器开始活动,直到为 0 时,服务端这边会向客户端这边发送一个不带数据的 ACK 请求,如果收到回复,则表明这条连接是活的。如果没有收到回复,服务器端这边会发送多次 ACK,到一定次数之后还没有收到回复,就认定这条连接已经死掉了,直接关闭掉。 **问题三:HTTP的keep-alive是什么意思?用途是什么?** HTTP 的 keep-alive 是一个机制,用于在处理完一次 HTTP 事务之后,不关闭连接,用于下一次的 HTTP 事务。 **问题四:重用tcp连接 zuży那么多口水来解释呢?** 重用 TCP 连接比建立新连接要复杂一些,因为需要处理连接状态、校验数据、处理错误等。由于 HTTP 在持久化连接上区分两次 HTTP 事务的方式有两种,一个是通过 Content-Length 这个 header 来判断主体内容的长度,另一个是通过 chunk 来实现。当使用传输编码 Transfer-Encoding:chunked 时,接收端需要根据长度值读取数据,以及最后一个长度为 0 的块来判定接收结束。

正文

https://zhuanlan.zhihu.com/p/35568646

 

最近在阅读Go语言的Http库,以前总觉得这些基础代码,会很高大上很难懂,所以连去挑战下的勇气都没有。工作了几年之后,总算是有信心来挑战下了,不过目前进展还是很慢,说明目前的实力还不足。

本来想着用Java照着Go的代码仿写一份的,写着写着,就感到越来越难了。因为对整体代码都没有认知,就直接开始,一边阅读代码,一边仿写,加上Go和Java都不能说熟到遂心应手的程度,写着写着,就变成纯粹用Java模拟Go的语法了。遇到愈来愈多无法直接模仿的代码和类库,仿写也就进行不下去了。

虽然是放弃了仿写,不过我还是觉得用另一门语言照着实现一份代码,进步会非常快。譬如之前自己写代码,就很少会用那么复杂的多线程同步。

虽说放弃了仿写,但是单纯的阅读代码,其实并没有什么意义,或者说,会觉得自己看懂了就一带而过了,事后也就忘了。于是决定重操旧业,边阅读代码,边写文章。

写文章让我心中倍感踏实,每次学点什么,如果我没有写成一篇总结文章,就觉得自己并没有学到,感觉也记不住,很快就忘了,譬如TCP的基础知识,我已经阅读过两本书了,现在还是很不懂。

如果后面自己还能坚持的话,我还是打算用Java把这份Go的http库给仿写出来。

下面开始正文:

首先第一个问题,http的keep-alive和tcp的keepalive,有没有关系?

答案自然是没有关系。

问题二: TCP 的 keepalive 是什么意思,用途是什么?

TCP实现中包含一个keepalive定时器,当一条TCP没有数据流通时,定时器开始活动,直至为0时,服务端这边会向客户端这边发送一个不带数据的ACK请求,如果收到回复,则表明这条连接是活的。如果没有收到回复,服务器端这边会发送多次ack,到一定次数之后还没有收到回复,就认定这条连接已经死掉了,直接关闭掉。

具体作用就两个:探测连接的死活,以及保持连接的活动,保证不被防火墙之类的服务杀死(比如防火墙认为一条连接超过一定时间没有活动就要杀死掉,只要设置keepalive短于这个时间即可保活)。

Linux的TCP默认是没有开启keepalive的,因为大量的keepalive会浪费服务器资源。keepalive也可以在代码里建立TCP的时候开启,具体可以看这篇 TCP KeepAlive How To

问题三:HTTP的keep-alive是什么意思?用途是什么?

http的keep-alive其实是HTTP 1.0的产物,HTTP 1.1 之后,所有的http连接都默认是keep-alive的, 所谓的keep-alive,就是一条tcp连接,在处理完一次http事务之后,不关闭此tcp连接,用于下一次的http事务。譬如客户端和 服务器端建立一个连接,用于客户端向服务器端发送图片。如果不是keep-alive的http连接,那么在发送完一张图片之后,就关闭 掉这条连接了。而keep-alive的连接,则在发送完一张图片后,放回到连接池里,客户端要再次发送图片到服务器了,就直接从连接池拿出这条连接,而不是从零开始建立一条连接(http的底层是TCP,从零建立一条tcp连接,三次握手,慢启动等导致非常耗时)。

对于HTTP 1.1,并不需要指定keep-alive了。但是,假如你希望这条http连接完成一次事务之后(发送完这张图片),就关闭这条连接(实际就是关闭底层的tcp连接),那么可以在http请求的头部加入 Connection: close,而且可以在任何时候加入这个头部,比如发第一张图片不加,第二张图片加这个头部。

不发送 Connection:close, 并不意味着服务器承诺永远不关闭这条连接,实际上空闲超过一定时间一定数量之后,就会关闭掉。

问题四:重用tcp连接不是很正常的事情么,为什么http的keep-alive会有那么复杂的历史,要废那么多口水来解释呢?

重用连接之后,对于一次http事务是否完成了,就需要稍微复杂点的判断了。同一条tcp通道,你灌进来一张图片的数据之后又再灌进来一张图片,对于另一端的服务,它如何确定第一张图片的数据读到哪个位置就完成了呢?如果连接不是keep-alive的,那么只要把tcp通道里的所有数据都读完就可以了。

目前http在持久化连接上,区分两次http事务的方式有两种,一个是通过Content-Length这个header来判断主体内容的长度,比如我通过http请求发送了一个 Hello, 那么这个Content-Length就是5。读完之后,就是下次事务的开始了。另一种则是通过chunk, 即分块编码来实现。

如果Content-Length设置错误或者没有设置,那么接收端就应该质疑这个长度的正确性。用Go的http库测试了下,发现用户是 无法设置Content-Length这个header的。

但有一种情况可以不设置Content-Length,即使用传输编码Transfer-Encoding:chunked的时候,历史上Transfer-Encoding支持 多种编码,但是目前最新的规范里,只支持chunked编码,即分块编码一种。

当在报文的头部加入Transfer-Encoding:chunked的时候,报文就会被分块,每块包含长度值,数据,以及分隔符CRLF,最后一个块长度必须为0,如下图:

 

 

接收端就可以根据长度值读取数据,以及最后一个长度为0的块来判定接收结束。

分块传输有许多的用途和好处,譬如有些内容是持续产生的,事先并不知道长度是多长,用分块传输就可以边传输边读取新数据发送了。还有一些大文件,如果先将整个文件压缩好了再传输,对用户很不友好(感觉等待的时间长),就可以采用分块传输和内容 编码结合(Content-Encoding),一块块的压缩,一块块的传输。

与[转帖]HTTP 的 keep-alive 和 chunk相似的内容:

[转帖]HTTP 的 keep-alive 和 chunk

https://zhuanlan.zhihu.com/p/35568646 最近在阅读Go语言的Http库,以前总觉得这些基础代码,会很高大上很难懂,所以连去挑战下的勇气都没有。工作了几年之后,总算是有信心来挑战下了,不过目前进展还是很慢,说明目前的实力还不足。 本来想着用Java照着Go的代码仿写

[转帖]聊一聊nginx中KeepAlive的设置

文章目录 问题分析为什么要有KeepAlive?TCP KeepAlive和HTTP的Keep-Alive是一样的吗?Nginx的TCP KeepAlive如何设置Apache中KeepAlive和KeepAliveTimeOut参考资料 问题 之前工作中遇到一个KeepAlive的问题,现在把它记

[转帖]Nginx Http 模块中 Upstream 的 keepalive 参数配置注意事项

Nginx Http 模块中 Upstream 的 keepalive 参数配置注意事项 摘要 在高并发环境下 keepalive 参数配置不当容易产生大量 TIME_WAIT,导致端口耗尽,服务异常。 keepalive 值应该大于等于 upstream 中 server 的数量。(建议是 ser

[转帖]Nginx超时timeout 设置

Nginx 超时配置,连接时间过长直接关闭连接,显示timeout http { #每个 TCP 连接最多可以保持多长时间 keepalive_timeout 60; #客户端向服务端发送一个完整的 request header client_header_timeout 10; #客户端发送服务端

[转帖]HTTP与HTTPS超文本传输协议的区别是什么

https://www.likecs.com/show-308649882.html 随着越来越多的网站使用HTTPS加密,现在HTTPS的使用已经成了硬性要求了。虽然说https是http的安全版,但两者还是有不少区别的。本文从https、http的概念和原理入手,讲解他们的不同,让读者朋友能够真

[转帖]QUIC & HTTP/3 Support:主流浏览器和服务端对 HTTP/3 的支持情况(2021年12月更新)

https://sysin.org/blog/quic-http3-support/ 1. 相关概念 1.1 TLSv1.3 TLS 1.3 由 IETF 于 2018 年 8 月正式发布。 SSL 即 Secure Sockets Layer 安全套接字层。TLS 即 Transport Laye

[转帖]http请求详解

1. 简介 HTTP(HyperText Transfer Protocol,超文本传输协议)是一套计算机通过网络进行通信的规则。计算机专家设计出HTTP,使HTTP客户(如Web浏览器)能够从HTTP服务器(Web服务器)请求信息和服务,HTTP目前协议的版本是1.1。HTTP遵循请求(Reque

[转帖]HTTP状态码、请求方法、响应头信息

https://www.cnblogs.com/pachongshangdexuebi/p/5279608.html HTTP状态码 当浏览者访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头(server he

[转帖]【基础】HTTP、TCP/IP 协议的原理及应用

https://juejin.cn/post/6844903938232156167 前言 本文将持续记录笔者在学习过程中掌握的一些 HTTP 、TCP/IP 的原理,以及这些网络通信技术的一些应用场景,文章会保持更新,相当于对这块知识的一个总结和归纳。有不正确之处欢迎指出,及时改正~ 纲要 访问网

[转帖]HTTP压测工具wrk使用指南

https://www.cnblogs.com/liufarui/p/11063328.html 【前言】 笔者使用wrk,是为了测试nginx转发报文的时候set_proxy_header规则,然后发现wrk尤其的好用,所以在这里写下来,以后用的时候还能查一查。 【安装】 不讲概念了,直接讲安装。