目录

第一章 HTTP概述

第二章 URL与资源

第三章 HTTP报文

第四章 连接管理

第五章 WEB服务器

第六章 代理

第七章 缓存

第八章 网关、隧道、中继承

第九章 HTTP NG

第十章 客户端识别与cookie机制

第十一章 基本认证机制

第十二章 安全HTTP

第一章 HTTP概述

1、POST和PUT的区别

  • POST:将客户端数据发送到一个服务器网关应用程序
  • PUT:将来自客户端额数据存储到一个命名的的服务器资源中

2、HTTP报文:格式是纯文本,不是二进制代码,可以很方便的调试和拓展。报文分为请求报文和响应报文,格式很类似,主要包含以下三个部分:起始行、首部字段、(空行)、主体。

3、HTTP协议:应用程协议,网络通信的底层细节由TCP/IP传输协议实现,保证无差错、按序传输、流式数据(可以在任何时刻以任意尺寸将数据发送出去)

4、HTTP协议版本:0.9版本有很严重的设计缺陷,只应该用于老客户端的交互,只支持GET请求,不支持多媒体内容的MIME类型。1.0是一个广泛使用的版本,添加了版本号、各种HTTP首部,一些额外的方法以及多媒体对象的处理,使得包含生动图片的WEB页面和交互表格成为可能。1.0+支持keep-alive长连接、虚拟主机支持、代理连接。1.1是当使用的版本,引入重要的性能优化删除一些不好的特性。2.0重点关注的是性能的大幅优化以及更强大的服务逻辑远程执行框架。

5、WEB的结构组件

  • 代理:位于客户端和服务端之间的HTTP实体,接受所有客户端的HTTP请求转发给服务端,可以对请求进行修改。对于用户客户端来说这样的应用程序就是代理,比如可以进行客户端下载资源检测等。
  • 缓存:HTTP的仓库,使常用的页面副本可以保存在离客户端更近的地方,一种特殊的HTTP代理服务器,将客户端一次请求访问的资源缓存起来,接下来的请求可以从缓存中取出来。
  • 网关:连接其他应用程序的WEB服务器,一种特殊的服务器,作为其他服务器的中间实体使用,通常用于将HTTP流量转换成其他协议。
  • 隧道:对HTTP通信报文进行盲转发的特殊代理,建立起来之后,就会在两条连接之间对原始数据进行盲转发的HTTP应用程序,通常会在一条或者多条HTTP连接上转发非HTTP数据,转发时候不会窥探数据,常见的一种用途就是通过HTTP链接承载加密的安全套接字层(SSL Secure Sockets Layer)流量,这样SSL流量就可以穿过只允许Web流量通过的防火墙了。如HTTPS连接建立的过程是通过HTTP请求先建立一条HTTP/SSL隧道,然后在HTTP信道上传输加密的SSL流量。
  • Agent代理:发起自动HTTP请求的半智能WEB客户端,代表用户发送HTTP请求的客户端程序,如WEB 浏览器。

第二章 URL与资源

1、URL字符集:默认的计算机系统字符集都通常倾向于以英语为中心。很多计算机使用的是US-ASCII字符集,使用7位二进制码表示英文打字机提供的大多数按键和少数不可打印控制字符(用于文本格式和硬件通知)。ASCII码历史悠久,可移植性好,但是能表示的语言太少,因此需要通过一种编码机制,通过转义表示不安全字符。例子

  • “~” :120(0x7E)
  • “空格” :32(0x20)
  • “%” :37(0x25)

在URL中,有几个字符被保留起来,有着特殊的含义,%、/、.、..、#、?、;、:、$,+、@&=、{}、|、\、^、~、[]、<>、0x00-0x1f、0x7f、>0x7f等,对于某些传输协议是支持非安全字符的。

2、常见的WEB方案

  • http
  • https
  • mailto:指向的是Email地址,与其他方案都不太通,他并不指任何可以直接访问的对象,如mailto:joe@joes-hardware.com
  • ftp:作为一种数据访问方案使用
  • rtsp、rtspu:RESP URL 是可以通过实时流传输协议解析的音、视频媒体资源标识符。方案中的u指的是使用UDP来获取资源的。
  • file:一台主机上可以直接访问的文件
  • news:访问特定的文章或者新闻组
  • telnet:交互式业务,通过telnet访问资源

第三章 HTTP报文

1、报文的组成部分:三个部分分别是对报文描述的起始行start line,包含属性的首部header,可选包含数据的主体body部分。起始行和首部是由行分隔符的ASCII码,每行都以一个由两个字符组成的行终止序列作为结束(回车符ASCII是13,换行符ASCII码是10),主体可以包含文本数据与二进制数据,也可以为空,首部的Content-Type说明了主体是什么形式。一个报文可以由0个或多个首部。

2、常用的HTTP方法

  • GET
  • HEAD:从服务器获取响应报文的首部,可以用于检测资源的情况,类型以及是否存在。
  • POST:向服务器发送需要处理的数据
  • PUT:向服务器发送需要存储的数据
  • TRACE:对可能经过代理服务器传送到服务器上的报文进行追踪,TRACE请求主要用于诊断,用于验证请求是否如愿的穿过请求、响应链,请求中不能带有实体的body部分,响应的主体body中是服务器收到请求的精确副本。
  • OPTIONS:请求服务器告知支持的各种功能,可以是方法,或者对某些特殊资源支持哪些方法。 出于安全考虑,并不是所有域名访问后端服务都可以。其实在正式跨域之前,浏览器会根据需要发起一次预检(也就是option请求),用来让服务端返回允许的方法(如get、post),被跨域访问的Origin(来源或者域)。参考:https://www.jianshu.com/p/5cf82f092201
  • DELETE

