http超详解

总览

第一部分:HTTP基础及概念

什么是HTTP?
HTTP相关的一些概念及技术简介
HTTP的报文结构

第二部分:HTTP进阶

HTTP协议的特点
HTTP的优缺点分析
HTTP报文中的body(头字段)
HTTP传输大文件的方法
HTTP的连接管理
HTTP的重定向和跳转
HTTP的Cookie机制
HTTP的缓存控制
HTTP的代理服务
HTTP的缓存代理
HTTP与CDN

第一部分:HTTP基础及概念

一.什么是HTTP?

一.到底什么是HTTP?
HTTP,(Hyper Text Transfer Protocol,超文本传输协议)
我们首先从名字入手,来刨析一下,http协议到底是用来干什么的!
(1)协议:使用计算机能够理解的语言确立了一种计算机之间进行交流通信的规范,以及相关的各种控制和错误处理方式

(2)传输:顾名思义,就是将物体X,从地点A运送到地点B,在计算机世界中运送的物体就是数据了
不过需要注意的是,数据虽然在A和B之间传输,但是并没有限制A和B两个角色,允许中间有中转或者接力
即在直观的(A------B)通信背后,其实真正的通信线路可能是(A—C---D—B),这里C和D也都遵从HTTP协议,可以看作是整个通信过程的中间人。整个传输过程中只要不打扰基本的数据传输,就可以添加任意的额外功能,例如安全认证,数据压缩,编码转换等来优化整个传输过程

(3)超文本:首先来看一下什么是文本
文本:表示HTTP传输的不是TCP/UDP这些底层协议里被切分的杂乱无章的二进制包,而是完整的,有意义的数据,可以被浏览器,服务器这样的上层应用程序处理

互联网早期,文本只是简单的字符文字,但发展到现在,“文本”的涵义已经被大大的扩展了,图片,音频,视频甚至是压缩包,在HTTP眼里都可以算作是“文本”

所谓超文本,就是超越了文本的普通文本,它是文字,图片,音频和视频等的混合体,最最最关键的是含有“超链接”能够从一个“超文本”跳跃到另一个“超文本”形成的复杂的非线性,网络状的结构

对于“超文本”我们最熟悉的应该就是HTML了,它本身只是纯文字文件,但内部用很多标签定义了对图片,音频,视频的链接,再经过浏览器的解释,呈现在我们面前的就是一个含有多种视听信息的页面

通过上述,我们即可以总结HTTP倒是是个什么东西了!
*HTTP,在计算机世界里专门在两点之前传输文字,图片,音频,视频等超文本数据的约定和规范

二.对HTTP的误解
我们经常会对HTTP产生各种各样的误解!下面我们对常见的误解进行“拨乱反正!”
1.HTTP不是互联网!
互联网是基于全球的许多网络互相连接形成的巨大的国际网络,在它上面存放着各式各样的资源,也对应着各式各样的协议,例如超文本资源使用HTTP,普通文件使用FTP,电子邮件使用SMTP,POP3等

2.HTTP不是HTML
HTML是超文本的载体,是一种标记语言,使用各种标签描述文字,图片,超链接等资源,并且可以嵌入CSS,JAVA,Script等技术实现复杂的动态效果

二.与http相关的一些概念及技术简介

一.与HTTP相关的一些概念
下面介绍几个常见的与HTTP息息相关的概念
(1)浏览器
浏览器的正式名字叫做“Web Browser”,网页浏览器。它其实是我们查看互联网上网页资源的应用程序,名字里的Web,实际上指的是WWW万维网

浏览器本质上是一个HTTP协议中的请求方,使用HTTP协议获取网络上的各种资源,除此之外,他还集成了很多额外的功能

比如
HTML 排版引擎用来展示页面,Java Script引擎用来实现动态化效果,甚至还有开发者工具用来调试网页,以及各种插件和扩展

在HTTP协议里,浏览器的角色被称为User Agent,即用户代理,意思是作为访问者的“代理”来发起HTTP请求,不过在不引起混淆的情况下,称之为客户端

(2)CDN
浏览器和服务器是HTTP协议的两个端点,那么在两者之间还有别的什么东西吗?

浏览器通常不会直接连接到服务器,中间会经过很多“关卡”,其中的一个重要角色就叫做CDN

CDN全称,Content Delivery Network 翻译过来就是内容分发网络,它应用了HTTP协议里的缓存和代理技术,来代替源站响应客户端的请求

CDN的好处,简单来说,它可以缓存原站的数据,让浏览器的请求不需要“千里迢迢”地到达源站服务器,直接在半路上就可以获取响应,如果CDN的调度算法很优秀,更可以找到离用户最近的节点,大幅度缩短响应时间

CDN也是现在互联网中的一项重要基础设施,除了基本的网络加速外,还提供负载均衡,安全防护,边缘计算,跨运营上网络等功能,能够成倍地“放大”源站服务器的服务能力,很多云服务上都把CDN作为产品的一部分

(3)爬虫
前面讲,浏览器是一种用户代理,代替我们访问互联网,但HTTP协议并没有规范用户代理后面必须是真正的人类,他也完全可以是“机器人”,这些机器人的正式名称就叫做“爬虫”,实际上是一种可以访问Web资源的应用程序

(4)HTML
HTTP协议传输的主要内容之一,它描述了超文本页面,用各种“标签”定义文字,图片等资源和排版布局 ,最终由浏览器“渲染”出可视化页面

(5)WAF
WAF:网络应用防火墙,与硬件“防火墙类似”,是应用层面的“防火墙”,专门检测HTTP流量,是防护WEB应用的安全即使

WAF通常位于WEB服务器之前,可以阻止如SQL注入,跨站脚本等攻击

二.URI和URL
URI(Uniform Resource Identifier,统一资源标识符)是http中一个非常重要的一个概念它唯一标记了互联网上的资源

URI另一个更常用的表现形式是URL(Uniform Resource Locator,统一资源定位符),即俗称的网址,它实际是URI的一个子集,这两者几乎是相同的,差异不大,差异在此处就不在介绍了

下面我们以nginx的官网为例

 http://nginx.org/en/download.html

这是一个URI,主要有三个基本的部分构成
1.协议名:即访问该资源应当使用的协议,这里是http
2.主机名:即互联网上主机的标记,可以是域名或者IP地址,这里是nginx.org
3.路径:即资源在主机上的位置,使用“/”分隔多级目录,这里是“/en/download.html”

三.什么是https
http有一非常致命的缺点就是它传输的报文是明文传输的,如果传输信道被不法分子监听了那么基本上相当于所有信息都被别人看去了,因为明文传输的数据没有任何加密处理,一看就知道传输的内容是什么了

https是http的加密模式,全称为HTTP over SSL/TLS,也就是运行在SSL/TLS协议上的HTTP

SSL/TLS是一个负责加密通信的安全协议,建立在TCP/IP之上,也是个可靠的传输协议,可以被用作HTTP的下层协议

HTTPS相当于HTTP+SSL/TLS+TCP/IP
HTTP就是HTTP+TCP/IP

SSL:Secure Socket Layer,安全套接字层
TLS:Transport Layer Security,传输层安全
SSL发展到3.0时被标准化,改名为TLS

SSL使用了许多密码学最先进的研究成果,综合了对称加密,非对称加密,摘要算法,数字前面,数字证书等技术,能够在不安全的环境中为通信的双方创建出一个密码的,安全的传输通道,为HTTP套上一副坚固的盔甲

四.http代理
代理(Proxy)是HTTP协议中请求方和应答方中间的一个环节,作为“中转站”,既可以转发客户端的请求,也可以转发服务器的应答

