一、HTTP协议简介
1、通信的定义
通信,就是信息的传递和交换。
通信三要素:
通信的主体
通信的内容
通信的方式
案例:
服务器把传智专修学院的简介通过响应的方式发送给客户端浏览器。
其中,
通信的主体是服务器和客户端浏览器;
通信的内容是传智专修学院的简介;
通信的方式是响应;
2、通信协议
通信协议(Communication Protocol)是指通信的双方完成通信所必须遵守的规则和约定。
通俗的理解:通信双方采用约定好的格式来发送和接收消息,这种事先约定好的通信格式,就叫做通信协议。
2.1互联网中的通信协议
客户端与服务器之间要实现网页内容的传输,则通信的双方必须遵守网页内容的传输协议。
网页内容又叫做超文本,因此网页内容的传输协议又叫做超文本传输协议(HyperText Transfer Protocol) ,简称 HTTP 协议。
2.2HTTP协议
HTTP 协议即超文本传送协议 (HyperText Transfer Protocol) ,它规定了客户端与服务器之间进行网页内容传输时,所必须遵守的传输格式。
例如:
客户端要以HTTP协议要求的格式把数据提交到服务器
服务器要以HTTP协议要求的格式把内容响应给客户端
2.3HTTP协议的交互模型
HTTP 协议采用了 请求/响应的交互模型。
二、HTTP请求消息
由于 HTTP 协议属于客户端浏览器和服务器之间的通信协议。因此,客户端发起的请求叫做 HTTP 请求,客户端发送到服务器的消息,叫做 HTTP 请求消息。
注意:HTTP 请求消息又叫做 HTTP 请求报文。
1、组成部分
HTTP 请求消息由请求行(request line)、请求头部( header ) 、空行 和 请求体 4 个部分组成。
1.1请求行
请求行由请求方式、URL 和 HTTP 协议版本 3 个部分组成,他们之间使用空格隔开。
1.2请求头部
请求头部用来描述客户端的基本信息,从而把客户端相关的信息告知服务器。比如:User-Agent 用来说明当前是什么类型的浏览器;Content-Type 用来描述发送到服务器的数据格式;Accept 用来描述客户端能够接收什么类型的返回内容;Accept-Language 用来描述客户端期望接收哪种人类语言的文本内容。
请求头部由多行 键/值对 组成,每行的键和值之间用英文的冒号分隔。
请求头部 – 常见的请求头字段
头部字段 | 说明 |
---|
Host | 要请求的服务器域名 | Connection | 客户端与服务器的连接方式(close 或 keepalive) | Content-Length | 用来描述请求体的大小 | Accept | 客户端可识别的响应内容类型列表 | User-Agent | 产生请求的浏览器类型 | Content-Type | 客户端告诉服务器实际发送的数据类型 | Accept-Encoding | 客户端可接收的内容压缩编码形式 | Accept-Language | 用户期望获得的自然语言的优先顺序 |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gt1Kzp73-1647780093259)(images/image-20220103154105822.png)]
关于更多请求头字段的描述,可以查看 MDN 官方文档:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers
1.3空行
最后一个请求头字段的后面是一个空行,通知服务器请求头部至此结束。
请求消息中的空行,用来分隔请求头部与请求体。
1.4请求体
请求体中存放的,是要通过 POST 方式提交到服务器的数据。
注意:只有 POST 请求才有请求体,GET 请求没有请求体!
三、HTTP响应消息
响应消息就是服务器响应给客户端的消息内容,也叫作响应报文。
1、组成部分
HTTP响应消息由状态行、响应头部、空行 和 响应体 4 个部分组成,如下图所示:
1.1状态行
状态行由 HTTP 协议版本、状态码和状态码的描述文本 3 个部分组成,他们之间使用空格隔开;
1.2响应头部
响应头部用来描述服务器的基本信息。响应头部由多行 键/值对 组成,每行的键和值之间用英文的冒号分隔。 关于更多响应头字段的描述,可以查看 MDN 官方文档:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers
1.3空行
在最后一个响应头部字段结束之后,会紧跟一个空行,用来通知客户端响应头部至此结束。
响应消息中的空行,用来分隔响应头部与响应体。
1.4响应体
响应体中存放的,是服务器响应给客户端的资源内容。
四、HTTP请求方法
HTTP 请求方法,属于 HTTP 协议中的一部分,请求方法的作用是:用来表明要对服务器上的资源执行的操作。最常用的请求方法是 GET 和 POST。
五、HTTP响应状态码
HTTP 响应状态码(HTTP Status Code),也属于 HTTP 协议的一部分,用来标识响应的状态。
响应状态码会随着响应消息一起被发送至客户端浏览器,浏览器根据服务器返回的响应状态码,就能知道这次 HTTP 请求的结果是成功还是失败了。
1、组成及分类
HTTP 状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字用来对状态码进行细分。
HTTP 状态码共分为 5 种类型:
完整的 HTTP 响应状态码,可以参考 MDN 官方文档 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status
2、常见的HTTP响应状态码
2.1 2**成功相关的响应状态码
2** 范围的状态码,表示服务器已成功接收到请求并进行处理。常见的 2** 类型的状态码如下:
状态码 | 状态码英文名称 | 中文描述 |
---|
200 | OK | 请求成功。一般用于 GET 与 POST 请求 | 201 | Created | 已创建。成功请求并创建了新的资源,通常用于 POST 或 PUT 请求 |
2.2 3**重定向相关的响应状态码
3** 范围的状态码,表示表示服务器要求客户端重定向,需要客户端进一步的操作以完成资源的请求。常见的 3** 类型的状态码如下:
状态码 | 状态码英文名称 | 中文描述 |
---|
301 | Moved Permanently | 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替 | 302 | Found | 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI | 304 | Not Modified | 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源(响应消息中不包含响应体)。客户端通常会缓存访问过的资源。 |
2.3 4**客户端错误相关的响应状态码
4** 范围的状态码,表示客户端的请求有非法内容,从而导致这次请求失败。常见的 4** 类型的状态码如下:
2.4 5**服务端错误相关的响应状态码
5** 范围的状态码,表示服务器未能正常处理客户端的请求而出现意外错误。常见的 5** 类型的状态码如下:
状态码 | 状态码英文名称 | 中文描述 |
---|
500 | Internal Server Error | 服务器内部错误,无法完成请求。 | 501 | Not Implemented | 服务器不支持该请求方法,无法完成请求。只有 GET 和 HEAD 请求方法是要求每个服务器必须支持的,其它请求方法在不支持的服务器上会返回501 | 503 | Service Unavailable | 由于超载或系统维护,服务器暂时的无法处理客户端的请求。 |
六、GET与POST的区别
- GET请求会被浏览器留下访问记录,而POST不会留下记录;
- GET请求参数携带在URL后面,不太安全,而POST参数会放到请求体重,适合传输敏感数
- GET只能发送 ASCII字符,而POST没限制。
- 发送数据时机不同。GET请求会一次性将数据发送出去,而POST发送分两部分,先发送header 头部分,如果服务端相应100状态码(继续),然后再发送body部分。
- 受URL长度限制,GET传输数据较少,而POST传输数据量较大,一般默认为不受限制。
- 从幂等性的角度来说,GET是幂等的(只要参数不变,返回的结果总是相等的),而POST不是
- GET在浏览器回退时是无害的,而POST会再次发起请求
七、HTTP缓存
缓存是性能优化中非常重要的一环,浏览器的缓存机制对开发也是非常重要的知识点。接下来以三个部分来把浏览器的缓存机制说清楚:
什么是强缓存、协商缓存?
关于什么时候命中强缓存,什么时候命中协商缓存,主要依赖于http返回头信息里的Cache-Control返回字段进行控制。
什么情况下命中强缓存? 以常见的max-age为例:若max-age=5356800,则意思是说浏览器在首次请求这个文件的时候,可以在本地磁盘中保存这个文件5356800秒,从首次加载时间开始以后的这些时间内,若再次请求这个文件,浏览器可以不发起http请求,而直接使用缓存中的内容即可,这样不仅节省了服务器负担,也提升网站用户体验。 什么情况下命中协商缓存? 仍然以常见的max-age为例:若max-age=5356800,距离第一次请求文件已经过去了5356800秒,当用户再次需要这个资源的时候,浏览器就会拿之前这个文件返回的Etag以及Last-Modified,分别命名为If-None-Match和If-Modified-Since作为请求参数传给服务端,服务端与现有文件进行匹配,若文件已更新,则返回200状态码,同时返回最新文件给客户端。若文件未更新,则返回304状态码,告诉客户端缓存有效,可以继续使用。
2.缓存位置
关于文件缓存位置,可通过Chrome开发面板中,Network栏目下每个文件后面有一个Size属性查看
- 首次请求,会显示当前文件大小,例如xxkB。
- 在网页未关闭之前,再次请求,会从内存中取出文件,显示(memory cache)。
- 关闭网页再次请求的时候,若命中强缓存,会从磁盘中取出,显示(disk cache)。
Cache-Control有哪些字段
public 公共的。表示任何人都可以缓存,包括浏览器、代理服务器等。 private 私有的。表示只允许单个用户缓存,不能作为共享缓存。 no-cache 本地可以缓存,但每次都需要与服务端协商,即每次都命中协商缓存。 no-store 不适用任何缓存。 max-age=xxx 设置缓存最大周期(单位秒),超过这个相对时间被认为是过期,需要与服务端协商是否还可继续使用。与Expires不同,因为它是绝对时间,目前基本上已被废弃,因为若服务器时间与客户端时间相差较大的情况下,会产生一些异常问题。 s-maxage=xxx 设置代理服务器缓存文件过期相对时间,客户端会忽略它。 must-revalidate 一旦资源过期(比如超过max-age),在成功向原始服务器验证之前,缓存不能用该资源响应后续请求。 no-transform 不得对资源进行转换或转变。 only-if-cached 表明客户端只接受已缓存的响应,并且不要向原始服务器检查是否有更新的拷贝。
八、HTTP1.1的缺点
1.无状态
其实这也不能说是缺点,这算是它的特点之一,至于是缺点还是优点,要分场景来看的。那么什么是无状态呢?就是指通信过程的上下文信息,每次请求都是独立、互相无关的,且默认状态不需要保留状态信息的。但是在一些场景下,比如前一次请求需要与后一次请求有一定关联,这个时候无状态处理起来就比较麻烦了。
2.臃肿的消息首部
HTTP/1.1 的首部无法压缩,再加上 cookie 的存在,经常会出现首部大小比请求数据大小还大的情况。
3.明文传输
也就是协议里的报文,即传输头信息,不使用二进制,而是使用文本的形式传输。这就给中间拦截者造成可乘之机,拦截传输内容,获取敏感信息。
4.队头阻塞
http传输是基于请求-应答的模式进行的,报文必须是一发一收,所有任务被放到一个任务队列中串行执行。当http开启长连接的时候,当前域名下会共用一个TCP连接,一旦队首因某些原因卡住,后续只能处于等待状态,这就是著名的队头阻塞问题。
那么如何解决队头阻塞问题?在不升级到HTTP2.0的前提下,有两种解决方案:
**并发连接:**对一个域名分配多个长连接,增加多个任务队列。就像食堂打饭后排队付钱,一个队伍排到门口,现在从之前的一个窗口增加到多个窗口,同一时间做付款操作的同学多了,速度自然也就快起来了。 **域名分片:**上面讲到了对一个域名分配多个长连接,那么也可以分配多个域名。例如分配static1.baidu.com、static2.baidu.com等多个域名加载网站资源,每个域名再分配多个长链接,就可以相对解决队头阻塞问题。
注意: 域名也不是越多越好,因为每多一个域名,都要涉及到DNS查找、TCP三次握手、SSL/TLS握手,且TCP有一个慢启动特点,就是刚开始传输慢,慢慢的才会达到一个较快的稳定速度,如果启用了一个单独域名,而这个域名只传输了一个2KB的js文件,实际文件传输时间远远小于握手时间,就得不偿失了。具体哪个地方耗时可以在Chrome开发面板下Network中查看具体文件,其中有一个Waterfall内容。 解释: Queued at: 从页面加载到开始请求当前文件的等待时间。 Started at: 从第几秒开始请求当前文件。 Queueing: 在请求队列中的时间。 Stalled: 从TCP 连接建立完成,到真正可以传输数据之间的时间差,此时间包括代理协商时间。 DNS Lookup: 当前域名执行DNS查找所花费的时间。 Initial Connection: 建立连接所花费的时间,包括TCP握手/重试和协商SSL。 SSL: 完成SSL握手所花费的时间(如果是TLS协议,此处显示的就是TLS)。 Request sent: 发出网络请求所花费的时间,通常为一毫秒的时间。 Waiting(TFFB): TFFB 是发出页面请求到接收到应答数据第一个字节的时间。 Content Download: 接收响应数据所花费的时间。
九、HTTP2.0的优势
1.头部压缩
HTTP1.1时代,默认情况下前后两次HTTP请求没有关联,这被称为无状态,请求以及响应头信息里有很多字段(本文之前已介绍过),不论是否需要,都会以key:value的形式在网络中传输,尤其对于GET请求,请求报文几乎全是请求头,这个时候就存在非常大的优化空间。HTTP2.0就针对这个问题采用了HPACK压缩算法对头部内容进行压缩,大大减少了网络传输。
HPACK压缩算法的特点是啥?在服务端与客户端建立一个哈希表,以索引的形式代替头信息,双方传输就以索引为准,拿到索引值后到哈希表中寻找对应头内容,以此减少网络传输。
2.多路复用
上面讲到了HTTP1.1队头阻塞的问题,虽然采用了长连接以及多域名分片方法在一定程度上规避里队头阻塞,但并没有从根本上解决问题。比如在有限的带宽情况下,如何完成优先级较高的请求,而不是一定要按照排队的顺序。
HTTP2.0是以二进制分帧的方式来解决所谓的队头阻塞问题。将原来的Headers、Body的报文解析成二进制的帧数据,传输过程中看到的是10101的格式。这些二进制帧不存在先后关系,因此也就不会排队等待,也就没有了 HTTP 的队头阻塞问题。
注意:所谓的乱序,指的是不同ID的Stream是乱序的,但同一个Stream ID 的帧一定是按顺序传输的。二进制帧到达后对方会将Stream ID相同的二进制帧组装成完整的请求报文和响应报文。
3.服务器推送
我们知道在目前的HTTP1.1时代,服务器是被动的,只有客户端主动发起请求,服务端才会响应对应内容,是一问一答的模式。并不会主动推送内容给客户端,除非采用websocket。而HTTP2.0就增加了服务器推送特性,可以对客户端的一个请求发送多个响应。比如客户端请求html页面的时候,服务器可以将当前页面用到的js以及css等资源一并返回给客户端,减少后续交互。
当然,客户端也可以拒绝服务器的推送。
4.解析速度快
服务器解析 HTTP1.1 的请求时,必须不断地读入字节,直到遇到分隔符 CRLF 为止。而解析 HTTP2 的请求就不用这么麻烦,因为 HTTP2.0是基于帧的协议,每个帧都有表示帧长度的字段。
5.优先级
HTTP2.0可以对比较紧急的请求设置一个较高的优先级,服务器在收到这样的请求后,可以优先处理。
十、HTTP代理
目前通常意义上的代理,一般认为是CDN节点,就是架设在客户端与原服务器之间的服务器,对客户端来说它就是服务器,对服务器来说它就是客户端。主要起到负载均衡的作用,减少原服务器的压力,分担原服务器带宽,提高用户访问资源速度,提高用户体验。
什么是CDN
默认情况下,所有资源都会向原服务器请求。这不仅会给原服务器造成较大压力,还会因距离问题让客户端等待较长时间,例如服务器在美国,中国用户首次请求要跨越大半个地球,显然比从上海服务器请求更慢。这个时候对于原服务器来说,就需要个代理,这个代理服务器就被称为CDN节点,节点按照一定规则定期向原服务器更新文件即可,附近的用户就近访问当前节点即可,既减轻了原服务器压力,也减少了请求时间,提高用户体验。
十一、http性能优化相关
- DNS预解析 合理控制域名数量
- 使用HTTP2.0 采用服务端渲染+客户端渲染的方式 公共类库存放到CDN上
- http返回值Cache-Control的max-age设置较大值,例如6个月,尽可能保持一直缓存,文件更改的时候还一个hash文件名即可。
- 将CSS放在文件头部,JavaScript文件放在底部
- 使用字体图标iconfont代替图片图标
- 小图片采用base64压缩,减少网络请求
- js、css文件压缩,服务端采用gzip、br等压缩算法
- 图片懒加载。这对于首屏优化非常有用,非首屏需要的图片在网络空闲的时候异步加载即可
- 关于图片,也可以适当降低图片质量,或者先加载一个质量较低的图片显示给用户看,之后再加载清晰的图片展示给用户。
- 使用css3代理部分图标
- webpack配置按需加载
- 减少重绘重排
- 使用requestAnimationFrame来实现视觉变化
- 使用Web Workers
- 降低CSS选择器的复杂性
- 使用flexbox布局
- 使用transform和opacity属性更改来实现动画
最后一条建议:避免过度优化
|