3、常见的HTTP状态码:主要被分为5大类

  • 100-199信息类状态码
  • 100-Continue状态码,客户端如果想要在发送包含body的报文之前查看服务器是否会接受他,可以事先发一个携带值为100 Coninue 的 Expect 请求,服务端必须针对这个请求响应,是否接受客户端发送的报文。
  • 200-299成功状态码
  • 200-OK表示请求没问题,实体的主体部分包含了所请求的资源
  • 201-Created用于创建服务器对象的请求如PUT,响应的实体主体部分中应该包含了引用已创建资源的URL保存在Location字段。
  • 202-Accepted请求已被接受,但服务器还未执行任何动作,不能保证服务区会完成这请求。
  • 203-Non-Authoritative Information实体首部包含的信息不是来自于源端服务器,而是来自资源的一份副本,并没对资源的元数据进行校验。
  • 300-399重定向状态码:告知客户端使用替代位置来访问他们所感兴趣的资源,配合可选的Location首部告诉客户端资源以被移走。
  • 300-Multiple Choices客户端请求一个实际指向多个资源的URL时会返回这个状态码,比如服务器上某个HTML不同的语言版本,返回这个状态码会带上一个选项列表,这样用户可以选择。
  • 301-Moved Permanently:请求的URL移除,响应的Location首部应该包含资源所处的URL。
  • 302-Found:类似301,但是在HTTP1.0客户端发起一个POST请求,收到302之后会接受Location首部指定的重定向URL,并向那个URL发送一个GET请求,而不是像原始请求中发起POST请求。但是HTTP1.1规定使用303状态码实现上述行为,为了避开这个问题,HTTP1.1规定使用307代码取代302进行临时重定向。
  • 305-Use Proxy:用来说明必须使用一个代理访问资源,代理的位置使用Location给出。
  • 400-499客户端错误状态码
  • 400错误请求
  • 401未认证
  • 403服务端禁止
  • 404资源找不到
  • 405方法不允许
  • 406服务端不接受此类型body
  • 408客户端处理时间长,服务端关闭连接
  • 500-599服务器错误状态码
  • 500服务器内部错误
  • 501客户端发起的请求超出服务端的能力范围
  • 502网关无法访问
  • 503服务暂时不可用,可以在响应中包含一个Retry-After首部告知什么时候可用。

4、HTTP首部信息,如

《HTTP权威指南 陈涓 赵振平》读书笔记_HTTP

  • 通用首部:请求报文、响应报文都可以拥有
  • Connection:比如keep-alive长连接就是设置在这块。
  • Date:报文创建的时间
  • MIME-Version:给出了发送端使用的MIME版本
  • Trailer:如果报文采用了分块传输编码,就可以用这个首部列出位于报文
  • Transfer-Encoding:报文的编码方式
  • Update:发送端可能想要升级使用的新版本或者协议
  • Via:显示报文经过的中间节点(代理、网关)
  • 请求首部:请求报文特有的,他们为服务器提供一些额外的信息
  • Accept:比如客户端希望接受什么类型的数据
  • Referer:提供了包含当前请求URL的文档URL
  • User-Agent:将发起请求的应用程序名称告知服务器
  • Expect、If-Match、If-Modified-Since、If-Range和Range等条件请求首部:If-Range表示允许对文档的某个范围进行条件请求配合Range来限制资源指定范围。
  • Authorization、Cookie:安全认证请求首部,Cookie是客户端向服务端传送的一个令牌,并不是真正的安全首部,但是确实隐藏了安全功能。
  • Max-Porward、Proxy-Authorization、Proxy-Connection代理请求首部,供代理使用的属性信息。
  • 响应首部:响应报文特有的,以便为客户端提供信息
  • Server:比如客户端在根哪种类型的服务器进行交互
  • Age:响应持续的时间(从最初创建开始)
  • Retry-After:如果资源不可用的话,在此日期或时间重试
  • Warning:比状态码后面的原因短语更详细的一些警告报文
  • Accept-Ranges、Vary协商首部
  • 实体首部:描述HTTP报文的负荷,提供实体及其内容的大量信息,在请求报文和响应报文中都会存在。
  • Allow:列出可以对此实体执行的请求方法
  • Location:告知客户端实体实际存储在那个URL上去
  • Content-xxx:主体body相关,如Content-Type、Content-Ecoding等
  • ETag-资源版本标识符、Expires-缓存失效时间、Last-Modified-实体最后一次被修改的时间:实体缓存首部相关。
  • 扩展首部:非标准的首部,由应用程序开发者创建,由HTTP应用程序转发
  • 通用缓存首部:HTTP/1.0引入第一个允许HTTP应用程序缓存对象本地副本的首部,如Pragma允许缓存,HTTP/1.1改成了Cache-Controller

第四章 连接管理

1、TCP连接:世界上几乎所有的HTTP通信都是由TCP/IP承载的,TCP/IP是全球计算机和网络设备都使用的常用分组交换网络分层协议集。HTTP连接实际上就是TCP连接及其使用规则,TCP提供一条可靠的比特流传输管道,TCP的数据是通过名为IP分组(IP数据报)的小数据块发送的,可以将HTTP理解 HTTP over TCP over IP 这个协议栈,HTTPS就是在HTTP和TCP之间插入一个TLS、SSL的密码加密层。

《HTTP权威指南 陈涓 赵振平》读书笔记_服务器_02


2、TCP套接字API:套接字API允许用户创建TCP的端点数据结构,将这些端点与远程服务器的TCP端点进行连接,并对数据流进行读写,隐藏了底层网络协议和握手细则,以及TCP数据流与IP分组之间的分段和重装细节。

《HTTP权威指南 陈涓 赵振平》读书笔记_HTTP权威指南_03

3、TCP性能:HTTP紧挨着TCP,位于其上层,所以HTTP事务的性能很大程度上取决于底层TCP通道的性能。

4、HTTP事务的时延:与建立TCP连接以及传输请求和响应报文的时间相比,事务处理的时间可能是很短的,除非客户端或者服务端超载或正在处理复杂的动态资源,否则HTTP时延就是有TCP网络时延造成的。HTTP事务的时延主要由一下几种原因,主要取决于硬件速度,网络和服务器的负载,请求和响应报文的大小以及客户端和服务端之间的距离,TCP协议的复杂度同样也会对时延产生巨大的影响。

  • 客户端首先需要根据URI确定Web服务器的IP地址和端口号,如果最近没有对URI中的主机进行访问,通过DNS解析系统将URI中的主机名转换成一个IP地址可能需要花费数10s的时间。
  • 在建立TCP连接通道的时候需要三次握手,会有建立时延,这个值通常只有一两秒中,如果数百个HTTP事务,这个值也会快速叠加上去。
  • 报文的传输时延

