1. 什么是HTTP
HTTP 是一种 超文本传输协议(Hypertext Transfer Protocol)
,这你一定能说出来,但是这样还不够,假如你是大厂面试官,这不可能是他想要的最终结果。
超文本传输协议可以进行文字分割:超文本(Hypertext)、传输(Transfer)、协议(Protocol) ,它们之间的关系如下
按照范围的大小 协议 > 传输 > 超文本。
1.1 什么是超文本?
在互联网早期的时候,我们保存的信息通常都以文本
即简单字符的形式存在,文本是一种能够被计算机解析的有意义的二进制数据包。
随着互联网的高速发展,两台电脑之间能够进行数据的传输后,人们不满足只能在两台电脑之间传输文字,还想要传输图片、音频、视频,甚至点击文字或图片能够进行超链接
的跳转,那么文本的语义就被扩大了,这种语义扩大后的文本就被称为超文本(Hypertext)
1.2 什么是传输?
两台计算机之间会形成互联关系进行通信,我们存储的超文本会被解析成为二进制数据包,由传输载体(例如同轴电缆,电话线,光缆)负责把二进制数据包由计算机终端传输到另一个终端的过程称为传输(transfer)
通常我们把传输数据包的一方称为请求方
,把接到二进制数据包的一方称为应答方
。
1.3 什么是协议?
协议这个名词不仅局限于互联网范畴,也体现在日常生活中,比如情侣双方约定好在哪个地点吃饭,这个约定也是一种协议
,比如你应聘成功了,企业会和你签订劳动合同,这种双方的雇佣关系也是一种 协议
。
那么网络协议是什么呢?
网络协议就是网络中(包括互联网)传递、管理信息的一些规范。如同人与人之间相互交流是需要遵循一定的规矩一样,计算机之间的相互通信需要共同遵守一定的规则,这些规则就称为网络协议。
2. HTTP响应模型
HTTP(HyperText Transfer Protocol),超文本传输协议,是一个基于TCP实现的应用层协议。
HTTP由请求和响应构成,是一个标准的客户端服务器模型(B/S)。HTTP协议永远都是客户端发起请求,服务器回送响应。见下图:
HTTP是一个无状态的协议
。无状态是指客户机(Web浏览器)和服务器之间不需要建立持久的连接
,这意味着当一个客户端向服务器端发出请求,然后服务器返回响应(response),TCP连接就被关闭了
,在服务器端不保留连接的有关信息.HTTP遵循请求(Request)/应答(Response)模型。客户机(浏览器)向服务器发送请求,服务器处理请求并返回适当的应答。所有HTTP连接都被构造成一套请求和应答。
2.1 HTTP分组传输的特点
上面整个过程中我们可以总结出 HTTP 进行分组传输是具有以下特征:
- 支持客户-服务器模式。
- 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有 GET、HEAD、POST。
- 灵活:HTTP 允许传输任意类型的数据对象。正在传输的类型由 Content-Type 加以标记。
- 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。
- 无状态:HTTP 协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。
- 端口:默认使用80端口 ,https默认443
- 安全方面:明文传输 不安全会被监听更改
3. HTTP请求 / 响应报文
我们上面描述了一下 HTTP 的请求响应过程,流程比较简单,但是凡事就怕认真,你这一认真,就能拓展出很多东西,比如 HTTP 报文是什么样的,它的组成格式是什么? 下面就来探讨一下
3.1 HTTP请求报文
- 请求行(主要包含三部分)
- 方法 + URL + 协议版本。
- 其中请求方法主要是:
1. GET获取数据
2. POST上传数据
3. PUT修改数据
4. DELETE删除数据。
- 请求头
- 格式:key:value,包括协议自带头 和 自定义的头。
- 常见header头:
1. content-type: 来表示具体请求中的媒体类型信息 , text/html HTML格式 , text/plain 纯文本格式 ,image/jpeg jpg图片格式 , application/json JSON数据格式。
2. Accept: 接收数据格式, image/jpeg , text/html, application/xhtml+xml, application/xml;q=0.9 。
3. User-Agent: 描述用户浏览器信息 。
4. Connection: 使用连接,Keep-Alive(长连接) ,Close(短连接) 。
5. Accep-Encoding: 描述可以接受的编码,gzip,deflate等。
6. Cookie: 由服务器设置的,客户端下次请求的时候可以携带过来。
7. 用户自定义的Header。
xxxxx
- 空行 告诉服务请求头已经结束,用于分割。
- 请求体
- 一般在POST方法会将传输的数据提供到Body , 现在一般会采用JOSN进行格式。
- 在GET的时候可以提供Body , 一般建议不要使用
3.2 HTTP响应报文
- 状态行
- 格式: 协议版本 + 状态码 + 状态描述
- 常用的状态码:
1xxx ===> 客户端可以即发送请求
2xxx ===> 正常访问,200
3xxx ===> 重定向
4xxx ===> 401 未授权 , 404 Not found
5xxx ===> 501 服务器内部错误
- 响应头
Content-Type:application/json
Server:Apache , nginx
Date:Mon,12 Sep ....
xxxxx
-
空行 用于分割表示下面没有响应头了
-
响应体 通常是返回json数据
3.3 HTTP的一些常用的头介绍
- 通用头
通用标头主要有三个,分别是
Date
、Cache-Control
和Connection
1. Date: 它可以出现在请求标头和响应标头中,表示的是格林威治标准时间,这个时间要比北京时间慢八个小时,它的基本表示如下:
Date: Wed, 21 Oct 2015 07:28:00 GMT
2. Cache-Control: 他可以出现在请求标头和响应标头中,Cache-Control 的种类比较多, 主要大类有 `可缓存性`、`阈值性`、 `重新验证并重新加载` 和`其他特性`.
可缓存性是唯一响应标头才具有的特性,我们会在响应标头中详述
3. Connection: 决定当前事务(一次三次握手和四次挥手)完成后,是否会关闭网络连接.
持久性连接: Connection: keep-alive
非持久性连接: Connection: close
- 实体头
实体标头是描述消息正文内容的 HTTP 标头。实体标头用于 HTTP 请求和响应中。头部
Content-Length
、Content-Language
、Content-Encoding
是实体头。
1. Content-Length: 实体报头指示实体主体的大小,以字节为单位,发送到接收方.
2. Content-Language: 实体报头描述了客户端或者服务端能够接受的语言,例如:
Content-Language: de-DE
Content-Language: en-US
Content-Language: de-DE, en-CA
3. Content-Encoding: 这又是一个比较麻烦的属性,这个实体报头用来压缩媒体类型。Content-Encoding 指示对实体应用了何种编码。
gzip、compress、deflate、identity
- 请求标头
GET /home.html HTTP/1.1
Host: developer.mozilla.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://developer.mozilla.org/testpage.html
Connection: keep-alive
Upgrade-Insecure-Requests: 1
If-Modified-Since: Mon, 18 Jul 2016 02:36:04 GMT
If-None-Match: "c561c68d0ba92bbeb8b0fff2a9199f722e3a621a"
Cache-Control: max-age=0
-
内容协商 内容协商的分类有很多种,主要的几种类型是
Accept、Accept-Charset、Accept-Encoding、Accept-Language、Content-Language
。 -
响应标头
200 OK
Access-Control-Allow-Origin: *
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Date: Mon, 18 Jul 2016 16:06:00 GMT
Etag: "c561c68d0ba92bbeb8b0f612a9199f722e3a621a"
Keep-Alive: timeout=5, max=997
Last-Modified: Mon, 18 Jul 2016 02:36:04 GMT
Server: Apache
Set-Cookie: mykey=myvalue; expires=Mon, 17-Jul-2017 16:06:00 GMT; Max-Age=31449600; Path=/; secure
Transfer-Encoding: chunked
Vary: Cookie, Accept-Encoding
x-frame-options: DENY
4. HTTP缓存
说真的,http缓存相关的细节比较多,并且 http 常用协议版本有1.0、1.1
4.1 缓存相关的头
1. Expires
响应头,代表该资源的过期时间
2. Cache-Control
请求/响应头,缓存控制字段,精确控制缓存策略
3. If-Modified-Since
请求头,资源最近修改时间,由浏览器告诉服务器
4. Last-Modified
响应头,资源最近修改时间,由服务器告诉浏览器
5. Etag
响应头,资源标识,由服务器告诉浏览器
6. If-None-Match
请求头,缓存资源标识,由浏览器告诉服务器
配对使用的字段:
If-Modified-Since 和 Last-Modified
Etag 和 If-None-Match
4.2 缓存过程
5. HTTP1.0 / HTTP1.1 / HTTP 2.0
早在 HTTP 建立之初,主要就是为了将超文本标记语言(HTML)文档从Web服务器传送到客户端的浏览器。
5.1 HTTP的基本优化
影响一个 HTTP 网络请求的因素主要有两个:带宽和延迟
- 宽带:
如果说我们还停留在拨号上网的阶段,带宽可能会成为一个比较严重影响请求的问题.
但是现在网络基础建设已经使得带宽得到极大的提升,我们不再会担心由带宽而影响网速,那么就只剩下延迟了。
- 延迟:
1. 浏览器阻塞(HOL blocking):
浏览器会因为一些原因阻塞请求。
浏览器对于同一个域名,同时只能有 4 个连接(这个根据浏览器内核不同可能会有所差异),超过浏览器最大连接数限制,后续请求就会被阻塞.
2. DNS 查询(DNS Lookup):
浏览器需要知道目标服务器的 IP 才能建立连接。
将域名解析为 IP 的这个系统就是 DNS。这个通常可以利用DNS缓存结果来达到减少这个时间的目的。
3. 建立连接(Initial connection):
HTTP 是基于 TCP 协议的,浏览器最快也要在第三次握手时才能捎带 HTTP 请求报文,达到真正的建立连接.
但是这些连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。
5.2 HTTP1.0 和 HTTP1.1的一些区别
HTTP1.0最早在网页中使用是在1996年,而HTTP1.1则在1999年才开始广泛应用于现在的各大浏览器网络请求中,同时HTTP1.1也是当前使用最为广泛的HTTP协议,主要区别主要体现在:
1. 缓存处理
在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准.
HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略.
2. 带宽优化及网络连接的使用
HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能.
HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
3. 错误通知的管理
在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;
410(Gone)表示服务器上的某个资源被永久性的删除。
4. Host头处理
在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。
随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。
HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)
5. 长连接
HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。
在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。
5.3 SPDY 优化 HTTP1.X
2012年google如一声惊雷提出了SPDY的方案,优化了HTTP1.X的请求延迟,解决了HTTP1.X的安全性,具体如下:
-
降低延迟,针对HTTP高延迟的问题,SPDY优雅的采取了多路复用(multiplexing)。多路复用通过多个请求stream共享一个tcp连接的方式,解决了HOL blocking的问题,降低了延迟同时提高了带宽的利用率。
-
请求优先级(request prioritization)。多路复用带来一个新的问题是,在连接共享的基础之上有可能会导致关键请求被阻塞。SPDY允许给每个request设置优先级,这样重要的请求就会优先得到响应。
-
header压缩。 前面提到HTTP1.x的header很多时候都是重复多余的。选择合适的压缩算法可以减小包的大小和数量。
-
基于HTTPS的加密协议传输,大大提高了传输数据的可靠性。
-
服务端推送(server push),采用了SPDY的网页,例如我的网页有一个sytle.css的请求,在客户端收到sytle.css数据的同时,服务端会将sytle.js的文件推送给客户端,当客户端再次尝试获取sytle.js时就可以直接从缓存中获取到,不用再发请求了。
5.4 HTTP2.0 和 HTTP1.X 相比的新特性
-
新的二进制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。
-
多路复用(MultiPlexing),即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
-
header压缩,如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
-
服务端推送(server push),同SPDY一样,HTTP2.0也具有server push功能。