HTTP协议
HTTP
传输过程
HTTP 要传送一条报文时,会以流的形式将报文数据的内容通过一条打开的 TCP 连
接按序传输。TCP 收到数据流之后,会将数据流砍成被称作段的小数据块,并将段
封装在 IP 分组中,通过因特网进行传输(参见图 4-4)。所有这些工作都是由 TCP/
IP 软件来处理的,HTTP 什么都看不到。
每个 TCP 段都是由 IP 分组承载,从一个 IP 地址发送到另一个 IP 地址的。每个 IP
分组中都包括:
- 一个 IP 分组首部(通常为 20 字节);
- 一个 TCP 段首部(通常为 20 字节);
- 一个 TCP 数据块(0 个或多个字节)。
IP 首部包含了源和目的 IP 地址、长度和其他一些标记。TCP 段的首部包含了 TCP 端口号、TCP 控制标记,以及用于数据排序和完整性检查的一些数字值。
过程
从 Web 服务器等待连接开始。客户端根据 URL 判定出 IP地址和端口号,并建立一条到服务器的 TCP 连接。建立连接可能要花费一些时间,时间长短取决于服务器距离的远近、服务器的负载情况,以及因特网的拥挤程度。一旦建立了连接,客户端就会发送 HTTP 请求,服务器则会读取请求。一旦服务器获取了整条请求报文,就会对请求进行处理,执行所请求的动作,并将数据写回客户端。客户端读取数据,并对响应数据进行处理。
分析 HTTP 事务的延时
HTTP 事务的时延有以下几种主要原因。
- 客户端首先需要根据 URI 确定 Web 服务器的 IP 地址和端口号。如果最近没有对
URI 中的主机名进行访问,通过 DNS 解析系统将 URI 中的主机名转换成一个 IP 地址可能要花费数十秒的时间 (幸运的是,大多数 HTTP 客户端都有一个小的 DNS 缓存,用来保存近期所访问站点的 IP 地址。如果已经在本地“缓存”(记录)了 IP 地址,查询就可以立即完成。因为大多数 Web 浏览器浏览的都是少数常用站点,所以通常都可以很快地将主机名解析出来)。
- 接下来,客户端会向服务器发送一条 TCP 连接请求,并等待服务器回送一个请
求接受应答。每条新的 TCP 连接都会有连接建立时延。这个值通常最多只有一
两秒钟,但如果有数百个 HTTP 事务的话,这个值会快速地叠加上去。
- 一旦连接建立起来了,客户端就会通过新建立的 TCP 管道来发送 HTTP 请求。
数据到达时,Web 服务器会从 TCP 连接中读取请求报文,并对请求进行处理。因特网传输请求报文,以及服务器处理请求报文都需要时间。
- 然后,Web 服务器会回送 HTTP 响应,这也需要花费时间。
这些 TCP 网络时延的大小取决于硬件速度、网络和服务器的负载,请求和响应报文
的尺寸,以及客户端和服务器之间的距离。TCP 协议的技术复杂性也会对时延产生
巨大的影响。
一些会对 HTTP 产生影响的、最常见的 TCP 相关时延
其中包括:
- TCP 连接建立握手;
- TCP 慢启动拥塞控制;
TCP 数据传输的性能还取决于 TCP 连接的使用期(age)。TCP 连接会随着时间进行
自我“调谐”,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移
提高传输的速度。这种调谐被称为 TCP 慢启动(slow start),用于防止因特网的突
然过载和拥塞。
- 数据聚集的 Nagle 算法;
- 用于捎带确认的 TCP 延迟确认算法;
每个 TCP 段都有一个序列号和数据完整性校验和。每个段的接收者收到完好的段
时,都会向发送者回送小的确认分组。如果发送者没有在指定的窗口时间内收到确
认信息,发送者就认为分组已被破坏或损毁,并重发数据。
- TIME_WAIT 时延和端口耗尽。
HTTP连接处理
并行连接
HTTP 允许客户端打开多条连接,并行地执行多个 HTTP 事务。例如,并行加载了四幅嵌入式图片,每个事务都有自己的 TCP 连接。
持久连接
避免了大量并行连接的建立。因为,一个web页面上的大部分内嵌图片一般都来自与同一个web站点。所以HTTP/1.1允许HTTP设备在事务结束之后将TCP连接保持在打开状态,以便为未来的HTTP请求重用现存的连接。在事务处理结束之后仍然保持在打开状态的TCP连接被称为持久连接,非持久连接会在每个事务结束之后关闭。
Keep-Alive HTTP/1.0+
keep-alive请求发出后,client 和 server并不应定会同意进行keep-alive回话。他们可以在任意时刻关闭空心啊的keep-alive连接,并可随意限制keep-alive连接所处理的事务数量。这是keep-alive的互操作性
persistent connection HTTP/1.1
HTTP/1.1逐渐停职了对keep-alive的支持,用persistent connection取代了它,而且持久连接在默认情况下时激活的。除非特别指明,否则HTTP/1.1假定所有连接都是持久的。要在事务处理结束之后将连接关闭,HTTP/1.1应用程序必须想报文种显式的添加Connection:close首部,不然这个连接就仍保持在打开状态。
管道化连接
HTTP/1.1允许在持久连接上可选的使用请求管道,这是在持久连接上的进一步性能优化。在响应到达之前,可以讲多余的请求放入队列中,当第一条请求到达时就可以发送第二条请求了,而不用再等到响应到达client。
复用的连接(实验阶段)
在非正常关闭时重试请求。
Web服务器
流程
- 建立连接
如果客户端已经打开了一条到服务器的持久连接,可以用这条连接发送他的请求;否则,客户端要打开一条新的到服务器的连接。Web服务器建立连接时会判断连接的另一端时哪个客户端,从TCP连接中将IP解析出来。用来做监视连接上数据传输的准备,Web服务器可以随意拒绝或立即关闭任意一条连接,因为有些客户端IP地址或主机名时未认证的,或者因为他是已知恶意客户端等原因关闭连接。
- 接收请求
解析请求报文,在这个过程中,Web服务器会不定期地从网络上接收输入数据。网络连接可能随时都会出现延迟。Web服务器需要讲部分报文数据临时存储在内存种,直到收到足以进行解析的数据并理解其意义为止。
高性能的Web服务器可以同事支持数千条连接,这和Web服务器的结构有关。
单线程Web Server一次只能处理一个请求,直到完成为止,这样结构易于实现,但是性能不高。
多进程及多线程Web Sever可以同时处理请求。可以根据需要创建或者预先穿件一些线程/进程。然而这样,会在进程或线程数量的增多消耗大量的系统资源,因此一般都会对Web服务器的进程/线程最大数量进行限制。
复用I/OWeb Server在这种结构种中,要同时监视所有连接上的活动。当连接的状态发生变化时,就对那条连接进行少量的处理,处理结束后,将连接返回到开放连接列表种,等带下一次状态变化。只有在有事可做时才会对连接进行处理,在空闲连接上等待时并不会绑定线程和进程。
复用的多线程Web Server是将多线程和复用的功能结合在一起,以利于多个CPU。性能最高。
- 处理请求
- 访问资源
- 构建响应
- 发送响应
注意对持久连接的处理,要正确计算Content-Length首部,这样客户端才能知道响应什么时候结束。
- 记录事务处理过程,将与已完成事务有关的内容记录在一个日志文件中