5、TCP相关时延

  • TCP三次握手建立连接:现在的TCP栈都允许在客户端第三次握手发送的ACK确认分组中包含需要的真实数据。
  • TCP慢启动拥塞机制:防止网络拥塞的机制,由于这种机制,新连接的传输速度会比已经交换过一定数据的、已经平稳的连接慢一些,所以HTTP中有一些可以重用现存连接的工具。
  • 数据聚集的Nagle算法:TCP有一个数据流接口,应用程序可以通过他将任意尺寸的数据放入TCP栈(即使每次只有一个字节也可以)但是TCP段中包含40个字节的首部标记和首部,如果TCP段中的有用数据太少,网络的性能就会严重下降。Nagle算法试图在发送一个分组之前,将大量的TCP数据绑定在一起,以提高网络效率。Nagle算法鼓励发送全尺寸(LAN上最大的尺寸分组是1500字节,在因特网上是几百字节)的TCP段,如果其他分组仍然在传输过程中,就将那部分数据缓存起来,只有当挂起的分组被确认,或者缓存中积累够了足够发送一个全尺寸分组数据的时候,才会将缓存的数据发送出去。Nagle算法会引发几种HTTP性能问题,首先,小的HTTP报文可以无法填满一个分组,可能会因为等待那些永远不会到来的额外数据产生时延,其次,Nagle算法会阻止数据的发送,直到有确认分组抵达为止,但确认分组自身自身会被延迟确认算法延迟100-200毫秒,可以通过参数TCP_NODELAY禁用Nagle算法,如果这麽做,最好确定向TCP段写入大块数据。
  • 用于捎带确认的TCP延迟确认方法:由于因特网自身无法确保可靠的分组传输(因特网路由器超负载的话可以随意丢弃分组),因此TCP实现了基于滑动窗口的确认机制,现在很多TCP栈都实现了一种"延迟确认"算法,延迟确认算法会在一个特定的窗口时间(通常是100~200ms)内将输出确认放在缓冲区,已寻找能够捎带他的输出报文分组,也就是把去确认信息和输出的报文信息放一块,如果在那个时间没有输出数据分组,就会将确认信息放在单独的分组中传送。但是HTTP具有双峰特征的请求-应答行为降低了捎带信息的可能,导致确认报文一直在缓存中等待,通常延迟确认算法会引入相当大的时延,可以调整或禁止延迟确认算法。
  • TIME_WAIT时延和端口耗尽:当某个客户端TCP端点关闭TCP连接时候,会在内存中维护一个小的控制块,用来记录最近所关闭连接的IP、port,这类信息只会维护较短的一段时间,通常是所估计最大分段使用期间的两倍,称为2MSL(通常为两分钟),保证客户端最后发送的ACK能够到达服务器,帮助其正常关闭。

6、HTTP连接的处理

  • Connection首部字段处理:代理、高速缓存等不能对包含HTTP首部字段进行转发,转发之前必须删除Connection字段。某些哑代理或者盲中继会存在转发Connection的情况,客户端和服务器都以为使用Keep-Alive长连接通信,但是代理不知道,所以会将服务器响应报文传给客户端,然后等待服务器关闭连接,但服务器认为代理已经显示的请求它将连接保持在打开,因此不会关闭,代理就会挂在那里等待连接的关闭。解决办法可以是引入新的首部Proxy-Connection字段
  • 串行事务处理时延处理:假如每次请求资源都需要建立一个请求,那么连接时延和慢启动时延就会叠加起来,会造成速度很慢,几种现存和新兴的方法可以提高HTTP的连接性能
  • 并行连接:通过多条TCP连接发起并发的HTTP请求资源。即使并行连接的速度可能会更快,但并不一定总是更快,客户端的网络带宽不足导致多个HTTP事务竞争带宽,这样带来的性能提升很小。而且打开大量的连接会消耗很多的内存资源,从而引发自身的性能问题,比如Web服务器需要处理大量的用户连接请求,假如100个用户同时发请求,每个用户打开100个连接,服务器就要负责处理1w个连接,这会造成服务器性能严重下降,对高负荷的代理来说也是同样如此。因此浏览器一般会限制并行连接的数量为一个较小的值(通常是4个),服务器可以随意关闭来自特定客户端的超量连接。
  • 持久连接:重用TCP连接,以消除连接及关闭时延。站点局部性原理指的是用户可能再一段时间内更多访问某站点上的资源,因此再HTTP1.0允许HTTP设备再事务处理结束之后将TCP连接保持打开状态,比如keep-alive支持长连接字段,HTTP1.1的 persistent 连接称为持久连接,可以一定程度避免建立连接、慢启动机制的时延。但是管理持久连接时要特别小心,不然就会累计出大量的空闲连接,耗费本地以及远程客户端和服务器上的资源。使用keep-alive首部是将连接保持在活跃状态,发出keep-alive请求之后,客户端和服务端并不一定会同意进行keep-alive会话,如果同意,需要在响应头中带上keep-alive字段,他们可以在任意时刻关闭空闲的keep-alive连接,另外可以通过选项调节行为,比如timeout参数是响应头keep-alive存在时配置的,他估计服务器希望将连接保持在活跃状态的时间,比如max是在keep-alive存在响应首部发送的,他估计了服务器还希望多少个事务保持此连接的活跃状态。
  • 管道化连接:在持久化连接的基础上可选用管道话连接,在响应到达之前,可以将多条请求放入队列,通过共享的TCP连接发起并发的HTTP请求,这样可以降低网络的回环时间,提高性能。
  • 复用的连接:交替传送请求和响应报文。

《HTTP权威指南 陈涓 赵振平》读书笔记_服务器_04

