HTTP协议报文优化分析

HTTP协议作为互联网中陈旧而又炙手可热的规范,http报文结构及性能优化是使用时关注的重点。先从报文入手再进一步了解http优化方案。

HTTP URL结构

HTTP URL结构分为三部分:方案/scheme(http),服务器位置/host(www.domain.com),资源路径/path(/aaa/bbb/cccc.html)。

HTTP报文

HTTP报文是HTTP应用程序之间传送的数据块,发送者与接收者之间存在一种报文流动的概念,发送者为上游(upstream),接收者为下游(downstream),所有报文都向下游流动。(这里并无Server与Client的概念)。

HTTP报文组成结构

起始行(start line)、首部/报文头(header)、主体(body)

HTTP报文分类

HTTP报文分为两类,请求报文与响应报文,两者报文结构相同,只是起始行的语法有所不同。

HTTP请求报文结构

HTTP请求报文结构起始行

HTTP请求报文起始行由三部分组成,method(请求方式)、request-url(资源标识)、version(http版本,用于表明客户端使用哪种http),也被称之为请求行。

HTTP响应报文结构

HTTP响应报文起始行

HTTP响应报文起始行由三部分构成,version、status(状态码)、reason-phrase(状态的可读版本,便于阅读),也被称之为响应行。

HTTP报文头部(header)

HTTP报文头由零个或多个键值对(key:value)组成。

键值对

HTTP头部键值对除了HTTP规范中所定义的,可以根据实际需求自定义。

--http-*格式:key:val 空格或tab

HTTP报文分界线

http报文头(header)与主体(body)之间的分界线为一个CRLF(空行)。

HTTP报文主体

主体(body)包含一个由任意数据组成的数据块。

HTTP Method概要

HTTP的 GET、HEAD方法

GET、HEAD被定义成安全的方法。

因此具体的实现不应有修改服务端内容的行为,两者都是向服务发起请求,GET要求返回资源,HEAD只返回首部(header),两者的header在实现上应保持一致。

HTTP的PUT、POST方法

PUT、POST被定义成向服务端写入数据。

PUT语义要求服务器以URL作为标识(命名),以主体(boby)作为内容,在服务器上创建一个新文档(已存在则覆盖),POST则通常以form表单的形式把数据送到服务器,由服务器决定数据的去向。

HTTP TRACE方法

TRACE被用于跟踪请求过程中,各个环节对HTTP原始请求所作的修改,把修改后的内容(服务器收到的内容的精确副本)作为响应的主体(boby)返回,http trace方法通常出现在”闭环“诊断的应用场景中。

HTTP OPTIONS方法

OPTIONS用于让服务器告知能够支持哪些method。

HTTP DELETE方法

DELETE请求服务器删除指定的资源,但HTTP规范允许服务器以不通知客户端的方式撤销请求。

HTTP响应状态码说明

W3C HTTP状态码说明

http信息提示码

100~199已定义范围100~101,信息提示。

http成功状态码

200~299已定义范围200~206,成功。

HTTP 200 请求已成功,200响应中发送的有效负载取决于请求方法。

HTTP 201 Created,成功状态响应代码,请求已成功并已创建资源,在发回该响应之前有效地创建新资源,并且在消息正文中返回新资源。

HTTP 202 该请求已被接受处理,但处理尚未完成。

HTTP 203非权威信息,实体标头中返回的元信息不是从源服务器可用的权威集,而是从本地或第三方副本收集的。

HTTP 204无内容,服务器已完成请求但不需要返回实体主体,并且可能希望返回更新的元信息。

HTTP 205重置内容,服务器已完成请求,用户代理应该重置文档视图。

HTTP 206部分内容,服务器已完成对资源的部分GET请求。

http重定向码

300~399已定义范围300~305,重定向。

HTTP 301重定向-永久性移走。

HTTP 302重定向-代表暂时性转移(Temporarily Moved )。

HTTP 303和302状态码功能相同,但303只能用get方法获取资源。

HTTP 304 Not Modified客户端重定向响应代码表示不需要重新传输所请求的资源。

HTTP 305 CheckUpDown,Web服务器认为URL应该重定向到另一个URL - “代理”。

http客户端错误码

400~499已定义范围400~415,客户端错误。

HTTP 401 错误 - 未授权: (Unauthorized) 。

HTTP 403 Forbidden - 拒绝访问。

HTTP 404 Web服务器找不到所请求的文件或脚本,检查URL以确保路径正确。

HTTP 405 不允许此方法,对于请求所标识的资源,不允许使用请求行中所指定的方法。

HTTP 406 不可接受,此请求所标识的资源只能生成内容特征为“不可接受”的响应实体。

HTTP 407 需要代理身份验证,必须验证此代理服务器。

HTTP 412 在服务器上测试前提条件时,部分请求标题字段中所给定的前提条件评估为FALSE。

HTTP 414 Request-URI 太长,服务器拒绝服务此请求。

http服务器错误码

500~599已定义范围500~505,服务器错误。

HTTP 500 服务器内部错误,一般程序上为程序错误。

HTTP 501 未实现 (Not implemented),Web 服务器不理解或不支持的HTTP请求。