代理的种类
(1)匿名代理:完全隐匿了被代理的机器,外界看到的只是代理服务器

(2)透明代理:顾名思义,他在传输过程中是“透明开放”的,外界即知道代理,也知道客户端

(3)正向代理:靠近客户端,代表客户端向服务器发送请求

(4)反向代理:靠近服务器端,代表服务器响应客户端的请求

CDN和代理的关系
CDN实际上就是一种代理。它替源站服务器响应客户端的请求,通常扮演着透明代理和反向代理的角色

代理可以做的事情
(1)负载均衡:把请求均匀分散到多台机器,实现访问集群化

(2)内容缓存:暂存上下行数据,减轻后端的压力

(3)安全防护:隐匿IP,使用WAF等工具抵御网络攻击,保护被代理的机器

(4)数据处理:提供压缩,加密等额外的功能

五.DNS

DNS的应用
许多大公司,网络运行上都会建立自己的DNS服务器,作为用户DNS查询的代理,代替用户访问核心DNS系统。这些DNS服务器被称为“非权威域名服务器”,可以缓存之前的查询结果,如果已经有了记录,就无需再向根服务器发起查询,直接返回对应的IP地址

DNS实现负载均衡的方式
1.因为域名解析可以返回多个IP地址,所以一个域名可以对应多台主机,客户端收到多个IP地址后,就可以使用轮询算法向服务器发起请求,实现负载均衡

2.域名解析可以配置内部的策略,返回离客户端最近的主机,或者返回当前服务质量最好的主机,这样在DNS端把请求分到到不同的服务器,实现负载均衡

与DNS相关的一些恶意行为
1.域名屏蔽:对域名直接不解析,返回错误,让你无法拿到IP地址,也就无法访问网站

2.域名劫持:也叫做域名污染,你要访问A网站,但DNS给了你B网站

三.http的报文结构

一.http协议格式
按层次来分
1.首先http有两大类格式,分别是Request(请求)报文和Response(应答)报文
2.以Request报文来说,整个报文的结构可以由三部分构成,分别是请求行请求头空行实体部分空行
3.以Response报文来说,整个报文的结构同样也可以由三部分构成,分别是应答行应答头空行实体部分
在这里插入图片描述
下面我们简单分析一个HTTP的请求报文
在这里插入图片描述
以上图为例,我们简单分析一下请求报文的结构
1.首先是请求行,请求行由请求方法URL字段协议版本三个字段构成
POST /cgi-bin/httpconn HTTP/1.1
(1) POST为请求方法(下面会有详细的讲解)
(2)/cgi-bin/httpconn为要请求的URL字段
(3)HTTP/1.1为协议版本

2.请求行之后便是请求头部分
在这里插入图片描述
Host:表示我们要访问的IP地址
Accept:表示可以接受的文件的类型
Connection:表示选择连接的方式
Cache-Control:表示与缓存有关的选项
下面会对这些选项进行较为详细的讲解

3.空行
这里体现不出来,主要作用是将数据头和数据体分开,空行之下就是数据体了

4.数据体
在这里插入图片描述

以请求报文为例,整个请求报文的结构和功能可以表述如下
请求行-----告诉对端我要干什么?(方法),对端是谁(URL),如何通信(HTTP版本)
请求头------对请求的数据做出具体的诠释和要求
请求体------请求附带的数据,如要上传文件时即方法字段为POST时,请求体中的数据就是要上传的文件,当方法字段为GET时为空,

然后再分析一个HTTP的应答报文
在这里插入图片描述
1.首先是响应行,响应行由协议版本状态码,及描述组成
HTTP/1.1 200 OK
HTTP/1.1就是协议版本,200是状态码,OK则是对他的描述,有关状态码的问题,下面会详细的进行介绍

2.响应头
在这里插入图片描述
Content- Type:表示后面的文档属于什么MIME类型
Connection:告知连接方式
有关响应头的详细信息下面也会做出详细的解释

3.响应体
响应体就是响应的消息体,如果是纯数据就是返回纯数据,如果是HTML页面,那么返回的就是HTML页面代码,如果是JS代码就是JS代码

整个响应报文的结构和功能可以表述如下
响应行-----告诉请求方如何通信?(HTTP版本),对请求方的请求做出回应(状态码),对做出的回应进行描述(描述)
响应头------涉及具体的响应条目
请求体------对请求方请求做出的最具体的应答,可以是纯数据,也可以是代码

二.HTTP Method(方法)
HTTP报文的基本结构可以看作header+body构成。请求头里有请求方法和请求目标,响应头里有状态码和描述短语(通常是对无法正常进行应答的解释)

HTTP设计时的定位,使用HTTP建立了一个超链接文档系统,使用URI来定位这些文档,也就是资源,如何在协议里操作这些资源就是请求方法要解决的问题!它实际的含义就是客户端发出一个动作指令,要求服务器端对定位的资源执行这个动作

以下是常见的一些方法

GET:获取资源,可以理解为读取或者下载资源
HEAD:获取资源的元信息
POST:向资源提交数据,相当于写入或上传数据
PUT:类似POST
DELETE:删除某些资源
CONNECT:建立特殊的连接隧道
OPTIONS:列出可对资源实行的方法

其中GET,POST,HEAD,PUT是常用请求。GET和POST是最知名的请求方法,也是用的最多的两种方法

1.GET
它的含义是请求从服务器获取资源,这个资源既可以是静态的文本,页面,图片,视频也可以是由PHP,JAVA动态生成的页面或者其他格式的数据

GET方法虽然基本动作比较简单,但搭配URI和其他头字段就能实现对资源更精细的操作

2.HEAD
方法与GET方法类似,也是从请求服务器获取资源,服务器的处理机制也是一样的,但服务器不会返回请求的实体数据,只会传回响应头,也就是资源的元信息

HEAD方法可以看作是GET方法的一个简化版,或者轻量版。因为它的响应头与GET完全相同,所以可以用在很多并不算真正需要资源的场合,避免传输body数据的浪费

比如,想要检查一个文件是否存在,只要发个HEAD请求就可以了,没有必要用GET把真个文件都取下来,再比如,要检查文件是否有最新版本,同样也应该用HEAD,服务器会在响应头里把文件的修改时间传回来

3.POST/PUT
POST和PUT向URI指定的资源提交数据,数据就放在报文的body里

POST也是一个经常用到的请求方法,使用频率应该是仅此与GET,应用的场景也很多,只要向服务器发送数据,用到的大多数都是POST

POST通常表示的是新建,crate的含义
PUT则是修改,update的含义

4.DELETE
指示服务器删除资源,因为这个动作危害性特别打,所以通常服务器不会执行真正的删除操作,而是对资源做一个删除标记,当然,更多的时候服务器就直接不处理DELETE请求

5.CONNENT
比较特殊的方法,要求服务器为客户端和另一台远程服务器建立一条特殊的连接隧道,这时WEB服务器在中间充当了代理的角色

6.OPTIONS
该方法要求服务器列出可对资源实行的操作方法,在响应头的ALLOW字段里返回。它的功能有限,用处也不大

三.响应状态码
服务器收到请求报文,解析后需要进行处理,具体的业务逻辑多种多样,但最后必定是拼出一个响应报文发回客户端

下面介绍常见的状态码所代表的含义

1XX:提示信息,表示目前是协议处理的中间状态,还需要后续的操作

2XX:成功,报文已经接受到并被正确处理

3XX:重定向,资源位置发生变动,需要客户端重新发送

4XX:客户端错误,请求报文有误,服务器无法处理

5XX:服务器错误,服务器在处理请求时内部发生了错误