7、关闭连接的处理

  • 任何时刻服务端、客户端都能关闭一条TCP连接,包括出错的情况,连接长时间空闲的情况。
  • 由于幂等性等原因关闭连接:即使在非错误情况连接也可以任意时刻关闭,HTTP要做好非预期关闭的准备。如果事务是幂等的,客户端执行事务过程中连接关闭了,那么客户端就应该重新打开连接重试一次。对于管道化长连接,这种情况更多。POST请求方式一般是非幂等的,其他PUT、GET、TRACE等都是幂等的,幂等指的是一个事务不管是执行一次还是多次,得到的结果是一样的。
  • 正常关闭连接:TCP是双向连接,每一端都有输出、输入队列,用于数据的读写。关闭分为完全关闭和半关闭,使用半关闭来预防对等实体收到非预期的写入,比如关闭连接的输入信道比较危险,因为不知道另一端是否还要写数据,如果客户端向服务端的读取信道发送数据,但是服务端已经关闭,测试就会恢复一个TCP连接重置的报文,大部分操作系统都把这当作严重错误处理,会删除客户端还未读取的在操作系统缓存中的数据,之前服务器的响应数据还未读取部分都会被清空丢失。

第五章 WEB服务器

1、服务器执行的任务

  • 建立连接
  • 接受请求:读取解析HTTP报文
  • 处理请求
  • 访问资源
  • 构建响应
  • 发送响应

高性能服务器能在接受请求阶段可以同时支持数千条连接,这些连接有可能是繁忙的,有些可能是空闲的,如何管理这些连接很关键

  • 单线程处理:一次处理一个请求,直到这个请求结束才处理下一个请求。只适合负载低的服务器。
  • 多线程(多进程)处理:多个线程处理请求,可以根据所需或者预先创建线程,当请求过多时,过多的线程、进程数量、内存会耗费太多的资源。
  • 复用I/O处理:单线程监视所有连接,只处理需要处理的连接,处理完接着监视所有连接。
  • 多线程复用I/O处理:多个线程监视连接,充分利用多CPU服务器特性。

第六章 代理

1、概念:HTTP的代理服务器既是客户端也是服务端,分为私有和共享代理,私有代理不常见,如浏览器辅助产品以及ISP服务。严格来说代理是连接两个或者多个使用相同协议的应用程序,而网关连接则是多个使用不通协议的端点,实际上他们之间的区别很模糊,由于浏览器和服务器使用的有可能是不同版本的HTTP,因此代理需要做一些协议转换工作,而商业化的代理也可能会实现网关的功能如SSL安全协议、SOCKS防火墙、FTP访问等。

2、使用代理的好处:儿童过滤器、文档范文控制、安全防火墙、Web缓存、反向代理(常被部署在网路边缘,为真实的服务器服务,可以访问目标服务器以提高访问公共内容时候的性能)、内容路由器(类似网关)、转码器、匿名代理(主动从HTTP报文删除身份特性)

3、代理按照部署拓扑结构分类

  • 出口代理:固定在本地网络的出口点,以便控制本地网络和大型因特网之间的流量。
  • 入口代理:固定在ISP访问点上,处理客户的聚会请求,使用缓存代理来提高用户的下载速度。
  • 反向代理:通常被部署在网络边缘,在WEB服务器之前,只在必要时请求真正的服务器。
  • 网络交换代理:将有足够交换能力的代理放在网络之前的因特网对等交换点上,通过缓存代理减轻因特网节点的阻塞。

4、流量如何通过代理

  • 修改客户端:客户端浏览器一般都支持受自动、手动代理配置,然后客户端的请求都会直接发给代理服务器,再转给真正的服务器。
  • 修改网络:在客户端不知情的情况下对请求进行拦截,并将流量导入一个代理,这种代理被称为拦截代理。
  • 修改DNS:放在真正服务器之前的代理服务器,直接假扮WEB服务器的名字和IP地址。
  • 修改服务器:配置服务器给客户端的响应为重定向305

5、代理请求相关

  • 访问的URI可能不同,一般来说直接访问服务器的时候,它会发送部分URI,设置客户端使用代理时,一般会发送完整的URI,因为可能多个代理给一个服务器服务。通用的代理应该都能支持,如果提供部分URI,可以配合Host等首部确认原始服务器。
  • TRACE方法:代理服务器可以在转发报文的时候对其修改,可以添加、修改、删除首部,也可以将主体部分转换成不同格式,可使用HTTP1.1的TRACE方法追踪代理传输的请求报文。
  • 代理必须对不认识的首部字段进行转发。
  • OPTIONS方法:客户端或者代理可以发现WEB服务器所支持的功能,比如他们所支持的方法,会在响应的Allow首部返回。

第七章 缓存

1、WEB缓存是可以自动保存常见文档副本的HTTP设备,使用缓存有以下优点:

  • 减少冗余的数据传输
  • 缓解了网络瓶颈问题,不需要更多的带宽就能更快的加载页面,很多网络为本地客户端提供的带宽比远程服务器提供的带宽要宽,因此数据传输会受限于服务器带宽,如果客户端能从具有高带宽的缓存获取副本,那么缓存就能提高性能。
  • 降低了对原始服务器的要求,服务器可以更快的响应,避免过载的出现。
  • 降低了距离时延,从较远的地方加载页面可能会慢一些。每台网络路由器都会增加因特网流量的时延,即使客户端和服务器端没太多的路由器,光速自身也会造成显著的时延。

2、缓存命中性:缓存内容是有限的,缓存的命中性是个问题,对于缓存未命中的需要将请求转发给原始服务器。

3、缓存一致性:原始服务器内容可能发生变化,需要缓存时不时对其"新鲜度检测" ,被称为HTTP的再验证,HTTP定义了一些特殊的请求,不需要从服务器获取整个对象,就可以快速检测内容是否是最新的。缓存检测的实际一般是在客户端发起请求的时候并且副本很旧需要验证的时候,才会对副本进行验证,检测的时候会像服务器发送一个小的再验证请求,如果内容没有变化,服务器会提供一个小的304 Not Modified 进行响应,只要缓存知道副本仍然有效,就会把副本置为暂时新鲜,并返回给客户端。

《HTTP权威指南 陈涓 赵振平》读书笔记_http_05

HTTP提供几个用来对已缓存对象进行再验证的工具,但是常用的是If-Modified-Since首部,将这个首部添加到GET请求中去,就可以告诉服务器在缓存失效的时候需要重新刷新缓存。