HTTP 502 Bad Gateway,大多是上游服务器和网关/代理以不同的协议交换数据(不一致)。

HTTP 503 Service Unavailable,服务不可用,暂时超载或临时维护,Web 服务器目前无法处理 HTTP 请求。

HTTP 504  Gateway timeout,网关超时,意味着上游服务器已关闭(不响应网关 / 代理)。

HTTP 505 HTTP Version Not Supported,服务器不支持或拒绝支持请求消息中使用的HTTP版本。

TCP/IP协议

HTTP over TCP over IP

HTTP传送一条报文,以流的方式把数据传给TCP/IP程序,TCP/IP会将数据流分成”段“,并将”段“封装在IP分组中,通过因特网进行传输。

IP分组

每个TCP”段“都由IP分组承载,从一个IP地址发送到另一个IP地址。每个IP分组中都包括:

IP分组头部:源、目标IP地址,长度和其他标记。

TCP段头部:TCP端口号、TCP控制标记、数据排序和用于完整性检查的数值。

TCP数据块。

TCP连接标识的构成

在操作系统中,一个TCP连接标识由四部分数据构成。

源IP地址、源端口号、目标IP地址、目标端口号

以上四部分构成一条唯一的TCP连接标识,以文件的形式存放在操作系统中。

TCP连接握手的3个步骤

1、客户端向服务器发送一个TCP分组,分组中设置一个特殊的SYN标记。

2、服务器接受连接,对一些连接参数进行计算,并向客户端回送一个TCP分组,分组中包含被置位的SYN和ACK。

3、客户端向服务器回送一条确认信息,通知连接已建立(通常可以在这次确认请求中稍带业务数据)。

HTTP性能影响的焦点

TCP连接握手

小的HTTP事务可能会在建立TCP连接上花费50%的时间,如何重用现存连接,来减小这种时延造成的影响,成为优化这一问题的焦点。

延迟确认

由于网络传输不能保证数据的到达率,TCP需要自己实现数据完整性及传输成功的校验,因此需要有确认报文,由于确认报文本身很小,所以为了有效利用网络,可以在发送确认信息时“稍带”同向输出数据,为了能够等到同向输出数据,确认信息通常会延迟100~200毫秒后发出。合理调整延迟确认算法成为改善这一问题的焦点。

TCP慢启动

TCP数据传输为了防止网络突然过载和拥堵,不会一次将所有分组都发送出去,在发送一个分组成功确认后,接着会发送两个分组,成功后会发送四个分组,以此类推的把数据分组传送出去。

由于新连接会比已经交换过一定数量数据的连接慢,所以,可以使用工具重用现存连接来提升传输性能,HTTP“持久连接”就属于这个范畴。

数据聚集的Nagle算法

应用程序可以将任意大小的数据放入TCP栈中,而每个TCP“段”的头部和标记部分至少占40个字节,如果用TCP大量发送包含少量数据的分组,是很不经济的,所以引入了Nagle算法。

Nagle算法在等待上一个分组的确认信息的过程中,把新进的多个数据分组重新“打包”成更大的数据分组等待发送,当上一个数据分组的确认信息回来时,或等待发送的数据分组是一个全尺寸(大约1500字节)的数据分组时,才会发起新一轮的数据发送。Nagle算法引发了两个新的性能问题。

其一:当小报文无法填满一个数据分组时,而确认信息又没有回来,这时会一直等待额外数据的到来。

其二:与延迟确认机制的冲突,在Nagle算法收到确认信息之前,不会发送新的数据分组的场景中,由于确认信息会被延迟确认算法延迟100~200毫秒,所以加剧了性能问题。如果确保向TCP写入的都是大块的数据,禁用Nagle算法会提高性能。

TIME_WAIT时延和端口耗尽

当TCP连接关闭时,内存中仍然会为这个连接短暂维护一个小的控制块,这一算法可以防止在两分钟内同一个客户端创建、关闭、重新创建TCP连接所带来的问题。

这里引发的一个思考,在服务端可以创建多少个TCP连接标识文件?这个受限于操作系统中一个目录允许的文件数

另一问题则是如果客户端在作基准测试,客户端所在机器的会因为需要创建唯一性的TCP连接而导致端口被耗尽。在这些场景下考虑TIME_WAIT是有意义的。

HTTP Header中的Connection属性

当客户端与服务器端之间存在一些中间实体(如:代理服务器、高速缓存等),客户端/服务器在header中发送的key:value如果不想被最终的接收端看到,可以通过Connection属性指定具体key进行剔除。

如:Server发送的header中包含[a:1 b:3 c:5 Connection:a,c],经过代理服务器转发到Client时,Client收到的header中只包含[b:3],a、c被Connection指定所剔除。

Connection键值对在现代的代理服务器中是一个不会被连续转发的存在,A发送请求给B(代理服务器),B收到header中包含Connection的键值对,再转发给C时,这个Connection的键值对会从header中剔除。

在header中不能被代理转发或作为响应“头部”内容的包括:

Proxy-Authenticate、Proxy-Connection、Transfer-Encoding、Upgrade

关于HTTP协议简要概述先探讨于此,后续会有更多关于HTTP协议的内容。