(1)2XX详解
200 OK ,是最常见的成功状态码,表示一切正常,服务器如客户端所期望的那样返回了处理结果,如果是非HEAD请求,通常在响应头后都会有body数据

204 NO Content,是另一个很常见的成功状态码,它的含义与 “200 OK”基本相同,但响应头后没有body数据,所以对于WEB服务器来说,正确地区分200和204是必要的

206 Partial Content, 是HTTP分块下载或者断点续传的基础,在客户端发送“”范围请求,要求获取资源的部分数据时出现,他与200一样,也是服务器成功处理了请求,但body里的数据不是资源的全部,而是其中的一部分

(2)3XX详解
301 Moved Permanently ,俗称永久重定向,含义是此次请求的资源已经不存在了,需要改用新的URI再次访问,

302 Found , Moved Temporaily,俗称临时重定向,意思是请求的资源还在,但需要暂时用另一个URI来访问

301和302都会在响应头里使用字段Location指明后续要跳转的URI,最终的效果很相似,浏览器都会重定向到新的URI,两者的根本区别在于 一个是永久 一个是临时,所以在场景,用法上差距很大

(3)4XX详解
400 Bad Request:是一个同样的错误码,表示请求报文有错误,但具体是数据格式错误,还是URI超长它没有明确说,只是一个笼统的错误,客户端看到400只会是“一头雾水”,“不知所措”,所以在开发WEB应用是应当尽量避免给客户端返回400,而是要使用其他更具明确含义的状态码

403 : Forbidden ,实际上不是客户端的请求出错,而是表示服务器禁止访问资源,原因可能多种多样,例如信息敏感,法律禁止等,如果服务器友好一点,可以在body里详细说明拒绝请的原因

404:NOT Found:原意是资源在本服务器上未找到,所以无法提供给客户端。但现在已经被“用滥了”,只要服务器“不高兴”就可以给出个404,而我们也无从得知后面到底是什么别的原因

(4)5XX详解
500通用错误码

501,表示客户端请求的功能还不支持,这个错误码比500要温和

502,通常是服务器作物网关或者代理是返回的错误码,表示服务器自身工作正常,访问后端服务器时发生了错误

503 ,Service Unavailable 表示服务器当前很忙,暂时无法响应服务,我们上网时有时候遇到的“网络服务正忙。请稍后重试”

第二部分:HTTP进阶

HTTP协议的特点

·灵活可扩展
·可靠传输
·应用层协议
·请求-应答的通信模式
·无状态

一.灵活可扩展
HTTP的灵活可扩展体现在HTTP的功能并没有被写死,可以由开发者对其进行添加新的功能

起初HTTP的功能是非常少的,后来不断的进行完善,加入了请求方法,状态码的定义(状态码是三位数的这一事实从一定程度上可以佐证是预留出了状态码来标记后来可能会出现的目前还未知的状态)

通过请求头中各种请求字段的定义可以丰富整个传输的功能性和提高性能

二.可靠传输
HTTP是一个可靠的传输协议

这个特点显而易见,**因为HTTP协议是基于TCP/IP协议栈的,**而TCP本身就是一个可靠的传输协议,所以HTTP自然也就继承了这个特性,能够再请求方和应答方之间可靠地传输数据

它的具体做法与TCP/UDP差不多,都是对实际传输的数据做了一层包装,加上了一个头,然后调用Socket API,通过TCP /IP协议栈发送或者接收

三.应用层协议
HTTP协议是一个应用层的协议

在TCP/IP诞生后的几十年里,虽然出现了许多的应用层协议,但他们都仅关注很小的应用领域,局限在很少的应用场景。例如FTP只能传输文件,SMTP只能发送邮件,SSH只能远程登录等,在通用数据传输方面,没有很好的体现

而HTTP协议在通用数据的传输方面做的是非常好的,它既可以传输纯文本的数据,也可以传输视频,音频图片等类型的数据

四.请求-应答
HTTP协议使用的是请求-应答模式

这个请求-应答模式是HTTP协议最根本的通信模型,通俗来讲就是“一发一收”,“有来有去”,就像是写代码时的函数调用,只要填写好请求头里的字段,“调用”后就会收到答复

请求-应答模式也明确了HTTP协议里通信双方的定位,永远是请求方先发起连接和请求,是主动的,而应答方只有在收到请求后才能答复,是被动的,如果没有请求时不会有任何动作

当然,请求方和应答方的角色也不是绝对的,在浏览器-服务器的场景里,通常服务器都是应答方,如果将他用作代理连接后端服务器,那么他就可能同时扮演请求方和应答方的角色

HTTP的请求-应答模式也恰好契合了传统的C/S系统架构,请求方作为客户端,应答方作为服务器。所以,随着互联网的发展就出现了 B/S (Browser/Server)架构,用轻量级的浏览器代替笨重的客户端应用,用轻量级的浏览器代替笨重的客户端应用,实现零维护的“瘦”客户端,而服务器则摒弃私有通信协议转而使用HTTP协议

此外,请求-应答模式也完全符合 RPC(Remote Procedure Call,远程系统调用)的工作模式,可以把HTTP请求处理封装成远程函数调用

五.无状态
HTTP协议是一个无状态的协议

所谓的”状态“应该如何去理解呢?

“状态”其实就是客户端或者服务器里保存的一些数据或者标志,记录了通信过程中的一些变化信息

我们所知道的,TCP协议是有状态的,一开始处于Closed状态,连接成功后是ESTABLISHED状态,断开连接后是FIN-WAIT状态,最后又是CLOSED状态

这些“状态”就需要TCP在内部使用一些数据结构去维护,可以简单地想象成是个标志量,标记当前所处的状态,例如0是ClOSED,2是ESTABLISHED等等

再来看HTTP,那么对比TCP就可以看出,整个协议里没有规定任何的“状态”,客户端和服务器永远是在一种“无知”的状态,建立连接前两者互不知情,每次收发的报文也都是互相独立的,没有任何的联系,收发报文也不会对客户端或服务器产生任何影响,连接后也不会要求保存任何信息

**“无状态”形象地说来时“没有记忆能力”。**比如,浏览器发了一个请求,说“我是小明,请给我A文件”,服务器收到报文后就会检查一下权限,看小明确实可以访问A文件,于是把文件发回给浏览器,接着浏览器还想要B文件,但服务器不会记录刚才的请求状态,不知道第二个请求和第一个请求是同一个浏览器发来的,所以浏览器必须还得重复一次自己的身份才行:“我是刚才的小明,请再给我B文件”

HTTP的优缺点分析

一.优点之简单,灵活,易于扩展
首先HTTP最重要也是最突出的优点是:”简单,灵活,易于扩展“

简单:其简单,最直观的一个体现就是它的基本报文格式就是”header+body“,头部信息也是简单的文本格式,用的也都是常见的英文单词

灵活和易于扩展: 这两者实际上一体的,他们互为表里,相互促进,因为“灵活”所以才会“易于扩展”,而“易于扩展”又反过来让HTTP更加灵活,拥有更强的表现能力

HTTP协议里的请求方法,URI,状态码,头字段等每一个核心组成要素都没有被写死,允许开发者任意定制,扩充或解释,给予了浏览器和服务器最大程度的新人和自由,也正好符合了互联网“自由与平等”的精神----缺什么功能自己加个字段或者错误码什么的补上就是了

二.双刃剑之无状态
无状态对于HTTP而言可以算的是一把双刃剑了!下面来分析一下它的利,害分别是什么!

1.优点----提高服务器性能的利用率
因为服务器没有”记忆能力“,所以就不需要额外的资源来记录状态信息,不仅实现上会简单一些,而且还能减轻服务器的负担,能够把更多的CPU和内存用来对外提供服务