4、缓存的字节命中率:缓存的文档有大有小,而且访问频率也不太一样,因此更倾向于使用字节命中率来作为度量值来评估缓存。HTTP并未为用户提供一种手段来区分响应数据是从缓存得到的还是从原服务器得到的,

  • 有些商业代理会在缓存响应的首部加上via首部附加额外的信息,描述缓存中发生的情况。
  • 客户端有一种方法可以判断响应是否来自缓存,就是使用Date首部,将响应中的Date首部的值与当前时间比较,如果响应中的日期值比较早,客户端通常可以认为这是一条缓存的响应。
  • 客户端也可以通过Age首部来检测缓存的响应,通过这个首部可以分辨出这条响应的使用期

5、缓存的拓扑结构分类

  • 私有缓存:不需要很大的存储空间以及配置,如WEB浏览器中有内建的私有缓存,大多数浏览器都会将常用文档缓存在个人电脑磁盘和内存中,并且允许用户去配置缓存的大小和各种配置。
  • 共有代理缓存:服务多个客户端,降低网络流量。

6、代理缓存的层次结构:在实际中,实现层次化的缓存是很有意义的

  • 链式状缓存:在较小的缓存未命中的请求将会被导向较大的父缓存,由他为剩下那些"提炼过"的流量提供服务,但是代理缓存的链路不易过长,否则这种性能消耗会比较严重。
  • 网络状缓存:各个代理缓存之间呈现网络状,以更加复杂的方式进行对话,或者决定彻底绕开缓存,直接连接原始服务器,或者决定与那个父缓存进行对话,这种选择何种路由对内容进行访问、管理和传送被称为内容路由器。缓存之间这种复杂的关系允许不同地组织互为对等体,简称兄弟缓存,但是HTTP协议并不支持兄弟缓存,一些对HTTP扩展的协议如ICP因特网缓存协议、HTCP协议超文本缓存协议支持。

7、缓存处理流程

  • 接受:读取报文
  • 解析:解析报文,放入易于操作的数据结构
  • 查找:根据URL查找本地是否存在缓存,专业级的缓存会使用快速算法确定本地缓存中是否存在某个对象。
  • 新鲜度检测:缓存从服务器获取到之后,在某段时间内是被认为是新鲜的,缓存可以在不联系服务器的情况下,直接提供文档,但是超过这段时间后,缓存需要和服务器进行再次确认,已查看文档是否发生改变。客户端请求头可以配置强制缓存进行再验证,或者是完全避免,这使得事情变得复杂了。
  • 创建响应:按需对响应进行调整,比如加上新鲜度信息(Cache-Control、Age、Expires首部),而且通常会包含一个Via首部来说明请求是由一个代理缓存提供的。
  • 发送
  • 日志

再验证逻辑

《HTTP权威指南 陈涓 赵振平》读书笔记_HTTP_06

其中再验证阶段,和服务器缓存一致的判断可以由HTTP特殊的响应首部来完成,比如Cache-Control、Expires等,HTTP会让原始服务器给每个文档都加上这些头部"过期时间" ,这些文档经过首次访问会存储在代理缓存中,Expires是HTTP1.0+的首部,使用的是绝对时间,Cache-Control是HTTP1.1的首部,使用的是相对时间,比如Cache-Control:max-age,后面从缓存取数据的时候,判断时间过去表示缓存需要再验证,再验证结果如果原始文档发生了变化,就从原始服务器拉一份最新的,然后返回给客户端,若验证结果没有发生变化,缓存只需要更新本地最新的首部。

另外是允许将再验证和从原始服务器获取最新数据放入一个GET请求中,首部加上If-Modified-Since <date> 即IMSIf-None-Match <tag> 即INM,代理缓存服务器发送这个再验证请求,服务器接收到这个请求,会判断自某个日期之后资源是否发生变化,

  • IMS可以与服务端响应Last-Modified <date>配合使用,下次发IMS请求的时候就会带上这个时间。
  • 如果发生变化,IMS请求会被判定为true,然后GET就会被成功执行,返回带着新主体的200响应,新的文档会被返回给缓存,文档的新鲜时间也是最新的。
  • 如果没发生变化,IMS请求就会被判定为false,然后会返回一个304 Not Modified 报文。
  • INM是为了解决IMS的缺陷比如文档在服务器端被周期性的修改,但是内容并未改变,或者是无法判断某些文档修改的时间抑或者是妙级别的粒度太大,这个时候可以加上文档的版本标识符tag,然后进行再验证的逻辑。

《HTTP权威指南 陈涓 赵振平》读书笔记_HTTP权威指南_07


对于IMS和INM的验证,缓存允许使用不同的验证器来完成,分为强、弱验证器,强验证器指的是文档内容发生过改动即使改动很小,也需要更新缓存,弱验证器指的是允许忍受一定程度的修改,服务器在响应中会使用W/来标识弱验证器。如果服务器返回一个标签值,那么HTTP1.1客户端必须使用实体标签验证器,如果服务器只返回一个Last-Modified的话,客户端可选IMS或者INM。

8、控制缓存的能力:服务器端可以通过HTTP响应头Cache-Control来指定在文档过期之前可以代理缓存、客户端缓存(浏览器)可以将其缓存多长时间,也就是在服务器更新文档之前,缓存对象有效的时间。

  • Cache-Control:no-store:禁止缓存对响应进行复制,缓存会像客户端的响应也会带上该头部,然后删除对象。功能和兼容HTTP 1.0+的Pragma:no-store类似。
  • Cache-Control:no-cache:响应实际上是可以存储在缓存中的,只是在与原始服务器进行新鲜度再验证之前,缓存不能将其提供给客户端使用。
  • Cache-Control:must-revalidate:严格的遵守过期时间,如果在新鲜度有效期内,那么可以返回缓存,但是如果过了新鲜度,而且再验证的时候服务器不可用,那么就会返回一个504 Gateway Timeout错误。
  • Cache-Control:max-age:从服务器接收到文档保存新鲜度的秒数,如Cache-Control:max-age = 0 表示服务器请求缓存不要缓存文档,每次访问的时候都进行刷新。

《HTTP权威指南 陈涓 赵振平》读书笔记_服务器_08

《HTTP权威指南 陈涓 赵振平》读书笔记_HTTP权威指南_09

