http协议
前言
含义:http(hyper text transfer protocol)协议就相当于客户端和服务端定义好的一个规范,通过这个规范,所有人在请求和响应的过程中都需要遵循这样的规范
http协议作用:规范了浏览器和服务器之间的数据交互,当初设计http协议就是为了提供一种发布和接收html页面的方法,由url标识具体的资源,后面http用来传递的数据格式不仅仅是html,应用非常广泛
url的编码
注意:在浏览器中输入url时,一旦出现了一些特殊字符(比如中文、空格)需要进行utf-8编码
网站访问的实现
用户点击url为http://www.qq.com/index.html的链接后浏览器和web服务器执行了以下动作
- 浏览器分析超链接的url
- 浏览器向dns请求解析www.qq.com的ip地址
- dns将解析出来的ip地址222.246.129.80返回给浏览器
- 浏览器与ip地址为222.246.129.80的服务器建立tcp链接(80)
- 浏览器请求文档:get/index.html
- 服务器给出响应,将文档index.html发送给浏览器
- 释放tcp连接
- 浏览器显示index.html内容
http注意事项:
- 基于tcp/ip协议
- 默认端口号位80
- 请求和响应一一对应
- 每次请求相互独立,是无状态协议
- http1.1(最经典最广泛的版本)之后支持可持续连接(多个请求可以共用一个tcp连接)
无状态性:其是指一个客户端(浏览器)第二次访问同一个web服务器上的页面时,服务器无法知道这个客户曾经访问过。http的无状态性简化了服务器的设计,使其更容易支持大量并发的http请求
请求方法
- get:常用于读取的操作,请求参数直接拼接在url的后面(浏览器对url是有长度限制的)
- post:常用于添加、修改、删除的操作,请求参数可以放到请求体中,请求体没有大小限制
- head:请求得到与get请求相同的响应,但没有响应体(使用场景:在下载一个大文件前,先获取其大小,再决定是否要下载。以此可以节约带宽资源)
- options:获取目的资源所支持的通信选项,比如服务器支持的请求方法
- put:对已存在的资源进行覆盖(如要上传一个东西用来覆盖之前的资源)
- patch:用于对资源进行部分修改(资源不存在,会创建新的资源)
- delete:用于删除指定资源
- trace:请求服务器回显其收到的请求信息,主要用于http请求的测试和诊断
- connect:可以开启一个客户端与所请求资源之间的双向沟通的通道,它可以用来创建隧道(tunnel)可以用来访问采用了ssl(https)协议的站点
get与post请求区别
- get请求参数直接显示在地址栏的,而post的请求参数放在请求体中
- get方式不安全,post安全
- get请求参数有限制,post没有限制
- get只能传输字符数据,post可以传输字节数据
请求头字段
http响应状态码
分类
常见状态码
- 100 continue:请求的初始部分已经被服务器收到,并且没有被服务器拒绝,客户端应该继续发送剩余的请求,若请求已经完成,就忽略这个响应
- 200 ok:请求成功
- 302 found:请求的资源被暂时移动到了location头部指定的url上
- 304 not modified:说明无需再次传输请求的内容,也就是说可以使用缓存的内容
- 400 bad request:由于语法无效,服务器无法理解该请求
- 401 unauthorized:缺乏目标资源需要的身份验证凭证
- 403 forbidden:服务器端有能力处理该请求,但是拒绝授权访问
- 404 not found:服务器端无法找到所请求的资源
- 405 method not allowed:服务器禁止使用当前的http方法的请求
- 406 not acceptable:服务器端无法提供与accept-charset以及accept-language指定的值相匹配的响应
- 408 request timeout:服务器想要将没有在使用的连接关闭(一般服务器会在空闲连接上发送此消息,即便在客户机没有发送任何消息的情况下)
- 500 internal server error:所请求的服务器遇到意外情况并阻止其执行请求
- 501 implemented:请求的方法不被服务器支持,因此无法被处理(服务器必须支持的方法:get、head)
- 502 bad gateway:作为网关或代理角色的服务器,从上有服务器(如tomcat)中接收到的响应是无效的
- 503 service unavailable:服务器尚未处于可以接收请求的状态(通常造成这种问题的原因是由于服务器停机维护或者已超载)
响应头字段
注意:请求头与响应头中的value值可以为多个,多个值之间用逗号隔开,也有很多value值有一定的权重用q表示,value值与权重之间用分号隔开,若value值没写权重则权重为1.0
缓存的理解
理解:浏览器想获得文件的数据的话,首先他会发起一个get请求到服务器,服务器就会返回一连串的数据给我们的浏览器(一连串的包,最后组成一个完整的文件);浏览器就会将服务器曾径返回的数据存到浏览器本地(可以放到浏览器的内存里面-memory cache,也可以放到浏览器所在的硬盘里面-disk cache)
注意:
- 实际上http缓存机制远远比上图的流程要复杂
- 通常会缓存的情况是:get请求 静态资源(比如html、css、js、图片等)
- ctrl f5可以强制刷新缓存
缓存的响应头
1.pragma:作用类似于cache-control,http/1.0的产物
2.expires:缓存的过期时间(gmt格式时间),http/1.1的产物
3.cache-control:设置缓存策略
- no-storage:不缓存数据到本地(意思就是我返回给你的文件不要缓存到本地)
- public:允许用户、代理服务器缓存数据到本地
- private:只是允许用户缓存数据到本地
- max-age:缓存的有效时间(多长时间不过期),单位秒
- no-cache:每次需要发请求给服务器询问缓存是否有变化,再来决定如何使用缓存
4.last-modified:资源的最后一次修改时间
5.etag:资源的唯一标识(相对于last-modified,优先级更高)
no-cache的理解
浏览器发请求给服务器索要资源,若收到的响应头设置为no-cache,那么服务器就会根据浏览器请求携带的信息来对比浏览器内过期的缓存与自己的要发的数据是否一致,若一致,则服务器返回304来告知客户端继续使用那个缓存;若不一致,则服务器将会把最新的数据发送给客户端,客户端将其缓存到本地
注意:
- 缓存过期时间优先级:pragma>cache>expires
- 缓存是有有效时间的,假设缓存的有效时间是120s(在120s期间,无论客户端怎么刷新页面,都不会发请求给服务器,都是用浏览器本地的缓存)
缓存的请求头
- if-none-match:若上一次的响应头中有etage,就会将etage的值作为请求头的值发给服务器,若服务器发现资源的最新摘要值跟if-none-match不匹配,就会返回新的资源(200 ok)否则,就不会返回资源的具体数据(304 not modified)
- if-modified-since:若上一次的响应头中没有etage,有last-modified,就会将last-modified的值作为请求头的值发给服务器,若服务器发现资源的最新摘要值跟if-modified-since不匹配,就会返回新的资源(200 ok)否则,就不会返回资源的具体数据(304 not modified)
last-modified(最先出现的)的缺陷
- 只能精确到秒级别,若资源在一秒内被修改了,客户端将无法获取最新资源的数据
- 若某些资源被修改了,但是又被改回来了(最后一次修改时间发生变化),但是内容却没有任何变化(会导致相同的数据被重复传输,没有使用到缓存)
注意:相比last-modified,etage可以做到只要资源的内容没有变化,就不会传输资源数据;只要资源的内容发生了变化,就会返回最新的资源数据给客户端
缓存的使用流程
理解:
- 浏览器发起get请求,请求的时候会看自己的本地有没有缓存,第一次访问没有本地缓存,那么就会直接请求服务器,然后服务器返回200 ok,然后看服务器返回给我们的cache-control响应头,若该值为no-storage,那么就不缓存到本地;若该值不为no-storage,那么就将获得的数据缓存到本地。
- 此时浏览器有发了一个相同的get请求,然后浏览器就会看看是否有本地缓存,由于是第二次,所以本地会有缓存;这时就会看当初缓存里面的响应头cache-control是否是no-cache,若该值不是no-cache那么就会看看缓存是否过期,若缓存没过期,那么直接使用本地缓存,否则看响应头是否有etage(若catch-control为no-cache也会直接走这条路线),若上一次有etag字段,那么就会发个请求头给服务器并且在请求头带有if-none-match字段,若服务器发现该值与最新值的etage值不匹配,那么服务器便会响应200 ok将最新值发给客户端,否则便会响应304让客户端继续使用本地缓存资源,若响应头没有etage字段,那么就会查看该响应头有没有last-modified,若有last-modified那么就会请求服务器,并在请求头带上if-modified-since字段,若服务器发现该值与last-modified一致,那么就会返回304告知客户端使用本地缓存,否则服务器便会响应客户端200 ok;若响应头也没有last-modified字段,那么就会直接请求浏览器,浏览器便会响应客户端200 ok。
前言
- http/1.0:发起请求首先要建立连接,中间进行通信,通信结束后,就将连接断开;若要发起下一个请求,那么就需要建立下一个连接
- http/1.1:就建立一个连接,在这个连接里面可以发送多次请求(在这个连接里面发一次请求进行通信,这次请求完毕之后可以再发一次请求进行通信)同一时间一个连接只能对应一个请求;若想同时发起多个请求,那么就需要建立多个连接(针对同一个域名,大多数浏览器允许同时最多6个并发连接)
以上协议的缺陷
- 只允许客户端主动发起请求
- 同一个会话的多次请求中,头信息会被重复传输
前言:(speedy的缩写)其是基于tcp的应用层协议,它强制要求使用ssl/tls,2009年11月,google宣布将spdy作为提高网络速度的内部项目
spdy与http的关系
- spdy并不用取代http,它只是修改了http请求与响应的传输方式
- 秩序增加一个spdy层,现有的所有服务器端应用不用做任何修改
- spdy是http/2的前身
前言:http/2在底层传输做了很多的改进和优化,但在语义上完全与http/1.1兼容,比如请求方法、状态码、各种headers等都没改变,因此想要升级到http/2开发者不需要修改任何代码,只需要升级服务器配置,升级浏览器
http/2的一些基本概念
数据流:已经建立的连接内的双向字节流,可以承载一条或多条消息(所有的通信都在一个tcp连接上完成,此链接可以承载任意数量的双向数据流)
消息:与逻辑http请求或响应消息对应,由一系列帧组成。
帧:http/2通信的最小单位,每个帧都包含帧头(会标识出当前帧所属的数据流)
注意:来自不同数据流的帧可以交错发送,然后根据每个帧头的数据流标识符进行重新组装
http/2的特性
二进制传输数据
http/2采用二进制格式传输数据,而非http/1.1的文本格式(二进制格式在协议的解析和优化扩展上带来更多的优势和可能)
帧的交错发送
客户端和服务器可以将http消息分解为互不依赖的帧,然后交错发送,最后在另一端把他们重新组装起来;使用一个连接,并行发送多个请求和响应,他们之间互不干扰
设置权重表明接收响应的优先级
http/2的标准,允许每个数据流都有一个关联的权重和依赖关系
- 可以向每个数据流分配一个介于1-256之间的整数
- 每个数据流与其他数据流之间可以存在显存依赖关系
客户端可以构建和传递“优先级树”,表明它倾向于如何接收响应
服务器可以使用此信息通过控制cpu、内存和其他资源的分配设定数据流处理的优先级,在资源可用之后,确保将高优先级响应以最优方式传输至客户端
注意:
- 应尽可能先给父数据流分配资源
- 同级数据流(共享相同父项)应按其权重比例分配资源
http/2的头部压缩技术
注意:
- http/2使用hpack压缩请求头和响应头,可极大的减少头部开销,进而提高性能
- 早期版本的http/2和spdy使用zlib压缩可以将所传输头数据的大小减小85%-88%,但在2012年夏天,被攻击导致会话劫持后被更安全的hpack取代
http/2的服务器推送技术
含义:服务器可以对一个客户端请求发送多个响应,除了对最初请求的响应外,服务器还可以向客户端推送额外资源,而无需求客户端额外的明确需求
举例:本来我只是请求html,但是服务器发现这个html里面有很多图片,那么服务器便会将自己有的都推给我们
http/2的问题
队头阻塞
http/2是基于tcp的,tcp协议的话,那么最终要拿的包还是要保证有序的;若传给tcp的一堆有顺序的包中的其中一个包丢失,那么后面的包就不能往上取,就会导致应用层一直拿不到该请求
注意:由于quic底层用到的是udp协议,那么quic就没有该问题
握手延迟
注意:rtt(round trip time) 往返时延,可以简单的理解为通信一来一回的时间
前言
- google觉得http/2仍然不够快,于是就有了http/3
- http/3由google开发,弃用了tcp协议,改用udp协议和quic协议实现
- quic(quick udp internet cnnections)快速udp网络连接,由google开发,在2013年实现,于2018年从http-over-quic改名为http/3
注意:http/3的可靠传输由quic来保证
http/3的特性
连接迁移
tcp基于4要素(源ip、目标ip、源端口、目标端口)切换网络时至少有一个要素发生变化,那么就会导致连接发生变化;当连接发生变化时,若还使用原来的tcp连接,则会导致连接失败,就得等原来的连接超时后重建连接;所以我们有时候发现切换到一个网络时,即使新网络状态良好,但内容还是需要加载很久,若实现的好,当检测到网络变化时立刻建立新的tcp连接,即使这样,建立新连接还需要几百毫秒时间
quic的连接不受4要素的影响,当4要素发生改变时,源连接依然维持;其主要使用一组connection id来标识一个连接,即使ip或端口发生变化,只要connect id没变化,那么依然可以维持
操作系统内核、cpu负载
据google和facebook称,与基于tls的的http/2相比,他们大规模部署的quic需要将近2倍的cpu使用量,linux内核的udp部分没有得到像tcp那样的优化,因为传统上没有使用udp进行如此高速的信息传输,tcp和tls有硬件加速,而这对于udp很罕见,对于quic则基本不存在