2.缺点----对某些连续的请求的支持不好
既然服务没有记忆能力,他就无法支持需要连续多个步骤的“事务”操作。例如电商购物,首先要登录,然后添加购物车,再下单,结算,支付,这一系列操作都需要知道用户的身份才行,但“无状态”服务器是不知道这些请求时相互关联的,每次都得问一遍身份信息,不仅麻烦,而且还增加了不必要的数据传输量

为了应对HTTP的无状态带来的一些问题,所以就出现了Cookie这个技术,下面将会详细的对Cookie这个技术进行讲解

三.明文传输的利与弊
”明文传输“的意思就是协议里的报文(准确的说是header部分)不使用二进制数据,而是用简单可阅读的文本形式

1.优点
对比TCP,UDP这样的二进制协议,它的优点显而易见,不需要借助任何外部工具,用浏览器,Wireshark,或者tcpdump抓包后,直接用肉眼就可以很容易地查看或者修改,未我们的开发调试工作带来极大的便利

2.缺点
明文传输的缺点是显而易见的,HTTP报文的所有信息都会暴露在”光天化日之下“,在漫长的传输链路的每一个环节上都毫无隐私可言,不坏好意的人只要入侵了这个链路里的某个设备,简单地“旁路”一下流量,就可以实现对通信的窥视

3.存在的安全隐患
黑客就是利用了HTTP明文传输的缺点,在公共场所架设一个WIFI热点开始“钓鱼”,诱骗网民上网,一旦你连上了这个Wifi热点,所有的流量都会被截获保存,里面如果有银行卡号,网站密码等敏感信息的话那就很危险了

四.不安全
与明文缺点相关但不完全等同的另一个缺点就是”不安全“

安全有很多方面,明文只是”机密“方面的一个缺点,在”身份认证“和”完整性校验“这两方面HTTP也是非常欠缺的

身份认证:简单讲就是”怎么证明你就是你!“
HTTP没有提供有效的手段来确认通信双方的真实身份。虽然协议里有一个基本的认证机制,但因为刚才所说的明文传输的缺点,这个机制可以说完全起不到作用,非常容易被攻破