《HTTP权威指南 陈涓 赵振平》读书笔记_http_10

在Web开发中,缓存是提高网站性能的重要手段之一。但有时候我们需要控制浏览器是否缓存某些文件或请求,这时可以使用HTTP响应头来实现。

no-cache:表示不直接从缓存中获取资源,而是先向服务器发送一个请求,由服务器判断资源是否更新,如果没有更新则返回304 Not Modified状态码,否则返回最新的资源。
no-store:表示禁止缓存该资源,每次都必须向服务器重新请求。
对于CSS和JS文件,通常情况下我们希望它们被缓存起来,以便加快页面加载速度。因此,我们可以设置缓存时间较长,并且使用no-cache选项,这样即可保证用户访问时能够从本地缓存中获取资源,同时又能及时检查是否有更新。

例如:

Cache-Control: max-age=3600, no-cache
对于具体的业务请求,根据实际需求选择合适的缓存策略。如果数据变化频繁,建议使用no-cache选项;如果数据变化较少,可以考虑使用max-age选项设置缓存时间,减轻服务器压力。

需要注意的是,在使用缓存时还需要考虑到安全问题,避免敏感信息被缓存导致泄露。

另外可以附加HTTP1.0+ 的 `Expires:绝对时间` 或者不附加过期信息,让缓存自己确定过期时间。如果响应中没有Cache-Control:max-age首部,也没有Expires首部,缓存可以计算一个试探性最大使用期,可以使用任何算法,但是如果得到的最大使用期大于24小时,就应该向响应首部添加一个Heuristic Expiration Warning(试探性过期警告)首部,一般很少出现。

9、应用场景

另外在实际的项目中,可以配合全局Controller异常捕获,在发生异常的时候通过Cache-Control:no-store Expires:0不进行缓存。

@RestControllerAdvice
public class GlobalExceptionHandler {
		// 发生异常
		 @ExceptionHandler(Exception.class)
    public ErrorMessage handleControllerException(HttpServletRequest request, HttpServletResponse response, Exception e) {
		// 清除缓存
		removeCacheControlHeader(response)
		// 异常分类
    }
}

private void removeCacheControlHeader(HttpServletResponse response) {
        if (response.containsHeader("Cache-Control")) {
            //如果reponse的状态码非200,就不要加上CacheControl
            response.setHeader("Cache-Control", "no-store"); // HTTP 1.1.
            response.setDateHeader("Expires", 0); // Proxies.
        }
    }

第八章 网关、隧道、中继

1、网关的概念:网关可以作为某种翻译器使用,它抽象出一种能够到达资源的方法,可以进行客户端、服务端之间进行辅助通信。

2、协议网关的分类:

  • 服务端安全网关:对所有的输入Web请求加密,客户端可以使用HTTP浏览Web内容,但是网关会自动加密用户的对话
  • 客户端安全加速网关:放在服务端之前常作为不可见的拦截网关或者反向代理,他们接受HTTPS请求然后进行解密,向Web服务器发送普通的HTTP请求。

3、隧道的概念:隧道允许用户通过HTTP连接发送非HTTP流量,这样就可以在HTTP上捎带其他协议数据了,使用Web隧道最常见的场景就是要在HTTP连接种嵌入非HTTP流量,这样,这类流量就可以穿过只允许Web流量通过的防火墙了。Web隧道是用HTTP的CONNECT方法建立起来的,CONNECTION方法请求隧道网关打开一条TCP连接,并对客户端和服务器之间的后继数据进行盲转发,建立隧道的流程

  • 客户端发送一条HTTP CONNECT请求给隧道网关,除了起始行之外,CONNECT的语法和其他HTTP方法类似,主机和端口都需要被指定,隧道网关会打开一个TCP连接,一般是安全的SSL 443通道
  • 一旦TCP连接创建,隧道网关就会发送一个HTTP 200 的响应来通知客户端,响应和一般的HTTP响应不太相同,这个响应并不需要包含Content-Type字首部,响应中的原语一般通常被设置为Connection Established。
  • 客户端通过HTTP方式发送的数据都会被隧道网关转发给TCP连接,服务器发送的数据都会被隧道网关转发给客户端。

作为一种性能优化的方式,允许客户端在发送CONECT请求之后,接受响应之前,发送隧道数据,这样可以更快的将数据发送给服务器,这就意味着隧道网关必须要能处理跟在CONNECT请求之后的数据,隧道网关不能假设客户发送的数据只包含首部,需要将请求中其他比如实体数据也要读取待会一块发给服务器,若是CONNECT请求被服务器回复认证请求而不是200请求,客户端还需要重新发送真实数据。

4、SSL隧道解决的问题:最初开发Web隧道是为了通过防火墙来传输加密的SSL流量,很多组织都会将所有流量通过分组过滤路由器和代理服务器以隧道方式传输,以提高安全性。但是有些协议比如加密SSL,其信息是加密的,无法通过传统的代理服务器转发,隧道会通过一条HTTP连接来传输SSL流量,以穿过端口80的HTTP防火墙。

下面是直连的SSL连接与隧道化SSL连接图,隧道化SSL连接中只是将加密数据经过隧道传输,并不会在安全事务中扮演其他角色。

《HTTP权威指南 陈涓 赵振平》读书笔记_网络_11

第九章 HTTP NG

1、HTTP的局限性:HTTP最初的目的是为了能简单的访问分布式信息服务器上链接的多媒体内容,随着需求场景越来越复杂,HTTP1.1提供可追踪文档版本的标记和指纹,提供一种方法支持文档的上传以及可编程网关之间的交互,以及多语言、安全、认证、降低流量的缓存、减少时延等。HTTP发展过程的局限性

  • 复杂性:存在一些复杂、相互交织的要求、连接管理、报文处理等功能逻辑。
  • 可拓展性:很难实现递增式拓展
  • 性能:某些部分效率不高,其中很多低效特性会随着高时延、低吞吐的无线访问技术的广泛使用而变得更加严重。
  • 传输依赖性:大部分都是基于TCP、IP协议栈,使用其他协议栈的很少。

