什么是HTTP协议?
HTTP协议是可靠的数据传输无状态协议,它属于应用层。HTTP把联网的细节都交给了通用、可靠的因特网传输协议TCP/IP。
只要建立了TCP连接,客户端和服务端之间的报文交换就不会丢失、不会被破坏。
为什么说HTTP是无状态的?
无状态的意思就是说每一次请求都与之前的请求无关,每一次请求包含的cookie、url、首部等有状态的数据都是一个完整的文档,不需要请求其上下文。
缺点就是每一次请求都需要重新发送状态,也就是说服务器不会主动保存之前的状态。一般如果想让应用有状态,会在http协议中加上cookie、session等缓存机制。
HTTP连接
在HTTP客户端向服务器发送报文之前,需要用IP地址和端口号在客户端和服务器之间建立一条TCP/IP连接。一般浏览器通过HTTP获取服务器中某个HTML资源过程如下:
- 浏览器从URL中解析出服务器的主机名;
- 浏览器通过DNS将主机名转换成服务器的IP地址;
- 浏览器将端口号(默认80)从URL中解析出来;
- 浏览器建立一条与Web服务器的TCP连接;
- 浏览器向服务器发送一条HTTP请求报文;
- 服务器向浏览器回送一条HTTP响应报文;
- 关闭连接,浏览器渲染文档并显示;
当然上述只是简单的描述,其中还有很多具体的步骤我们以后再说。
TCP连接
我们知道,HTTP协议依赖TCP/IP来进行通信。那么什么是TCP/IP呢?TCP/IP是全球计算机网络都在使用的一种常用的分组交换网络分层协议集。
TCP数据传输
- TCP为HTTP提供了一条可靠的比特传输管道。从TCP连接一端填入的字节会从另一端以原有的顺序正确地传送出来。
传输的数据是通过称为IP分组的小数据块来发送的。每个IP分组都包括:
- 一个IP分组首部(通常为20字节);
- 一个TCP段首部(通常为20字节);
- 一个TCP数据块(0个或多个字节);
- TCP连接通过4个值来识别:<源IP地址、源端口号、目的IP地址、目的端口号>,这4个值一起唯一地定义了一条连接。
TCP性能考虑
HTTP事务的时延:一般影响HTTP事务的时延主要有以下几点原因:
- 解析主机名:首次解析主机名需要通过DNS解析系统将URI中的主机名转换成一个IP地址,这可能要花费不少时间;如果没有缓存DNS,则以后的每次访问都需要重新解析DNS,带来巨大时间消耗。
- 发送TCP连接请求:每条新的TCP连接都会有连接建立时延,如果同时发送上百条连接,则所耗时间大大增加。
- 连接建立完后,客户端会通过新建立的TCP管道发送HTTP请求报文,服务器接收到报文后会对请求进行处理。这其中传输报文、处理报文都需要花费时间;服务器处理完报文后回送响应报文也需要传输时间
总的来说,硬件速度、客户端和服务器的负载量、客户端与服务器之间的距离、报文的大小等会对时延产生巨大影响。
TCP握手时延:TCP连接需要经过三次握手,一般步骤如下:
- 请求新的TCP连接,客户端向服务器发送一个TCP分组(通常40~60字节)。分组中设置了一个特殊的SYN标记,说明是连接请求。
- 服务器接受连接,对连接参数进行计算,向客户端回送一个TCP分组,分组中的SYN和ACK标记都被置位,告诉客户端请求已接受。
- 客户端向服务器回送一条确认信息的TCP分组,包含ACK标记,告诉服务器连接已成功建立。(现代的TCP栈允许客户端在这个确认分组中发送数据)
- TCP延迟确认:TCP有自己的确认机制来确保数据成功传输。每个TCP段都有一个序列号和数据完整性校验和。一般确认报文很小,所以TCP允许将确认报文和输出的数据分组组合在一起传输,这里就引入了一个“延迟确认”算法。“延迟确认”算法会在一个特定的窗口时间(通常100~200ms)内将输出确认存放在缓存区,以寻找能携带它的输出数据分组,如果在特定时间内没有输出数据分组,就将确认信息放在单独的分组进行传输。但这样一般会引入比较大的时延,所以不一定完全要用延迟算法。
- TCP慢启动:为了防止网络负载过大和阻塞,TCP连接会采取慢启动,也就是说一开始限制连接的最大速度,随着数据的传输成功,慢慢增大传输速度。例如建立一个新连接,先发送一个分组,等确认成功后,才可以发送两个分组,等都被确认后,就可以发送四个分组,以此类推。。。
由于这种特性,新连接的传输速度会比已经交换过一定量数据的、“已调谐”连接慢一些。 - Nagle算法问题:由于TCP允许将任意尺寸数据放入TCP栈中传输,所以如果TCP发送了大量包含少量数据的分组,则网络性能就会很低,浪费很多流量。Nagle算法就是用来解决此类问题。该算法试图在发送一个分组之前,将大量TCP数据绑定在一起来提高网络效率。
Nagle算法希望发送全尺寸(LAN上最大尺寸的分组大约1500字节,Internet上是几百字节)的段。如果其他分组任然在传输过程中,就将那部分数据缓存起来,只有当挂起分组被确认,或者缓存中积累了足够发送一个全尺寸的分组后才将缓存的数据传输出去。这样就会带来性能问题,如果HTTP报文很小,一直达不到全尺寸,就会一直在等待那些永远不会到来的数据而引起时延;而且Nagle算法会阻止数据传输直到有确认分组抵达,但确认分组自身又有延迟。
所以HTTP应用程序可以通过设置参数TCP_NODELAY来禁用Nagle算法,但是这样要确保会向TCP写入大块数据,而避免传输数量多的小分组。
- TIME_WAIT、端口耗尽:TCP关闭某个连接时,会在内存中维护一个小的控制块,用来记录最近所关闭连接的IP地址和端口号,通常维持2MSL(2分钟)左右。这样可以防止在两分钟内创建、关闭并重新创建两个具有相同IP地址和端口号的连接。但这样就会限制可用端口号的数量,降低连接率。要确保不会遇到TIME_WAIT端口耗尽问题,可以增加客户端负载生成机器的数量,或者确保客户端和服务器在循环使用几个虚拟IP地址以增加更多的连接组合。
评论 (0)