如果仅使用HTTP协议,很有可能你会连接到一个页面一模一样但却是个假冒的网站,然后再被“钓”走各种私人信息(证书问题

虽然银行可以用MD5,SHA1等算法给报文加上数字摘要,但还是因为“明文”这个致命缺点,黑客可以连同摘要一同修改,最终还是判断不出报文是否被篡改

为了解决HTTP不够安全的特点,所以就出现了HTTPS,这个在下面会继续讲到

五.HTTP的性能
HTTP协议**基于TCP/IP,并且使用了”请求-应答“的通信模式,**所以性能的关键就在这两点上

必须要说的是,TCP的性能是不差的,否则也不会纵横互联网江湖四十年。而且他已经被研究的很透,集成在操作系统内核里经过了细致的优化,足以应付大多数的场景

但是现在互联网的特点是移动和高并发,有时候不能保证稳定的连接质量,所以在TCP层面上HTTP协议有时候就会表现的不够好

而”请求应答“模式则加剧了HTTP的性能问题,这就是著名的队头阻塞

队头阻塞:当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一并被阻塞,会导致客户端迟迟收不到数据

HTTP报文中的body(头字段)

一.数据类型和编码
在TCP/IP协议栈里,传输基本都是header+body的格式,但TCP,UDP是传输层的协议,不会关心body数据是什么,只要把数据发送到对方就算是完成了任务

而HTTP协议则不同,他是应用层的协议,数据到达之后,工作只能说完成了一半,还必须要告诉上层应用这是什么数据才行,否则上层应用就会不知所措

所以,在通信过程中,通信的两端,必须要协商好数据的类型

那么在HTTP中是如何来标记和协商数据类型的呢?

为了解决数据类型的问题,HTTP借用了电子邮件系统中的一个解决方案-----多用途互联网邮件扩展(MIME)

MIME是一个很大的标准规范,但HTTP只“顺手牵羊”取了其中的一部分,用来标记body的数据类型,这就是我们平常总能听到的”MIME type

MIME把数据分成了八大类,每个大类下再细分出多个子类,形式是“type/subtype”的字符串

下面简单介绍一下HTTP里常见的几种类别

1.text:即文本格式的可读数据,最熟悉的就是text/html了,表示超文本文档,此外还有纯文本 text/plain,样式表text/css等

2.image:即图像文件,有image/gif,image/jpeg,image/png等

3.audio/video:音频和视频数据,例如audio/mpeg,video/MP4等

4.application:数据格式不规定,可能是文本也可能二进制,必须由上层应用程序来解释,常见的有 application/json ,application/javascript,application/pdf等,另外如果实在不知道数据是什么类型,就会是application/octet-stream,即不透明的二进制数据

但仅有MIME TYPE还不够,因为HTTP在传输时为了节约带宽,有时候还会压缩数据,因此,还需要一个Encoding type 告诉数据是用的什么编码格式,这样对方才能正确解压缩,还原出原始的数据

比起MIME type来说,Encoding type就少了很多,常用的只有下面三种:

1.gzip:GNU zip压缩格式,也是互联网上最流行的压缩格式

2.deflate:zlib(deflate)压缩格式,流行程度仅此于gzip

3.br:一种专门为HTTP优化的新压缩算法

数据类型使用的头字段

有了MIME type和Encoding type 。无论是浏览器还是服务器都可以轻松识别出body的类型,也就能正确处理数据了

HTTP协议为此定义了两个Accept请求头字段和两个Content实体头字段,用于客户端和服务器进行”内容协商“” 也就是说客户端用Accept头告诉服务器希望接收什么样的数据,而服务器用Content头告诉客户端实际发送了什么样的数据

Accept头字段
Accept字段标记的是客户端可理解的MIME type可以用“,”做分隔列出多个类型,让服务器有更多的选择余地,例如下面的头

Accept:text/html,application/xml,image/webq,image/png

这就是告诉服务器:我能够看懂,HTML,XML的文本还有webp和png的图片,请给我这四类格式的数据

相应的,服务器会在响应报文里用头字段Content-Type高数实体数据的真实类型

Content-Type:text/html

这样浏览器看到报文里的类型是“text/html”就知道是HTML文件,会调用排版引擎渲染出页面,如果看到image/png就知道是一个PNG文件,就会在页面上显示图像

Accept-Encoding头字段
Accept-Encoding字段标记的是客户端支持的压缩格式,例如上面说的gzip,deflate等,同样也可以用“,”分隔开来列出多个,服务器可以选择其中一种来压缩数据,实际使用的压缩格式放在响应头字段Content-Encoding

Accept-Encoding:gzip,deflate,br
Content-Encoding:gzip

不过这两个字段是可以省略的,如果请求报文里没有Accept-Encoding字段,就表示客户端不支持压缩格式,如果响应报文里没有Content-Encoding字段,就表示响应数据没有被压缩

二.语言类型与编码
MIME type和Encoding type解决了计算机理解body数据的问题,但互联网遍布全球,不同国家不同地区的人使用了很多不同的语言,虽然都是text/html,但如何让浏览器显示出每个人都可理解可阅读的语言文字呢?

为了解决这个问题,HTTP采用了与数据类型相似的解决方案,又引入了两个概念:语言类型,和字符集

所谓的语言类型就是人类使用的自然语言,例如英语、汉语、日语等,而这些自然语言可能还有下属的地区性方盲,所以在需要明确区分的时候也要使用"type-subtype"的形式,不过这
里的格式与数据类型不同,分隔符不是“/”,而是”-“

举几个例子:en表示任意的英语,en-US表示美式英语,en-GB表示英式英语,而zh-CN就表示我们最常使用的汉语

关于自然语言的计算机处理还有一个更麻烦的东西叫做“字符集”

不同的语言有不同的编码方式,为了方便开发者和提高用户的体验,出现了Unicode和UTF-8,把世界上所有的语言都容纳在一种编码方案里,UTF-8也成为了互联网上的标准字符集

语言类型使用的头字段

Accept-Language:浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到。

Accept-Language:zh-CN,zh,en

这个请求告诉服务器:“最好给我zh-CN的汉语文字,如果没有就用其他的汉语方言,如果还没有就给英文”

Content-Language:服务器实际提供的语言种类

Content-Language:zh-CN

Accept-Charset:浏览器可接受的字符集。
响应头里没有对应的Content-Charset,而是在Content-Type字段的数据类型

HTTP传输大文件的方法

一.数据压缩
上面我们讲到了,数据类型与编码时,提到了数据压缩的概念,显而易见当我们传输一个大数据时,如果在传输之前先把大数据压缩成较小的数据再进行传输,因为在本地对数据压缩和解压缩的时间和在链路上传输的时间相比,通常是比较小的。同时也降低了消耗的带宽

但是数据压缩也存在一定的问题,对于gzip等压缩算法来说,通常只对文本文件有较好的压缩率,而图片,音频视频等等多媒体的数据本身就已经是高度压缩的,再用gzip处理也不会变小(甚至还有可能增大一点),所以遇到这种情况,数据压缩就失效了

二.分块传输
压缩是把大文件整体变小,我们可以反过来思考,如果大文件整体不能变小,那就把它“拆开”,分解成多个小块,把这些小块分批发给浏览器,浏览器收到后再组装复原

这样浏览器和服务器都不用在内存里保存文件的全部,每次只收发一小部分,网络也不会被大文件长时间占用,内存,带宽资源也就节省下来了

这种“分段”的思路在HTTP协议里就是“chunked”分块传输的编码,在响应报文里用头字段Transfer-Encoding:chunke来表示,意思是报文里的body部分不是一次性发过来的,而是分成了许多的块(chunk)逐个发送, 在接受端再将每个分块拼接起来

分块传输也可以用“流式数据”例如由数据库动态生成的表单页面,这种情况下body数据的长度是未知的,无法在头字段“Content-Length”里给出确切的长度,所以也只能用chunk方式分块发送

Transger-Encoding:chunked 和 Content-Length这两个字段是互斥的,也就是说响应报文里这两个字段不能同时出现,一个响应报文的传输要么是长度已知,要么是长度未知,这一点一定要记住
在这里插入图片描述
三.范围请求
有了分款传输编码,服务器就可以轻松地收发大文件了,但对于上G的超大文件,还有一些问题需要考虑

比如,我们在看电影时,像跳过片头直接看正片,或者想拖动进度条,这实际上是想获取一个大文件其中的片段数据,而分块传输并没有这个能力

HTTP协议为了满足这样的需求,提出了“范围请求”的概念,允许客户端在请求头里使用专用字段来表示只获取文件的一部分,相当于是客户端的“化整为零”

范围请求不是WEB服务器必备的功能,可以实现也可以不实现,所以服务器必须在响应头里使用字段“Accept-Ranges:bytes”明确告知客户端:“我是支持范围请求的”

如果不支持的话,服务器可以发送 Accept-Range:none或者干脆不发送“Accept-Ranges”字段,这样客户端就认为服务器没有实现范围请求功能,只能老老实实地收发整块文件了

请求头Range是HTTP范围请求的专用字段,格式是bytes=x-y,其中的x和y是以字节为单位的数据范围

注意 x,y表示的是“偏移量”,范围必须从0计数,例如前10个字节表示为“0-9”,第二个十字节表示为10-19,而“0-10”实际上是前11个字节

服务器收到Range字段后,需要做四件事

第一,它必须检查范围是否合法,比如文件只有100个字节,但请求200-300这就是范围越界了,服务器就会返回状态码416,意思是范围请求有误,无法处理

第二,如果范围正确,服务器就可以根据Range头计算偏移量,读取文件的片段了,返回状态码206 Partial Content,和200的意思差不多,但表示body只是原数据的一部分

第三,服务器要添加一个响应头字段 Content-Range,告诉片段的实际偏移量和资源的大小,格式是“bytes x-y/length”,与Range头区别在没有“=”范围后多了总长度,例如,对于“0-10”的范围请求,值就是bytes 0-10/100

最后剩下的就是发送数据了,直接把片段用TCP发给客户端,一个范围请求就算是处理完了

HTTP的连接管理

一.短连接,长连接

短链接

​ HTTP协议最初是个非常简单的通信协议,通信过程也采用了简单的“请求-应答”方式

它底层的数据传输基于TCP/IP,每次发送请求前需要先与服务器建立连接,收到响应报文后立即关闭连接

因为客户端与服务器的整个连接过程很短暂,不会与服务器保持长时间的连接状态,所以就被称为“短连接”。早期的HTTP协议也被称为是“无连接”的协议

短连接的缺点相当严重,因为在TCP协议里,建立连接和关闭连接都是非常“昂贵”的操作。TCP建立连接要有“三次握手” 发送3个数据包,需要一个RTT,关闭连接时“四次挥手”,4个数据包需要两个RTT

而HTTP的一次简单“请求-响应”通常只需要4个包,如果不算服务器内部的处理时间,最多是2个RTT,这么算下来,浪费的时间就是“3/5=60%”,有三分之二的时间被浪费掉了,传输效率很低

长连接
针对短连接暴露出的缺点,HTTP协议就提出了“长连接”的通信方式,也叫“持久连接(persistent connections )”,“连接保活(keep alive)”,“连接复用”(connection reuse)

其实解决办法也很简单,用的就是“成本均摊”的思路,既然TCP的连接和关闭非常耗时间,那么九八这个时间成本由原来的一个“请求-应答”上。这样虽然不能改善TCP的连接效率,但基于“分母效应”,每个“请求-应答”的无效时间就会降低不少,整体传输效率就提高了

二.与连接相关的头字段

Connection:keep-alive

由于长连接对性能的改善效果非常的明显,所有在HTTP/1.1中的连接都会默认启用长连接。不需要用什么特殊的头字段指定,只要向服务器发送了第一次请求,后续的请求都会重复利用第一次打开的TCP连接,也就是长连接,在这个连接上收发数据

当然,我们也可以在请求头里明确地要求使用长连接机制,使用的字段是Connection值是keep-alive

不过不管客户端是否显式要求长连接,如果服务器支持长连接,他总会在响应报文里放一个Connection:keep-alive字段,告诉客户端:“我是支持长连接的,接下来就用这个TCP一直收发数据吧”

但长连接存在着一定的缺陷

  1. 因为TCP连接长时间不关闭,服务器必须在内存里保存它的状态,这就占用了服务器的资源。如果有大量的空闲长连接只连不发,就会很快耗尽服务器的资源,导致服务器无法为真正有需要的用户提供服务

-----因此,长连接也需要在恰当的时间关闭,不能永远保持与服务器的连接,这在客户端或者服务器都可以做到

  1. 在客户端,可以在请求头里加上“connection:close”字段,告诉服务器:“这次通信之后就关闭连接”,服务器看到这个字段,就知道客户端要主动关闭连接,于是在响应报文里也加上这个字段,发送之后就调用Socket API关闭TCP连接

服务器端通常不会主动关闭连接,但也可以使用一些策略来关闭已经打开的连接,以nainx为例他有两种方式

1.使用“keepalive_timeout”指令,设置长连接的超时时间,如果在一段时间内连接上没有任何数据收发就主动断开连接,避免空闲连接占用系统资源

2.使用“keepalive_requeste”指令,设置长连接上可发送的最大请求次数,比如设置成1000,那么当Nginx在这个连接上处理了1000个请求后,也会主动断开连接

三.队头阻塞问题的解决

“队头阻塞”与短连接和长连接无关,而是由HTTP基本的“请求-应答”模型所导致的

因为HTTP规定报文必须是“一发一收”,这就形成了一个先进先出的“串行”队列,队列里的请求没有优先级的概念,只有入队的先后顺序,排在最前面的请求被最优先处理

如果队首的请求因为处理的太慢耽误了时间,那么队列里后面的所有请求也不得不跟着一起等待,结果就是其他的请求承担了不应有的时间成本
在这里插入图片描述

解决方案
因为“请求-应答”模型不能变,所以“队头阻塞”问题在HTTP/1.1里无法解决,只能缓解

HTTP采用“并发连接”的方式,也就是同时对一个域名,发起多个长连接,用数量来解决质量的问题

但这种方式也存在缺陷,如果每个客户端都想自己快,建立很多个连接,用户数 * 并发数就会非常的大,服务器的资源根本就无法应对,或者被服务器认为是恶意攻击,反而会造成“拒绝服务”

所以,HTTP协议建议客户端使用并发,但不能“滥用”并发,RFC2616里明确限制每个客户端最多并发2个连接。 后来提高到6~8

HTTP的重定向和跳转

一.跳转的过程分析(主动跳转)
加入我们点了百度上的某个链接,那么接下来会发生什么?

1.浏览器首先解析链接文字里的URI

2.再用这个URI发起一个新的HTTP请求,获取响应报文后就会切换显示内容,渲染出新URI指向的页面

这样的跳转动作是由浏览器的使用者主动发起的,可以称为“主动跳转”,但还有一类跳转是由服务器发来的,浏览器使用者无法进行控制,相对地可以被称为“被动跳转”,这在HTTP协议里有个专门的名词,叫做“重定向”

二.重定向跳转的过程(被动跳转)

一次重定向,实际上发送了两次的HTTP请求,第一个请求返回了302,然后第二个请求就被重定向到了“指定页面”

过程为:第一个请求返回的响应报文,里面有一个Location字段,他就是重定向跳转的目的URI

HTTP的Cookie机制

一.Cookie—给HTTP增加了记忆
上面我们讲到了,HTTP是无状态的协议,这样就会带来很多的问题,尤其是当客户端需要进行一系列连续的操作时会进行多次的身份验证从而造成性能的损失

为了解决这类问题,HTTP使用的方法是给每个客户端“一个标记(Cookie)”,这些标记只有服务器才能理解,需要的时候,客户端把这些标记(Cookie)一同发给服务器,服务器看到了标记,就能够认出对方是谁了!

二.Cookie的工作进程
与Cookie相关的两个头字段分别是响应头字段 Set-Cookie 和请求头字段 Cookie

1.当用户通过浏览器第一次访问服务器的时候,服务器肯定是不知道他的身份的。所以,就要创建一个独特的身份标识数据,格式就是“key=value”然后放进Set-Cookie,随着响应报文一同发送给浏览器

2.浏览器收到响应报文,看到里面有Set-Cookie,知道这时服务器给的身份标识,于是就保存起来,下次再请求的时候就自动把这个值放进Cookie字段里发给服务器

注意: 服务器有时会在响应头里添加多个Set-Cookie,存储多个KEY-VALUE,但浏览器这边发送时不需要用多个Cookie字段,只要在一行里用“;”隔开就行

在这里插入图片描述
从上图我们可以看出,Cookie是由浏览器负责存储的,而不是操作系统。所以,它是“浏览器绑定”的,只能在本浏览器内生效

三.Cookie的属性

Cookie就是服务器委托浏览器存储在客户端里的一些数据,而这些数据通常都会记录用户的关键识别信息。所以,就需要在“key=value”外,再用一些手段来保护,防止外泄或窃取,这些手段就是Cookie的属性

1.Cookie的生存周期

也就是它的有效期,让它只能在一段时间内可用

​ Cookie的有效期可以使用 Expires和Max-Age两个属性来设置

​ Expires和Max-Age可以同时出现,两者的失效时间可以一致,也可以不一致,但浏览器会优先采用Max-Age计算失效期

2.Cookie的作用域

​ 也就是让浏览器仅发送给特定的服务器和URI,避免被其他网站滥用

​ 作用域的设置比较,“Domain”和“Path”指定了Cookie所属的域名和路径,浏览器在发送Cookie前会从URI中提取出host和path部分,如果不满足条件,就不会在请求头里发送Cookie

使用这两个属性可以为不同的域名和路径分别设置各自的Cookie,通常PATH就用一个/或者直接省略,表示域名下的任意路径都允许使用Cookie

3.Cookie的安全性

JS脚本里可以用document.cookie来读写 Cookie数据,这就带来了安全隐患,有可能会导致跨站脚本XSS攻击窃取数据

属性 HTTP ONLY,会告诉浏览器,此cookie只能通过浏览器HTTP协议传输,禁止其他方式访问,浏览器的JS引擎就会禁用document.cookie等一切相关的API,脚本攻击也就无从谈起了

另一个属性 SameSite 可以防范“跨站请求伪造(XSRF)”攻击,设置成“SameSite=Stric”可以严格限定Cookie不能随着跳转链接跨站发送而“SameSite=Lax”则略宽松一点,允许GET/HEAD等安全方法,但禁止POST跨站发送

还有一个属性叫做“Secure”,表示这个Cookie仅能用HTTPS协议加密传输,明文的HTTP协议会禁止发送,但Cookie本身是不加密的,浏览器里还是以明文的形式存在

四.Cookie的应用

1.身份识别,状态保持
Cookie最基本的一个用途就是身份识别,保存用户的登录信息,实现会话事务

比如,用账号和密码登录某电脑,登录成功后网站服务器会发送给浏览器一个Cookie,内容大概是“name=yourid”这样就成功地把身份标签贴在了你身上

之后你在网站里随便访问哪件商品的页面,浏览器都会自动把身份Cookie发给服务器,所以服务器总会知道你的身份,一方面免去了重复登录的麻烦,另一方面也能够自动记录你的浏览记录和购物下单(后台数据库或者也用Cookie)实现了状态保持

2.基于Cookie的广告追踪
例子,上网的时候我们会看到很多广告的照片,这些照片都是广告商网站(例如Google),它会“偷偷地”给你贴上Cookie标签,这样你上其他网站,别的广告就能用Cookie读出你的身份,然后做行为分析,再给你推广告

这种Cookie不是由访问的主站存储的,所以又叫“第三方Cookie”

基于Cookie信息的互联网精准广告定向技术研究

HTTP的缓存控制

Cache是计算机领域里的一个重要的概念,是优化系统性能的利器,由于链路漫长,网络时延不可控,浏览器使用HTTP获取资源的成本较高,所以,非常有必要把“来之不易”的数据缓存起来,下次请求的时候尽可能的复用,这样就可以避免多次请求-应答的通信成本,节约网络带宽,也可以加快响应速度

实际上,HTTP传输的每一个环节基本上都会有缓存,这一部分其实是非常复杂的

基于“请求-应答模式”的特点,可以大致分为客户端缓存和服务器端缓存,服务器端缓存经常与代理服务“混搭在一起”,下面主要介绍客户端–浏览器端的缓存

一.服务器端的缓存控制
1.浏览器发现要访问一个网页,先从自己的缓存中寻找,看看有没有之前缓存下来的。如果有,就直接从缓存中加载,如果没有,向服务器发送请求,获取资源

2.服务器响应请求,返回资源,同时通过头字段Cache-Control标记资源的有效期

3.浏览器缓存资源,等待下次重新使用

在这里插入图片描述
服务器标记资源有效期使用的头字段是“Cache-Control”里面的值“max-age=30”,就是资源的有效时间,相当于告诉浏览器,这个页面只能缓存30S,30S之后就算过期了,就不能再使用这些资源,需要重新向服务器端发送请求

Cache-Control头字段中的几个选项
no-store:不允许缓存,用于某些变化非常频繁的数据,例如淘宝的秒杀页面
no-cache:它的字面含义容易与no-store搞混,实际的意思并不是不允许缓存,而是可以缓存,但在使用之前必须要去服务器去验证是否过期,是否有最新的版本
must-revalidate:又是一个和no-chache相似的词,它的意思是如果缓存不过期就可以继续使用,但过期了如果还想用就必须去服务器验证

下面是对缓存各个头字段的解析

在这里插入图片描述

二.客户端的缓存控制
我们在浏览器的Chrome里点几次“刷新按钮”,可以发现,ID一直在变,根本不是缓存的结果,明明说可以缓存30S,怎么就不起作用呢?

其实不止服务器可以发Cache-Control头,浏览器也可以发“Cache-Control”就是说请求-应答的双方都可以用这个字段进行缓存控制,互相协商缓存的使用策略

下来分析一下,一个刷新操作到底浏览器干了什么事情

当我们点击刷新的时候,浏览器会在请求头里加一个“Cache-Control:max-age=0”因为max-age是“生存时间”,max-age=0的意思就是“我要一个最新的界面”,而本地缓存里的数据至少保存了几秒种,所以浏览器就不会使用缓存,而是向服务器发请求。服务器看到max-age=0,也就会用一个最新生成的报文回应浏览器

前进-后退这两个操作,会发现缓存处的标记为from disk chache,意思是没有发送网络请求,而是读取了磁盘上的缓存

三.条件请求
浏览器使用“Cache-Control”做缓存控制只能是刷新数据,不能很好地利用缓存数据,又因为缓存会失效,使用前还必须要去验证数据是否是最新的版本

为了解决上述问题,浏览器采取了下述方法

浏览器可以用两个连续的请求组成“验证动作”,先是一个HEAD,获取资源的修改时间等元信息,然后与缓存数据比较,如果没有改动就使用缓存,节省网络流量,否则就再发送一个GET请求,获取最新的版本

但上述这样的两个请求网络成本太高了,所以HTTP协议就定义了一系列“if”开头的“条件请求”字段,专门用来检查验证资源是否过期,把两个请求才能完成的工作合并在一个请求里做,而且验证的责任也交给了服务器,减轻了浏览器的负担

条件请求一共有五个头字段,我们最常用的“if-Modified-Since”和“if-None-Match”这两个。需要第一次的响应报文预先提供“Last-modified”和“ETag”然后第二次请求时就可以带上缓存里的原值,验证资源是否是最新的

如果资源没有变,服务器就回应一个“304 Not Modified” 表示缓存依然有效,浏览器就可以更新一下有效期,然后放心大胆地使用缓存了

在这里插入图片描述
Last-modified”很好理解,就是文件的最后修改时间
ETag是实体标签(Entity Tag)的缩写,是资源的一个唯一标识,主要是用来解决修改时间无法准确区分文件变化的问题

​ 比如,一个文件在一秒内修改了多次,但是因为修改时间是秒级,所以这一秒内的新版本无法区分

再比如,一个文件定期更新,但有时会是同样的内容,实际上没有变化,用修改时间就会误以为发生了变化,传送给浏览器就会浪费带宽

使用ETAG就可以精确地识别资源的变动情况,让浏览器能够更有效地利用缓存

四.缓存和Cookie之间的相同点和区别刨析

1.相同点
都会保存到浏览器中,并可以设置过期时间

2.不同点
(1)Cookie随着应答报文发送到浏览器,再随着请求报文由浏览器发送到服务器
而Cache不会,但可能会发送携带if-Modified-Since(保存资源的最后修改时间)和if-None-Match(保存资源唯一标识)字段来验证资源是否过期

(2)Cookie在浏览器可以通过脚本获取(如果cookie没有设置HttpOnly),Cache则无法在浏览器中获取(出于安全原因)

(3)Cookie通过响应报文的Set-Cookie字段获得,Cache则是位于body中

(4)Cookie常用于身份识别,而Cache则是为了节省带宽和加快响应速度

HTTP的代理服务

代理服务本身并不产生内容,而是处于中间未知转发上下游请求和响应

面向下游的用户时,表现为服务器,代表源服务器响应客户端的请求,而面向上游的源服务器时,又表现为客户端发送请求

一.服务器端代理的作用
1.负载均衡:代理服务器如nginx可以作为后端服务器集群的前端,将接受到请求负载均衡到后端的集群中
2.健康检查:使用“心跳”等机制监控后端服务器,发现有故障就及时“踢出集群”,保证服务的高可用
3.安全防护:保护被代理的后端服务器,限制IP地址或流量,抵御网络攻击和过载
4.加密卸载:对外网使用SSL/TLS加密通信认证,而在安全的内网不需要加密,消除了加解密成本
5.数据过滤:拦截上下行的数据,任意指定策略修改请求或者响应
6.内容缓存:暂存,复用服务器响应

二.代理相关头字段
代理服务器,需要用字段,”via“标明代理的身份
via是一个通用字段,请求头或响应头里都可以出现,每当报文经过一个代理节点,代理服务器就会把自身信息追加到字段的末尾,就像是被中间的代理节点盖了一个章

在这里插入图片描述

HTTP的缓存代理

上面我们讲到了,缓存是为了节省网络带宽资源,同时提高用户端的响应速度。代理对客户端和服务器端都起到一个非常重要的作用。将这两者结合起来,就是我们接下来要讲HTTP的缓存代理,它进一步优化了HTTP的通信过程,提高了通信的效率,减轻了服务器端的压力,其主要是面向服务器端来说的

之前我们讲的缓存是在浏览器方的,这里我们来看一下服务器上的缓存

服务器上的缓存也是非常有价值的,可以让请求不必走完整个后续流程,”就近“获得响应结果,特别是对那些”读多写少“的数据,例如突发热点新闻,爆款商品的详情页,一秒钟内可能有成千上万次的请求,即使仅仅缓存数秒钟,也能够把巨大的访问流量挡在外面,让RPS(Request per Second)降低好几个数量级,减轻应用服务器的并发压力,对性能的改善是非常显著的

HTTP的服务器缓存功能主要由代理服务器实现(即缓存代理)

在没有缓存的时候,代理服务器每次都是直接转发客户端和服务器的报文,中间不会存储任何数据,只有简单的中转功能,这样只是起到了隐藏真实后端服务器集群和对集群调度分配的作用

而加入缓存之后就不一样了
代理服务器收到来自源服务器的响应数据之后需要做两件事,第一个就是把报文转发给客户端,而第二个就是把报文放到自己的Cache里

下一次再有相同的请求,代理服务器就可以直接发送304或者缓存数据,不必再从源服务器哪里获取,这样就降低了客户端的等待时间,同时节约了源服务器的网络带宽

一.源服务器的缓存控制

之前我们讲到了Cache-Control的四种属性:max-age,no-store,no-cache和must-revalidate,这四种属性是服务器方设定约束客户端的,同样的也可以对代理进行约束

但客户端和代理是不一样的,客户端的缓存只是用户自己使用,而代理的缓存可能为非常多的客户端提供服务,所以,需要对它的缓存再多一些限制条件

首先,我们区分客户上的缓存和代理上的缓存,可以使用两个新属性”private“和”public

private表示缓存只能再客户端保存,是用户”私有“的,不能放在代理上与别人共享

**”public“**的意思就是缓存完全开放,谁都可以存,谁都可以用

其次缓存失效后的重新验证也要区分开来(即使用条件请求”Last-modified“和”ETag“),”must-revalidate“只要过期就必须回源服务器验证,而新的”proxy-revalidate“只要求代理的缓存过期后必须验证,客户端不必回源,只验证到代理这个环节就可以了

再次,缓存的生存时间可以使用新的”s-maxage“(s是share的意思,注意maxage中间没有”-“),只限定在代理上能够存多久,而客户端仍然使用”max-age

还有一个代理专用的属性”no-transform“,代理有时候会对缓存下来的数据做一些优化,比如把图片生存png,webq等几种格式,方便今后的请求处理。而”no-transform“就会禁止这样操作

下面的流程图是完整的服务器端缓存控制策略,可以同时控制客户端和代理
在这里插入图片描述

二.客户端的缓存控制
说完了服务器端的缓存控制策略,我们再来看看客户端
在这里插入图片描述

max-age,no-store,no-cache这三个属性前面介绍过了,他们也是同样作用于代理和服务器

关于缓存的生存时间,多了两个新属性”max-stale“和”min-fresh

max-stale的意思是如果代理上的缓存过期了也可以接受,但不能过期太多,超过x秒后依然有效

min-fresh的意思是缓存必须有效,而且必须再X秒后依然有效

CDN

cdn是一种在外部加速HTTP协议的服务

为什么要有网络加速?

其实HTTP的传输速度也不算差,但是我们需要考虑到一个很现实的问题,我们现在的传输线路一般都是光纤,而光速也是有限的,虽然每秒30万公里,但这只是真空中的上限,实际中,光缆的速度会下降到原本的三分之二左右,也就是20万公里/秒,这样一来,地理位置的距离导致的传输延迟就会变得比较明显了

除次之外,还有在各个运营商之间的切换,也会产生一定的延时,再加之各种中间设备之间的延迟,最终结果就是,如果仅用现在的HTTP传输模式,大多数网站都会访问速度缓慢,尤其是当客户端离服务器很远的时候,用户体验糟糕

什么是CDN?
为了解决上述问题,CDN就出现了,它是专门为解决”长距离“上网络访问速度而诞生的一种网络应用服务

从名字上看,CDN有三个关键字”内容“,”分发“,”网络

1.网络
CDN的最核心原则就是”就近访问“,如果用户能够在本地几十公里的距离之内获取到数据,那么时延基本上就是0了

所以CDN投入了大量资金,在全国,乃至全球的各大上枢纽城市都建立了机房,部署了大量拥有高存储高带宽的节点,构建了一个专用网络。这个网络是跨运营商,跨地域的,虽然内部也划分成读个小网络,但他们之间用高速专有线路连接,基本上可以任务不存在网络拥堵

分发
有了这个高速的专用网之后,CDN就要”分发“内容了,用到的就是上面我们讲到的“缓存代理技术” 。使用“推”或“拉”的手段,把源站的内容逐级缓存到网络的每一个节点上

于是,用户在上网的时候就不直接访问源站,而是访问离他“最近的”一个CDN节点,术语叫做“边缘节点”,其实就是缓存了源站内容的代理服务器,这样一来就省去了“长途跋涉”的时间成本,实现了“网络加速”

在这里插入图片描述

内容
那么CDN都能加速什么样的“内容”呢?

在CDN中,“内容”其实就是HTTP协议里的资源,比如超文本,图片,视频,应用程序安装包等

资源按照是否可缓存又分为“静态资源”和“动态资源”,所谓的“静态资源”是指数据内容“静态不变”,任何时候来访问都是一样的,比如图片,音频等。所谓的“动态资源”是指数据内容是“动态变化”的,也就是由后台服务器计算生成的,每次访问都不一样,比如商品的库存,微博的粉丝数等等

很显然只有静态资源才能被缓存加速,就近访问,而动态资源只能由源站实时产生,即使缓存了也没有意义。不过,如果动态资源指定了“Cache-Control”,允许缓存短暂的时间,那它在这段时间里也就变成了“静态资源”,可以被CDN缓存加速

我们不生成内容,我们只是内容的搬运工”用来形容CDN就非常的贴切

CDN的负载均衡
下面我们再来介绍一下CDN具体是怎么运行的,他有两个关键组成部分:全局负载均衡缓存系统,对应的分别是我们上述讲过的DNS缓存代理

全局负载均衡(Global Server Load Balance)一般简称为GSLB,它是CDN的“大脑”,主要的职责是当用户接入网络的时候在CDN专网中挑选出一个“最佳”节点提供服务,解决的是用户如何找到“最近的”边缘节点,对整个CDN网络进行“负载均衡”

在这里插入图片描述
GSLB最常见的实现方式是“DNS负载均衡

在原来没有CDN的时候,权威DNS返回的是网站自己服务器的实际IP地址,浏览器收到DNS解析结果之后直连网站,但加入CDN之后,权威DNS(服务器端配置的DNS服务器)返回的不是IP地址,而是一个CNAME别名记录,指向的是CDN的GSLB

因为没拿到IP地址,于是本地DNS就会像GSLB再发起请求,这样就进入了CDN的全局负载均衡系统,开始“智能调度”,主要的依据有这么几个
1.看用户的IP地址,查表得知地理位置,找相对最近的边缘节点
2.看用户所在的运营商网络,找相同网络的边缘节点
3.检查边缘节点的负载情况,找负载较轻的节点
4.其他,比如节点的“健康状况”,服务能力,带宽,响应时间等

GSLB把这些因素结合起来,用一个复杂的算法,最后找出一台“最合适”的边缘节点,把这个节点的IP地址返回给用户,用户就可以“就近”访问CDN的缓存代理了

CDN的缓存代理
缓存系统是CDN的另一个关键组成部分,相当于CDN的“心脏”。如果缓存系统的服务能力不够,不能很好地满足用户的需求,那GSLB调度算法再优秀也没有用

但互联网上的资源是无穷无尽的,CDN厂商不可能把所有资源都缓存起来。所以,缓存系统智能有选择地缓存那些最常用的那些资源

这里就有CDN的关键概念:“命中”,和“回源

“命中”就是指用户访问的资源恰好在缓存系统里,可以直接返回给用户;“回源”则正相反,缓存里没有,必须用代理的方式回源站取

相应地,也就有了两个衡量CDN服务质量的指标:“命中率”和“回源率”。命中率就是命中次数与访问次数之比。显然,好的CDN应该是命中率越高越好,回源率越低越好。现在的商业CDN命中率都在90%以上,相当于把源站的服务能力放大了10倍以上

提升命中率,降低回源率的方法
首先,最基本的方法就是在存储系统上下功夫,硬件用高速CPU,大内存,万兆网卡,再搭配TB级别的硬盘和快速的SSD

其次,缓存系统也可以划分出层次,分成一级缓存点和二级缓存点,一级缓存点配置高一些,直连源站,二级缓存配置低一些,直连用户。回源的时候二级缓存只找一级缓存,一级缓存没有才回源站,这样可以有效地减少真正的回源

第三个就是使用高性能的缓存服务,最常用的缓存代理软件,Squid,Varnish等

发布了24 篇原创文章 · 获赞 10 · 访问量 2357

猜你喜欢

转载自blog.csdn.net/flat0809/article/details/105029545
今日推荐