2、HTTP NG:下一代HTTP概括为 模块化及功能增强,建议将协议模块化分为三层,而不是连接管理、报文处理、服务器处理逻辑和协议方法都混在一起

  • 第一层:报文传输层,不考虑报文的功能,致力于端点间报文的不透明传输以及报文传输的性能,比如管道话、批量化传输,重用连接、在一条连接上并行复用多个报文流,报文分段更好确定边界,对应的协议为WebMUX。
  • 第二层:远程调用层,定义请求和响应的功能,试图提供类似JavaRMI 那样面向对象的框架,建议采用二进制协议,不考虑具体的细节如缓存、安全以及方法逻辑,主要是提供通用的远程调用支持。
  • 第三层:Web应用层,内容管理如请求方法。

3、WebMUX协议:复杂的高性能报文系统,通过这个系统,可以在一个复用的TCP连接上并行的传输报文,可以对不同速度产生和消耗的独立报文流进行高效的分组,并将其复用到一条或少数几条TCP连接上去。

第十章 客户端识别和cookie机制

1、HTTP最初是一个匿名、无状态的请求、响应协议,HTTP并不是天生就具有丰富的识别性的,需要依靠其他技术实现如

  • 承载用户身份信息的HTTP首部:From包含用户Email地址,User-Agent浏览器相关信息,Referer用户来源页面URL,不足以实现可靠的识别。
  • 客户端IP地址追踪,通过用户的IP地址对其进行识别:虽然IP地址有着变化较少的特性,但是也存在局限性,比如IP地址描述的是所用的机器,而不是用户,如果多个用户共享一台就不好区分了。存在NAT防火墙将实际的客户端IP地址转换为一个共享的防火墙IP地址加端口,
  • 用户登录:登录认证,通过Authenticate首部,具体的流程是客户端请求服务端,未登录会响应401 Login Required HTTP响应码,并添加WWW-Authentication首部要求用户登录,浏览器客户端输入账号密码之后重复原来的请求,并带上Authorization首部包含加密的用户名和密码。
  • 胖URL:在URL中维护用户标识
  • cookie:当前识别用户实现持久化会话的最好方式,可以将cookie分为两类,会话cookie和持久化cookie,会话cookie是一种临时cookie,记录用户访问站点时候的设置和偏好。当浏览器关闭会话cookie就会消失,一般没设置Discard参数或者没有设置Expires或Max-Age参数,而持久化cookie没有过期时间。cookie的基本思想就是让客户端浏览器积累一组服务器特有的信息,发请求的时候会携带指定域下的所有cookie给服务器。

2、一般cookie存储的结构会有几个字段

  • domain:在设置cookie时,可以指定其作用域(domain)属性,以控制哪些网站可以访问该Cookie。如果未指定作用域,则默认为当前页面所在的域名。以下是一些常见的作用域示例:
  • example.com:表示所有子域名都可以访问该Cookie,例如www.example.com、blog.example.com等。
  • .example.com:与上述相同,但还包括顶级域名本身,即example.com。
  • www.example.com:仅限于该特定子域名下使用。
  • /:表示整个网站都可以访问该Cookie。
    需要注意的是,由于安全原因,不同域名之间的Cookie不能互相访问。例如,在example.com域名下设置的Cookie无法被google.com域名下的页面访问到。
  • path:域中相关的路径前缀,用于区分独立的该域下的不同场景需求的cookie,如/foo与/foobar 和 /foo/bar.html相匹配。
  • source:是否只有在使用SSL连接的时候才发送这个cookie
  • expiration:过期时间

3、cookie与会话跟踪,以访问Amazon.com网站为例

  • 浏览器首次请求Amazon.com页面
  • 服务器将客户端重定向到一个电子商务软件的URL,客户端对重定向的URL发起一个请求,服务端在响应中发送两个cookie。
  • 服务器将客户端重定向另外一个URL,客户端请求这个URL会带着两个cookie,服务器返回响应内容。
  • 服务器将客户端重定向到首页,客户端会携带着两个cookie发请求,服务器返回响应内容。

4、cookie与缓存,cookie和资源缓存的规则并没有很好的建立起来,下面是几个指导性规则

  • 服务端如果无法缓存文档,要将其标示出来,如果除了Set-Cookie首部之外的文档是可缓存的,就使用Cache-Control:no-cache="Set-Cookie",另外一种做法是Cache-Control:public,有助于节省网络带宽。
  • 服务端缓存Set-Cookie首部要注意:如果响应中有Set-Cookie首部,就可以对主体进行缓存。
  • 服务端小心处理带有Cookie首部的请求

第十一章 基本认证机制

1、认证就是需要给出一些身份证明,HTTP提供一个可定制的控制首部,为不同的协议提供一个可拓展的框架,分为基本认证和摘要认证。

2、认证协议与首部:首次请求服务端响应401 Unauthorized,然后在首部WWW-Authenticate首部对保护区域进行描述,然后是客户端重新发送请求,附加一个Authorization首部,用来说明认证算法、用户名和密码。最后如果授权通过,服务器就会将文档返回,有些授权算法会在Authentication-Info首部返回一些与授权会话相关的附加信息。另外HTTP允许服务器为不同的资源划分不同的域,可以单独的为每个域进行权限控制,比如在WWW-Authenticate: Basic realm="Family" 表示需要对Family域下资源进行认证。

代理认证流程类似,只是首部和状态码略有不同

Web服务器

代理服务器

Unauthorized status code : 401

Unauthorized status code: 407

WWW-Authenticate

Proxy-Authenticate

Authorization

Proxy-Authorization

Authentication-Info

Proxy-Authentication-Info

3、基本认证:一种HTTP协议

  • 网络发送用户名和密码,容易被解码
  • 公司内部相同的用户名密码
  • 没有提供任何针对代理和作为中间人的中间节点的防护措施,当没修改认证首部但是修改了报文的其余部分,严重改变了事务的本质。
  • 假冒服务器很容易骗过基本认证

总之基本加密适合一些对隐私保护不高的场景,可以防止用户无意或者不小心对文档进行访问,可以将基本认证与加密数据传输(比如SSL)配合使用,向恶意用户隐藏用户名和密码。

