HTTP协议的历史
HTTP(Hypertext Transfer Protocol 超级文本传输协议)是访问万维网的载体,也是与我们接触最密切的网络协议,REST API的概念就强依赖于HTTP协议。从之前的文章互联网协议概览可以看到,它位于应用层,基于TCP/IP协议做可靠的传输和路由,本身设计是为了文本以及多媒体内容的共享,后来随着Web技术的发展,HTTP也提供了诸如缓存、持久连接、代理、隧道、Cookie、安全认证等功能,并且随着富客户端化的发展,计算力从服务器迁移到了客户端,从而对HTTP有了更高的要求,HTTP2.0应运而生。
Internet以及HTTP的诞生
1) 1967年ACM提出构建连接计算机的小型网络——高级研究计划署网络(ARPANET),之后其成员开始研究各种连接、传输、可靠等需求,提于1973年提出了传输控制协议(TCP)的概念。
2)1977年,TCP分成两个协议:传输控制协议(TCP)和因特网协议(IP),IP负责处理数据报的路由选择,TCP负责高层次的功能,如分段、重组、检错。
3)之后美国出现各种网络出现,1981年CSNET-计算机科学网;1986年NSFNET-国家科学基金网络,连接美国5个超级计算机中心;1991年,IBM、Merit和Verizon搭建了高级网络服务网(ANSNET)。
4)Web是由欧洲原子核研究委员会(CERN)的Tim Berners-Lee发明的,他最初希望借助多文档之间关联形成的超文本,连接成可互相参阅的万维网(WWW)。借助HTML、HTTP和URL三项构建技术,1990年11月,CERN成功研发了世界上第一台Web服务器和Web浏览器。
HTTP协议版本
- HTTP/0.9,HTTP1991原型版本,只支持GET方法,不支持多媒体内容、各种HTTP首部,很快就被1.0取代了
- HTTP/1.0,1.0是第一个得到广泛使用的HTTP版本,添加了版本号、多媒体、各种首部等。使得Web页面包含生动图片和交互式表格。
- HTTP/1.0+,90年代中叶,很多流行的Web客户端和服务器向HTTP添加了各种特性,包括持久的keep-alive连接、虚拟主机支持,代理支持。
- HTTP/1.1,1999年HTTP/1.1发布,矫正HTTP设计中的结构性缺陷,性能优化,是目前正在使用的版本。
- HTTP/2.0,作为下一代HTTP协议,目前还在开发中,可见HTTP1.1在20年的发展中依然稳定。2010年Google发布SPDY,旨在解决HTTP的性能瓶颈,缩短Web页面加载时间。2011年WebSocket成为独立的协议标准,实现Web浏览器和Web服务器之间的全双工通信。HTTP2.0主要在压缩、多路复用、TLS义务化、协商、Pull/Push、流量控制、WebSocket等方面研究。
HTTP报文
HTTP报文由三部分组成:描述报文的起始行、包含属性的首部(header)、可选的数据主体(body)。而报文又可以分为两类:请求报文和响应报文。
起始行
所有HTTP报文都以一个起始行开始,请求报文起始行说明了要做些什么;响应报文起始行说明发生了什么。
请求行:方法 URL HTTP版本
响应行:HTTP版本 状态码 状态描述
常用的HTTP方法:
- GET,从服务器获取一份文档
- HEAD,只从服务器获取文档的首部
- POST,向服务器发送需要处理的数据
- PUT,将请求的主体部分存储在服务器上
- TRACE,对可能经过代理服务器传送的报文进行追踪
- OPTIONS,决定可以在服务器上执行哪些方法
- DELETE,从服务器删除一份文档
常见的状态码:
- 1XX:信息提示。100 Continue,客户端应用程序只有在避免向服务器发送一个服务器无法处理或使用的大实体时才应该使用100;101 Switching Protocols;
- 2XX:成功。200 OK;201 Created;202 Accepted,已接收但还未执行;
-
3XX:重定向。300 Multiple Choices;301 Moved Permanently;302 Found;303 See Other;307 Temporary Redirect
- 4XX:客户端错误。401 Unauthorized;404 Not Found;403 Forbidden;405 Method Not Allowed
- 5XX:服务端错误。500 Internal Server Error;501 Not Implemented;502 Bad Gateway;503 Service Unavailable;504 Gateway Timeout;505 HTTP Version Not Supported
首部
首部是报文中的附加信息,是一个键值对列表。通常根据规范分为几类:
- 通用首部:与报文相关的最基本的信息;如Connection,Date,MIME-Version,Update, Via。通用缓存首部 Cache-Control
- 请求首部:Client-IP,From,Host,Referer,User-Agent,Accept首部,Expect条件首部,Authorization,Cookie,Max-Forward,Proxy-Connection
- 响应首部:Age,Server,Proxy-Authenticate,Set-Cookie
- 实体首部:描述主体长度和内容;Allow,Location
- 扩展首部:规范中没有的首部
关于首部,需要和具体的如缓存、代理等功能结合理解。
连接管理
几乎所有的HTTP通信都是由TCP/IP承载,TCP协议保证数据的可靠性。
TCP连接
对于HTTP开发者来说,TCP/IP是透明的,但是理解连接的具体行为还是必要的,下图描述了Web浏览器通过TCP连接与Web服务器进行交互。
TCP协议段
操作系统提供了TCP套接字编程接口,这些API隐藏了所有底层网络协议的握手细节,以及TCP数据流和IP分组之间的分段和重装细节。
TCP性能考虑
HTTP事务的性能在很大程度上取决于底层TCP通道的性能,基于TCP的性能特点,可以更好地理解HTTP的连接优化特性。HTTP事务的时延主要有几个原因:
- 客户端根据URI确定IP地址和端口,如果没有本地缓存,需要通过DNS解析IP地址,可能需要数十秒。
- 建立TCP连接,可能1-2秒
- 发送HTTP请求
- Web服务器返回HTTP响应
TCP相关的时延主要包括:
1)TCP连接建立握手,小的HTTP事务可能会在TCP建立上花费超过50%时间,通过重用连接可以减小这种影响。
2)延迟确认,每个TCP段都有一个序列号和数据完整性校验和,通过确认机制确保数据没有损坏。延迟确认算法会在一个特定的窗口时间将输出确认放在缓冲区,以寻找能够捎带它的输出数据分组,如果那段时间没有其他输出分组,则单独发送确认信息。
2)TCP慢启动拥塞控制,TCP连接会随着时间进行自我协调,起初限制速度,当数据成功传输后,会提高传输速度,所以新连接的传输速度回慢一些。
3)数据聚集的Nagle算法,试图在发送一个分组前将大量TCP数据绑定在一起,以提高网络效率。该算法会导致小的HTTP报文等待额外数据产生时延;同时Nagle算法会阻止数据发送,直到有确认分组到达。可以通过设置TCP_NODELAY来禁用Nagle算法,但要确保会向TCP写入大块数据。
4)TIMS_WAIT时延和端口耗尽。当某个TCP端点关闭TCP连接时,会在内存维护一个小的控制块,记录最近关闭的IP地址和端口号,通常保存2分组左右,确保这段时间内不会创建具有相同地址和端口号的新连接。在进行性能测试的机器上,客户端每次连接到服务器上时都会使用新的端口连接到Server的80端口,以此来确保连接的唯一性,但是由于可用的端口有限(比如60000个),在2min内连接无法重用,所以连接率就在500次/秒,超过的话就会导致TIME_WAIT端口耗尽问题。
HTTP连接的处理
- 串行事务,每个请求都需要新建TCP连接,连接时延和慢启动时延会叠加起来;
- 并行连接不一定快,需要打开大量连接消耗内存资源,消耗客户端网络带宽,浏览器会对并行连接总数限制(通常是4个)。同时TCP慢启动的延迟依然存在。
- 持久连接允许HTTP事务处理结束后保持TCP打开,支持连接重用,可以避免建立连接的延迟和慢启动的拥塞延迟,从而更快地传输数据。
对比持久连接的两种类型:HTTP/1.0+ “keep-alive”连接和HTTP/1.1 “persistent”连接
Keep-alive:该首部只是请求将连接保持在活跃状态,客户端和服务端可以随时关闭空闲的Keep-alive连接。
限制和规则:
①必须客户端发送一个Connection:Keep-alive请求首部来激活Keep-alive连接;
②该首部必须随请求的报文一起发送;
③只有在确定实体主体部分大小的情况下,连接才能保持在打开状态;
④代理和网关必须执行Connection首部的规则;对于不认识Connection首部的哑代理来说,它只是进行转发但并不保持连接,所以第二次再请求的时候会被挂起。Netscape提出加入Proxy-Connection新首部,效果如下图所示,可以解决单个盲中继问题。
HTTP/1.1停止了对keep-alive连接的支持,而使用了一种持久连接的模型取代了它。
Persistent:该首部默认情况下是激活的,除非特别指明,否则HTTP/1.1假定所有连接都是持久的。
限制和规则:
① 如果需要在事务处理结束后将连接关闭,则应用程序必须向报文中显式的添加一个Connection-close首部;
② 只有当连接上所有报文都有正确的、自动以报文长度时,连接才能持久保持,Body长度与Content-Length一致;
③ 每个持久连接都只适用于一跳传输;
④ 应用程序可以在任意时刻关闭连接,但应该能够从异步关闭中恢复,重试这条请求;
⑤ 一个客户端对任何服务器或代理最多只能维护2条持久连接以防止服务器过载;
- 管道化连接
通过共享TCP连接发起并发的HTTP请求,这也是在持久连接的基础上对性能的一种优化。
原理:在响应到达前,将多条请求放入队列,在高延时网络条件下,可以降低网络环回时间,提高性能。
限制和规则:
① 如果HTTP客户端无法确认连接是持久的,就不应使用管道连接;
② 必须按照与请求相同的顺序回送HTTP响应;
③ 客户端必须做好连接会在任何时刻关闭的准备,以及重发所有未完成的管道化请求;
④ HTTP客户端不应用管道化的方式发送非幂等性请求(比如POST);
Web服务器
Web 服务器逻辑实现了 HTTP 协议、管理着 Web 资源,并负责提供 Web 服务器的管理功能。Web 服务器逻辑和操作系统共同负责管理 TCP 连接。底层操作系统负责管理底层计算机系统的硬件细节,并提供了 TCP/IP 网络支持、负责装载 Web 资源的文件系统以及控制当前计算活动的进程管理功能。
基本Web服务器请求的步骤
- 建立连接,如果已经打开了一条持久连接,则使用原来的连接,否则打开一条新的服务器连接。解析客户端IP,将新的连接加入到Web服务器连接列表中,监控数据传输。Web服务器可以随意拒绝或者立即关闭任意一条连接。服务器可以将客户端IP转换成主机名,称为反向DNS,但是会降低处理速度。此外还有一个IETF的ident协议可以找到client的用户名,支持该协议的客户端会监听TCP的113端口的ident请求。获得client用户名一般用于通用日志记录,可以禁用来提高效率。
- 接收请求报文,Web服务器会从网络连接中读取数据,并将请求报文中的内容解析出来。对于请求的处理,有四种服务器结构:单线程、多进程和多线程、复用IO和复用的多线程Web服务器。
-
处理请求,根据方法、资源、首部和可选的主体部分对请求进行处理;
-
对资源的映射和访问。文档的根目录(document root),将资源URI附加在根目录后面,但不要让用户退到根目录之外访问其余的文件系统。VirtualHost,一台服务器上可以托管不同的站点,可以配置虚拟主机,每个VirtualHost有单独的DocumentRoot。通常会将(/~)映射成用户的主目录。动态内容资源的映射,此时URI映射到可执行程序,提供动态资源。CGI是早期出现的一种简单、流行的服务端应用程序执行接口。
-
构建响应,Web服务器识别了资源并执行方法中的动作,最后返回响应报文,主要包括Content-Type,Content-Length 和报文主体。有时候会返回重定向响应。重定向响应由返回码 3XX 说明。Location 响应首部包含了内容的新地址或优选地址的 URI。
重定向
①永久删除的资源(301):资源移到新位置或重命名,重定向到新的URL,更新书签信息
②临时删除的资源(303、307):资源临时移到新位置或重命名,重定向到新的URL,不更新书签信息
③URL增强(303、307):服务器生成新的URL,重定向到新的URL,重新发起请求
④负载均衡(303、307):超载的服务器将请求重定向到负载不太重的服务器
⑤服务器关联(303、307):服务器将客户端重定向到包含到包含客户端信息的服务器
⑥规范目录名称:客户请求的URI不带尾部斜线的目录名,会重定向到带斜线的URI
-
发送响应,对于持久连接,发送完可能仍保持打开状态,要正确计算Content-Length首部,不然客户端无法知道响应什么时候结束;而非持久连接则要关闭自己的连接。
-
记录日志,事务结束时,Web服务器会在日志文件中添加一个条目描述已经执行的事务。
代理
Web上的代理服务器是代表客户端完成事务处理的中间人。单个客户端专用的代理成为私有代理,比如某些浏览器辅助产品;众多客户端共享的代理称为公共代理,比如高速缓存。
代理和网关的对比:严格的说,代理连接的是多个使用相同协议的应用程序,而网关连接的是多个不同协议的端点,网关扮演的是“协议转换”的角色。实际上两者的区别很模糊,商业化的代理服务器也会实现网关的功能来支持SSL安全协议、SOCKS防火墙、FTP访问以及基于Web的应用程序。
为什么使用代理
代理服务器可以实现各种时髦且有用的功能。它们可以改善安全性,提高性能,节省费用。
使用示例:
- 儿童过滤器,过滤成人内容;
- 文档访问控制,实现统一访问控制策略,创建审核跟踪机制;
- 安全防火墙,代理服务器会在网络中的单一安全节点上限制哪些应用层协议的数据可以流入或者流出一个组织,还可以消除病毒和hook程序;
- Web缓存,维护了常用文档的本地副本;
- 反向代理,一方面可以提高访问公共内容的性能,另一方面可以配合路由功能,创建按需复制内容的分布式网络;
- 内容路由器,根据因特网流量以及内容类型将请求导向特定的Web服务器;
- 转码器,代理服务器在将内容发送给客户端之前,可以修改内容的主体格式。
代理会去往何处
部署代理服务器的几种方式:
- 出口代理,将代理固定在本地网络的出口点,以便控制本地网络与大型因特网之间的流量;提供防火墙保护,降低带宽费用,儿童过滤。
- 入口代理,常被放在ISP访问点上,用来处理客户的聚合请求,ISP使用缓存代理来存储常用的文档副本,提高用户下载速度。
- 反向代理,通常被部署在网络边缘,在Web服务器之前,可以处理所有传送给Web服务器的请求,并只在必要时向Web服务器请求资源。
- 网络交换代理,可以将具有足够处理能力的代理放在网络之间的英特网对等交换点上,通过缓存来减轻因特网节点的拥塞,并对流量进行监视。
Proxy层次结构,下一个inbound代理(靠近服务器)被称为父代理,下一个outbound(靠近客户端)被称为子代理。代理的层次关系可以是动态的,比如:负载均衡,子代理根据父代理的负载选择父代理;选择地理位置附近的路由;协议、类型路由;基于订购的路由,例如转发到大型缓存上提高性能。
四种常见的方式将客户端流量导向代理:
- 修改客户端。浏览器手动和自动代理配置;
- 修改网络。依赖监视HTTP流量的交换设备及路由设备,在客户端不知情的情况下,将流量导入一个代理;
- 修改DNS命名空间,反向代理
- 修改Web服务器。返回HTTP重定向命令,将流量发送给代理
客户端的代理设置
1)手工配置
如果配置过的浏览器基础过大,需要更改时重新配置比较困难。
2)代理的自动配置(Proxy Auto-Configuration, PAC)
PAC文件是一些小型的JavaScript程序,可以在运行过程中计算代理设置。每个PAC文件必须定义一个FindProxyForURL(url, host)的函数,用来为每个URI计算代理服务器
function FindProxyForURL(url, host) {
if (url.substring(0,5) == "http:") {
return "PROXY http-proxy.mydomain.com:8080"; }
else if (url.substring(0,4) =="ftp:") {
return "PROXY ftp-proxy.mydomain.com:8080"; }
else {
return "DIRECT";
}
}
3)Web代理自动发现协议(Web Proxy Autodiscovery Protocol, WPAD)
WPAD协议算法会使用发现机制逐级上升策略自动为浏览器找到合适的PAC文件,WPAD会一个接一个对每种技术进行尝试知道成功。当前WPAD协议按顺序定义了下列技术:
- 动态主机配置协议(Dynamic Host Configuration Protocol,DHCP)
- 服务定位协议(Service Location Protocol, SLP)
- DNS知名主机名
- DNS SRV记录
- TXT记录中的DNS服务URI
在显式地配置客户端代理设置的情况下,如客户端会发送完整的URI,这样代理才能建立和服务器的连接。如果没有代理,则可以发送部分URI,因为服务器知道自己的主机名和端口。
追踪报文
Via首部字段列出了与报文途经的每个中间节点的相关信息,每经过一个节点,都必须要将这个中间节点添加到Via列表的末尾。Via首部字段用于记录报文的转发,诊断报文循环,标识请求、响应链上所有发送者的协议的能力。每个Via路标中最多包含4个组件:可选的协议名、必选额协议版本、必选的节点名和一个可选的描述注释。请求和响应报文中都要有Via首部,有些代理会为非HTTP协议的服务器提供网关的功能,Via首部可以记录这些协议转换。
Via = "Via" ":" 1#( waypoint )
waypoint = ( received-protocol received-by [ comment ] )
received-protocol = [ protocol-name "/" ] protocol-version
received-by = ( host [ ":" port ] ) | pseudonym
TRACE方法可以追踪代理链上传输的请求报文,观察流经了哪些代理,进行了什么修改。通常,不管中间插入了多少代理,TRACE报文都会沿着整条路径传到目的服务器。可以使用Max-Forwards(最大转发次数)首部来限制TRACE和OPTIONS请求所经过的代理跳数,在测试代理链是否在无限循环中转发报文,或者査看链中特定代理服务器效果时,是很有用的。如果收到的Max-Forwards值大于零,转发的报文中就必须包含一个更新的Max-Forwards字段,其值被减一。所有的代理和网关都应该支持Max-Forwards。可以用Max-Forwards来査看在代理链的任意一跳上接收到的请求。
代理认证
代理可以作为访问控制设备使用。HTTP定义了一种名为代理认证(proxy authentication)的机制,这种机制可以阻止对内容的请求,直到用户向代理提供了有效的访问权限证书为止。对受限内容的请求到达一台代理服务器时,代理服务器可以返回一个要求使用访问证书的407 Proxy Authorization Required状态码,以及一个用于描述怎样提供这些证书的Proxy-Authenticate首部字段。客户端收到407响应时,会尝试着从本地数据库中,或者通过提示用户来搜集所需要的证书。只要获得了证书,客户端就会重新发送请求,在Proxy-Authorization首部 字段中提供所要求的证书。如果证书有效,代理就会将原始请求沿着传输链路向下传送。否则,就发送另一条407应答。
代理必须对不认识的首部字段进行转发,而且必须维持同名首部字段的相对顺序。类似地,如果代理不熟悉某个方法,那么只要可能,就应该尝试着将报文转发到下一跳节点上去。
通过HTTP OPTIONS方法,客户端(或代理)可以发现Web服务器或者其上某个特定资源所支持的功能(比如,它们所支持的方法)。
请求服务器支持的所有方法
OPTIONS * HTTP/1.1
HTTP/1.1在响应中唯一指定的首部字段是Allow首部,这个首部用于描述服务器所支持的各种方法(或者服务器上的特定资源)。
Allow: GET, HEAD, PUT
缓存
Web缓存是可以自动保存常见文档副本的HTTP设备。当Web请求抵达缓存时,如果本地有“已缓存的”副本,就可以从本地存储设备而不是原始服务器中提取这个文档。
缓存有以下四个功能:缓存减少了冗余的数据传输,节省了网络费用;缓解了网络瓶颈的问题,不需要更多的带宽就能够更快地加载页面;降低了对原始服务器的要求,服务器可以更快地响应,避免过载的出现;降低了距离时延,因为从较远的地方加载页面会更慢一些。
命中(cache hit)与未命中(cache miss)
原始服务器的内容可能会发生变化,缓存要不时对其进行检测,称为HTTP再验证(revalidation)。如果再验证返回304 Not Modified,则缓存仍然有效称为再验证命中或者缓慢命中(slow hit)。最常用的是If-Modified-Since首部。将这个首部添加到GET请求中去,就可以告诉服务器,只有在缓存了对象的副本之后,又对其进行了修改的情况下,才发送此对象。
缓存命中率(cache hit rate),命中次数/请求次数。
字节命中率:缓存提供的字节传输在所有字节所占比例,可以知道节省流量的程度。
不幸的是,HTTP没有为用户提供一种手段来区分响应是缓存命中的,还是访问原始服务器得到的。在这两种情况下,响应码都是200 OK,说明响应有主体部分。有些商业代理缓存会在Via首部附加一些额外信息,以描述缓存中发生的情况。
缓存拓扑:
- 私有缓存(单用户):chrome://cache 可以查看chrome浏览器缓存的页面
- 公有代理缓存(多用户):共享的公有代理缓存可以减少冗余,参考 Squid
- 层次化缓存
- 网状缓存,内容路由,对等缓存
缓存处理步骤:
1、接收——缓存从网络中读取抵达的请求报文
2、解析——缓存对报文进行解析,提取出URL和各种首部
3、査询——缓存査看是否有本地副本可用,如果没有,就获取一份副本,并将其保存在本地
4、新鲜度检测——缓存査看已缓存副本是否足够新鲜,如果不是,就询问服务器是否有任何更新
5、创建响应——缓存会用新的首部和已缓存的主体来构建一条响应报文
6、发送——缓存通过网络将响应发回给客户端
7、日志——缓存可选地创建一个日志文件条目来描述这个事务
- 新鲜度检测:HTTP1.1 会使用 Cache-Control:max-age=xxx(相对时间)来提供过期时间长度信息,优于 HTTP1.0 使用的 Expires:xxx(绝对时间)
- 再验证相关:条件方法再验证 If-Modified-Since ( IMS ) 和实体标签再验证 If-None-Match ( Etag )
- 优先级:Cache-Control:no-store > no-cache( pragma:no-cache ( http1.0 ) ) > must-revalidate > max-age > Expires > 缓存自己确定过期日期
- Cache-Control 指令: Cache-Control-max-fresh=
s 秒内文档要保持新鲜度 , Cache-Control:only-if-cached 只返回缓存有的对象 , Cache-Control:max-stale 让缓存随意提供过期的文件, Cache-Control:must-revalidate 使缓存服务器严格遵守过期信息
新鲜度检验与控制缓存
与缓存相关的HTTP首部字段:
1.通用首部字段
2.请求首部字段
3.响应首部字段
4.实体首部字段
优先级从高到低分别是 Pragma -> Cache-Control -> Expires
Cache-Control的可选请求值:
缓存头部对比:
头部 | 优势和特点 | 劣势和问题 |
---|---|---|
Expires | 1、HTTP 1.0 产物,可以在HTTP 1.0和1.1中使用,简单易用。2、以时刻标识失效时间。 | 1、时间是由服务器发送的(UTC),如果服务器时间和客户端时间存在不一致,可能会出现问题。2、存在版本问题,到期之前的修改客户端是不可知的。 |
Cache-Control | 1、HTTP 1.1 产物,以时间间隔标识失效时间,解决了Expires服务器和客户端相对时间的问题。2、比Expires多了很多选项设置。 | 1、HTTP 1.1 才有的内容,不适用于HTTP 1.0 。2、存在版本问题,到期之前的修改客户端是不可知的。 |
Last-Modified | 1、不存在版本问题,每次请求都会去服务器进行校验。服务器对比最后修改时间如果相同则返回304,不同返回200以及资源内容。 | 1、只要资源修改,无论内容是否发生实质性的变化,都会将该资源返回客户端。例如周期性重写,这种情况下该资源包含的数据实际上一样的。2、以时刻作为标识,无法识别一秒内进行多次修改的情况。3、某些服务器不能精确的得到文件的最后修改时间。 |
ETag | 1、可以更加精确的判断资源是否被修改,可以识别一秒内多次修改的情况。2、不存在版本问题,每次请求都回去服务器进行校验。 | 1、计算ETag值需要性能损耗。2、分布式服务器存储的情况下,计算ETag的算法如果不一样,会导致浏览器从一台服务器上获得页面内容后到另外一台服务器上进行验证时发现ETag不匹配的情况。 |
在制定缓存策略时,需要牢记下面这些技巧和方法:
- 使用一致的网址:如果您在不同的网址上提供相同的内容,将会多次获取和存储这些内容。提示:请注意,网址区分大小写。
- 确保服务器提供验证令牌 (ETag):有了验证令牌,当服务器上的资源未发生变化时,就不需要传送相同的字节。
- 确定中间缓存可以缓存哪些资源:对所有用户的响应完全相同的资源非常适合由 CDN 以及其他中间缓存进行缓存。
- 为每个资源确定最佳缓存周期:不同的资源可能有不同的更新要求。为每个资源审核并确定合适的 max-age。
- 确定最适合您的网站的缓存层次结构:您可以通过为 HTML 文档组合使用包含内容指纹的资源网址和短时间或 no-cache 周期,来控制客户端获取更新的速度。
- 最大限度减少搅动:某些资源的更新比其他资源频繁。如果资源的特定部分(例如 JavaScript 函数或 CSS 样式集)会经常更新,可以考虑将其代码作为单独的文件提供。这样一来,每次获取更新时,其余内容(例如变化不是很频繁的内容库代码)可以从缓存获取,从而最大限度减少下载的内容大小
缓存会导致广告所需的访问次数统计信息丢失,解决方案:
- 配置缓存,每次都进行再验证
- 迁移日志到服务器,因为缓存日志会记录命中信息
- RFC2227 在 HTTP 协议中添加了 Meter 首部,这个首部会周期性地将对特定 URL 的命中次数回送给服务器,服务器还可以通过这个首部对资源使用次数进行控制
参考:HTTP缓存控制小结
集成点:网关、隧道及中继
网关
网关可以作为某种翻译器使用,它抽象出了一种能够到达资源的方法。网关是资源和应用程序之间的粘合剂。应用程序可以通过HTTP或其他已定义的接口请求网关来处理某条请求,网关可以提供一条响应。网关可以向数据库发送査询语句,或者生成动态的内容。
通用网关接口(Common Gateway Interface, CGI)是一个标准接口集,Web服务器可以用它来装载程序以响应对特定URL的HTTP请求,并收集程序的输出数据,将其放在HTTP响应中回送。
随着Web应用程序提供的服务类型越来越多,HTTP可以作为一种连接应用程序的基础软件来使用。因特网委员会开发了一组允许Web应用程序之间相互通信的标准和协议。如:基于XML的SOAP
服务器与网关应用程序之间交互的基本运行机制:
隧道
Web隧道(Web tunnel)是HTTP的另一种用法,可以通过HTTP应用程序访问使用非HTTP协议的应用程序。使用Web隧道最常见的原因就是要在HTTP连接中嵌入非HTTP流量,这样,这类流量就可以穿过只允许Web流量通过的防火墙了。
Web隧道是用HTTP的CONNECT方法建立起来的。CONNECT方法请求隧道网关创建一条到达任意目的服务器和端口的TCP连接,并对客户端和服务器之间的后继数据进行盲转发。
在图a中,客户端发送了一条CONNECT请求给隧道网关。客户端的CONNECT方法请求隧道网关打开一条TCP连接(在这里,打开的是到主机orders.joes-hardware.com的标准SSL端口443的连接);在图b和图c中创建了TCP连接;一旦建立了TCP连接,网关就会发送一条HTTP 200 Connection Established响应来通知客户端;此时,隧道就建立起来了。客户端通过HTTP隧道发送的所有数据都会被直接转发给输出TCP连接,服务器发送的所有数据都会通过HTTP隧道转发给客户端。
管道化数据对网关是不透明的,所以网关不能对分组的顺序和分组流作任何假设。一旦隧道建立起来了,数据就可以在任意时间流向任意方向了。
SSL隧道
在图a中,SSL流量被直接发送给了一个(SSL端口443上的)安全Web服务器。在图b中,SSL流量被封装到一条HTTP报文中,并通过HTTP端口80上的连接发送,最后被解封装为普通的SSL连接。
这种方式有几个缺点:客户端到网关之间的连接是普通的非安全HTTP;尽管代理是已认证主体,但客户端无法对远端服务器执行SSL客户端认证(基于X509证书的认证);网关要支持完整的SSL实现。对于SSL隧道机制来说,无需在代理中实现SSL。SSL会话是建立在产生请求的客户端和目的(安全的)Web服务器之间的,中间的代理服务器只是将加密数据经过隧道传输,并不会在安全事务中扮演其他的角色。
在适当的情况下,也可以将HTTP的其他特性与隧道配合使用。尤其是,可以将代理的认证支持与隧道配合使用,对客户端使用隧道的权利进行认证。隧道网关无法验证目前使用的协议是否就是它原本打算经过隧道传输的协议。因此,比如说,一些喜欢捣乱的用户可能会通过本打算用于SSL的隧道,越过公司防火墙传递因特网游戏流量,而恶意用户可能会用隧道打开Telnet会话,或用隧道绕过公司的E-mail扫描器来发送E-mail。为了降低对隧道的滥用,网关应该只为特定的知名端口,比如HTTPS的端口443打开隧道。
中继
中继(relay)是没有完全遵循HTTP规范的简单HTTP代理。中继负责处理HTTP中建立连接的部分,然后对字节进行盲转发。
中继对持久对话一无所知,所以它会将收到的所有数据都转发给客户端,等待原始服务器关闭连接。但原始服务器认为中继要求服务器将连接保持在活跃状态,所以是不会关闭连接的。这样,中继就会挂起,等待连接的关闭。在图d中,当客户端收到回送的响应报文时,它会直接转向第二条请求,在 keep-alive连接上向中继发送另一条请求。简单中继通常不会期待同一条连接上还会有另一条请求到达。浏览器上的圈会不停地转,但没有任何进展。
Robot.txt
所有 Web 服务器都可以在服务器的文档根目录中提供一个可选的、名为 robots.txt 的文件。这个文件包含的信息说明了机器人可以访问服务器的哪些部分。如果机器人遵循这个自愿约束标准,它会在访问那个站点的所有其他资源之前,从 Web 站点请求 robots.txt 文件。
robots.txt 文件采用了非常简单的,面向行的语法。robots.txt 文件中有三种类型的行:空行、注释行和规则行。规则行看起来就像 HTTP 首部(
- User-Agent 行
每个机器人记录都以一个或多个下列形式的 User-Agent 行开始:
User-Agent:
- Disallow和Allow行
Disallow 和 Allow 行紧跟在机器人排斥记录的 User-Agent 行之后。用来说明显
式禁止或显式允许特定机器人使用哪些 URL 路径。
- Disallow/Allow前缀匹配
参考:
《图解HTTP》
《HTTP权威指南》
《计算机网络教程》