4、摘要认证:另外一种HTTP协议,但是并不是最安全的协议,试图修复基本认证协议的严重缺陷,做了一下改进,但是没被广泛使用,不能满足安全HTTP事务的很多需求,对于这些需求来说,使用传输层安全协议TLS(Transport Layer Security) 和 HTTPS(Secure HTTP)协议更合适一些

  • 不会明文发送密码:认证阶段发送密码的摘要,这段摘要为不可逆绕码,客户端和服务端都知道这个密码,然后服务端遍历所有密码对比。
  • 可以防止恶意用户捕获并重放认证的握手流程:密码的摘要也是可以被捕获然后重放供给的,因此服务端可以在WWW-Authenticate中响应一个随机数,客户端将这个随机数拼接密码然后进行摘要。
  • 有选择地防止对报文内容的篡改:增加qop: auth-int首部来进行报文完整性认证
  • 防范其他几种常见的攻击方式

第十二章 安全HTTP

上面的简单基础认证策略只适合友好环境,对于充满各种利益驱动和恶意对手的环境中,他们并不足以包含那些重要的事务处理,因此Web需要一种安全的HTTP形式。

1、HTTPS概念:HTTPS是最流行的HTTP安全形式,使用HTTPS时候所有的HTTP请求和响应数据在发送网络之前,都需要进行加密。HTTPS在下面提供一个传输级的密码安全层SSL以及后继者TLS,这个安全层位于TCP之上,简言之为位于安全层之上的HTTP。

2、加密编码技术相关概念

  • 密码
  • 密钥:对密码进行扰动的数字化参数
  • 对称密钥加密系统:加密、解密使用相同密钥的算法,常见的有DES、Triple-DES(128位)、RC2和RC4。
  • 非对称密钥加密系统:加密、解密使用不同的密钥的算法。也称公开密钥加密系统,没有像对称加密那样需要两两主机之间需要维护一对密钥,而是使用一个公开的公钥、自己留有解密的私钥,因此是一种能使数百万计算机便捷发送机密报文的系统。
  • 混合加密系统:非对称机密虽然方便,发送者直接公钥加密给接收者,然后接收者直接解密,但是非堆成加密效率比较低,因此混合加密就是首先利用非对称加密建立安全通道,然后发送对称的密钥,等待接收者收到对称密钥,然后发送者就发送对称密钥加密的报文即可。
  • 数字签名:检验报文是否被伪造或者篡改的校验和
  • 数字证书:由一个可信的组织验证和签发的识别信息

3、非对称加密算法很安全:公开密钥非对称加密算法面临的挑战就是 要确保即便有人拥有了下面所有的线索,也无法计算出保密的私有密钥

  • 公开的公钥
  • 拦截下来的密文

RSA算法是一个流行的非对称加密算法,即使有了公共密钥、任意一段明文、用公钥对明文编码之后得到的相关密文、RSA本身甚至源代码,破解私钥的代码和将一个极大的数进行质因数分解的困难程度相当,是计算机科学中最难的问题之一。

4、数字签名:不仅能使用对称、非对称加密算法进行加密HTTP报文,还可对HTTP报文进行签名,证明是谁编写的报文,同时证明报文是否被修改过。数字签名通常是由非对称加密产生的,签名由私钥产生,可以理解为加了密的校验和,也可以理解为指纹。使用签名的好处

  • 签名可以证明是作者编写了这条报文,因为作者才会由私钥,才能计算出内容的校验和。
  • 签名可以防止报文被窜改,如果报文被篡改,那么篡改者没有私钥伪造不出来内容修改后的校验和。

发送端A、接收端B之间使用签名的逻辑

  • A将变长的报文提取为定长的摘要
  • A使用私钥对这些摘要计算签名,并附加在需要发送报文的尾部
  • B接收到报文,需要验证报文是A写的并且没被篡改,B使用公钥的反函数,可以得到报文的摘要,然后就是对比签名的摘要和报文的摘要是否一致。

5、数字证书:包含某个受信任组织的担保的用户或公司的相关信息,一般包含 对象的名称、过期时间、证书发布者、来自证书发布者的数字签名。任何人都可以创建一个数字证书,证书也是由私钥创建,但是不是都可以获得证书签发权,证书的格式没有统一的规范。

6、数字证书的作用:通过HTTPS建立一个安全的Web事务之后,现代的浏览器都会自动获取所连接服务器的数字证书,如果服务器没证书,那么安全连接就会失败,证书中包含很多字段

  • Web站点的名称和主机名
  • Web站点的公开密钥
  • 签名颁发机构的名称
  • 来自签名颁发机构的签名

浏览器如果收到证书是会对签名颁发机构进行检查,

  • 如果这个机构是个很有权威的,浏览器之前已经安装过很多著名的办法机构证书信息,浏览器可能已经知道当前证书对应的的公钥了,直接验证验证证书签名即可。
  • 如果这个机构不被浏览器知道,签发机构是本地的IT部门或者其他软件厂商,那么浏览器应该通常会像用户显示一个对话框,看看是否需要信任。

7、HTTPS细节介绍

  • 由于SSL安全层的存在, HTTP应用层在将报文发给TCP之前,先将其发送给一个安全层,对其进行加密。
  • HTTP对应的端口为443,客户端会打开一条443的通道,然后进行握手,以二进制格式与服务器交换一些SSL安全参数,并附加上加密的HTTP命令。正是因为这样,需要和HTTP的80端口区分,否则大部分Web服务器会将二进制的SSL流量理解为错误的HTTP并关闭连接。
  • SSL第一次握手,首先打开443端口的通道,一旦建立TCP连接,客户端和服务端就会初始化SSL层,对加密参数进行沟通,主要包含交换协议版本号,选择一个两端都了解的密码,对两端的身份进行认证也就是交换证书,最后交换密钥。
  • 某些虚拟主机(一台服务器上有多个主机名)站点上安全流量的处理有时候是很棘手的,有些流行的Web服务器只支持一个证书,当服务器证书列出的实际官方主机名和各个虚拟主机名不匹配,访问虚拟主机的时候,就会弹框警告提示。
  • OpenSSL:SSL是个复杂的二进制协议,很复杂,但是可以借助开源的OpenSSL来实现一个简单的HTTPS客户端。