当前位置: 首页 > news >正文

做决定网站十大旅游电子商务网站

做决定网站,十大旅游电子商务网站,阿里云网站备案,中信建设有限责任公司建筑院HTTP 为什么会出现 HTTP 协议#xff0c;从 HTTP1.0 到 HTTP3 经历了什么#xff1f;HTTPS 又是怎么回事#xff1f; HTTP 是一种用于获取类似于 HTML 这样的资源的 应用层通信协议#xff0c; 他是万维网的基础#xff0c;是一种 CS 架构的协议#xff0c;通常来说从 HTTP1.0 到 HTTP3 经历了什么HTTPS 又是怎么回事 HTTP 是一种用于获取类似于 HTML 这样的资源的 应用层通信协议 他是万维网的基础是一种 CS 架构的协议通常来说HTTP 协议一般由浏览器等 “客户端” 发起发起的这个请求被称为 Request, 服务端接受到客户端的请求后会返回给客户端所请求的资源这一过程被称为 Response在大部分情况下客户端和服务器之间还可能存在许多 proxies他们的作用可能各不相同有些可能作为网关存在有些可能作为缓存存在。 HTTP 协议有三个基本的特性 简单HTTP 的协议和报文是简单易于理解和阅读的HTTP/2 已经改用二进制传输数据但 HTTP 整体还是简单的可拓展的请求和响应都包括 “Header” 和 “Body” 两部分我们可以通过添加头部字段轻松的拓展 HTTP 的功能无状态的服务端不保存客户端状态也就是说每一次请求的服务端来说都是唯一无差别的我们只能通过 Cookie 等技术创建有状态的会话。 HTTP 的历史 HTTP 的历史可以追溯到万维网刚被发明的时候1989年 Tim Berners-Lee 博士写了一份关于建立一个通过网络传输超文本系统的报告。该系统起初被命名为 Mesh在随后的1990年项目实施期间被更名为万维网*World Wide Web。他以现有的 TCP IP 协议为基础建造 由四个部分组成 用来表示超文本文档的文本格式即超文本标记语言HTML一个用来传输超文本的简单应用层协议即超文本传输协议HTTP一个用来显示或编辑超文本文档的客户端即网络浏览器而第一个浏览器则被称为 WorldWideWeb一个用于提供可访问文档的服务httpd 的前身. 这四部分在 1990 年底完成这时候的 HTTP 协议还很简单后来为了于其他版本的协议区分最初的 HTTP 协议被记为 HTTP/0.9 后来随着计算机技术的发展HTTP 协议也随着 HTTP/1.0, HTTP/1.1, HTTP/2 等关键版本更迭变得更加高效实用。 HTTP/0.9 on-line 最初的 0.9 版本也被称为单行协议on-line, 基于 TCP 协议该版本下只有一个可用的请求方法GET 请求格式也相当简单 GET /index.html它表示客户端请求 index.html 的内容0.9 版本的 HTTP 响应也同样简单他只允许响应 HTML 格式的字符串如 htmlh1 ..... /h1 /html这一阶段的响应甚至没有响应头也没有响应码或错误代码一旦出现问题服务端会响应一段特殊的 HTML 字符串以便客户端查看。 服务端在发送完数据后就会立刻关闭 TCP 连接。 HTTP/1.0 0.9 版本的 HTTP 协议太过于简单甚至是简陋而随着浏览器和服务器的应用被扩展到越来越多的领域0.9 版本的协议已经不能适应直到 1996年11月RFC 1945 定义了 HTTP/1.0, 但他并不是官方标准该版本的 HTTP 协议较 0.9 版本有了一下改变 版本号被添加到了请求头上像下面这样 GET /mypage.html HTTP/1.0引入了 HTTP头的概念无论是请求还是响应允许传输元数据这使得协议更加灵活和具有拓展性。 请求方法拓展到了 GETHEADPOST 在新 HTTP 头Content-Type的帮助下可以传输不止 HTML 的任意格式的数据。 响应时带上了状态码使得浏览器能够知道响应的状态并作出响应的处理。 … HTTP/1.1 同 0.9 版本一样1.0 版本下TCP 连接是不能复用的数据发送完后服务端会立刻关闭连接但由于建立 TCP 连接的代价较大所以 1.0 版本的 HTTP 协议并不是足够高效加上 HTTP/1.0 多种不同的实现方式在实际运用中显得有些混乱自1995年就开始了 HTTP 的第一个标准化版本的修订工作到1997年初HTTP1.1 标准发布。 1.1 版本的改进包括 支持长连接在 HTTP1.1 中默认开启 Connection keep-alive允许在一个 TCP 连接上传输多个 HTTP 请求和响应减少了建立和关闭连接造成的性能消耗。 支持 pipline: HTTP/1.1 还支持流水线pipline工作流水线是指在同一条长连接上发出连续的请求而不用等待应答返回。这样可以避免连接延迟。 支持响应分块对于比较大的响应HTTP/1.2 通过 Transfer-Encoding 首部支持将其分割成多个任意大小的分块每个数据块在发送时都会附上块的长 度最后用一个零长度的块作为消息结束的标志。 新的缓存控制机制HTTP/1.1定义的 Cache-Control 头用来区分对缓存机制的支持情况同时还提供 If-None-Match, ETag , Last-Modified, If-Modified-Since 等实现缓存的验证等工作。 允许不同域名配置到同一IP的服务器上在 HTTP/1.0 时认为每台服务器绑定一个唯一的 IP但随着技术的进步一台服务器的多个虚拟主机会共享一个IP为了区分同一服务器上的不同服务HTTP/1.1 在请求头中加入了 HOST 字段它指明了请求将要发送到的服务器主机名和端口号这是一个必须字段请求缺少该字段服务端将会返回 400. 引入内容协商机制包括语言编码类型等并允许客户端和服务器之间约定以最合适的内容进行交换。 使用了 100 状态码HTTP/1.0 中定义 o 1xx: Informational - Not used, but reserved for future use在 2.0 版本时使用了这个保留的状态码用来表示临时响应。 HTTPS HTTP/1.1 之后对 HTTP 协议的拓展变得更加简单但 HTTP 依然存在一个天然的缺陷就是明文传输数据直到 1994 年底网景公司在 TCP/IP 协议栈的基础上添加了 SSL 层用来加密传输后来在标准化的过程中 SSL 成了 TLS Transport Layer Security 传输层安全协议基于 HTTPS 通信的客户端和服务器在建立完 TCP 连接之后会协商通信密钥在之后的通信过程中 客户端和服务器会使用该密钥对数据进行对称加密以防数据被窃取或篡改。密钥协商阶段会使用非对称加密。 HTTP/2 HTTP/1.1 虽然允许连接复用和以流水线方式运作但在一个 TCP 连接里面所有数据依然还是按序发送的服务器只能处理完一个请求再去处理另一个请求如果第一个请求非常慢就会造成后面的请求长时间阻塞这被称为 队头阻塞Head-of-line blocking2009 年谷歌公开了自行研发的 SPDY 协议它基于 HTTPS并采用多路复用解决了队头阻塞的问题同时它还使用了 Header 压缩等技术大大降低了延时并提高了带宽利用率在之后的 2015 到 2019 年间谷歌在自家浏览器上实践和证明了这个协议SPDY 也成了 HTTP/2 的基石。 2015 年 5 月 HTTP/2 正式标准化他与 1.x 版本 不同在于 1.x 版的 HTTP 协议传输的是文本信息这对开发者很友好但却浪费了计算机的性能HTTP/2 改成了基于二进制而不再是基于文本的协议这是一个复用协议。并行的请求能在同一个链接中处理移除了HTTP/1.x中顺序和阻塞的约束。压缩了headers。因为headers在一系列请求中常常是相似的其移除了重复和传输重复数据的成本。其允许服务器在客户端缓存中填充数据通过一个叫服务器推送的机制来提前请求。 虽然 HTTP/2 2015 年就被标准化在到目前为止HTTP/1.1 任然被广泛使用据 MySSL 的最新统计截至 2020 年 12 月已有 65.84% 的站点支持了 HTTP/2. HTTP/3 HTTP/3 是即将到来的第三个主要版本的 HTTP 协议在 HTTP/3 中将弃用 TCP 协议改为使用基于 UDP 的 QUIC 协议实现。QUIC快速UDP网络连接是一种实验性的网络传输协议由Google开发该协议旨在使网页传输更快。 在2018年10月28日的邮件列表讨论中IETF(互联网工程任务组) HTTP和QUIC工作组主席 Mark Nottingham 提出了将 HTTP-over-QUIC 更名为 HTTP/3 的正式请求以“明确地将其标识为HTTP语义的另一个绑定……使人们理解它与 QUIC 的不同”并在最终确定并发布草案后将 QUIC 工作组继承到 HTTP 工作组, 在随后的几天讨论中Mark Nottingham 的提议得到了 IETF 成员的接受他们在2018年11月给出了官方批准认可 HTTP-over-QUIC 成为 HTTP/3。 2019年9月HTTP/3支持已添加到 CloudFlare 和 Chrome 上。Firefox Nightly 也将在2019年秋季之后添加支持。 HTTP/1.1 细节 HTTP报文 HTTP 的报文都由消息头和消息体两部分组成两者之间以 CRLF(回车换行) 分割。 请求头格式 请求头第一行为请求行其余为请求头字段如下 POST /api/article/list HTTP/1.1 Host: junebao.top:8888 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0 Accept: application/json, text/plain, */* Accept-Language: zh-CN,zh;q0.8,zh-TW;q0.7,zh-HK;q0.5,en-US;q0.3,en;q0.2 Accept-Encoding: gzip, deflate, br Content-Type: application/json;charsetutf-8 Content-Length: 32 Origin: https://junebao.top Connection: keep-alive Referer: https://junebao.top/ Cache-Control: max-age0请求行由三部分组成 请求方法请求资源的 url协议版本 他们以空格分隔RFC2068 定义了其中不同的请求方法他们分别为 OPTIONS GET HEAD POST PUT DELETE TRACE,除此之外后来还添加了一个 PATCH 方法。 方法基本用法请求响应幂等性缓存安全性OPTIONS获取目的资源所支持的通信选项,如检测服务器所支持的请求方法或CORS预检请求不能携带请求体或数据可以携带响应体但一般有效数据被放在头部如 Allow 等字段幂等不可缓存安全GET用于获取某个资源参数一般携带在 URL 后面没有请求体有响应体幂等可缓存安全HEAD用于请求资源的头部信息如下载前获取大文件的大小没有请求体没有响应体响应头应该与使用 GET 请求时的一样幂等可缓存安全POST将数据发送给服务器数据放在请求体中有响应体不幂等可缓存包含新鲜信息时不安全PUT使用请求中的负载创建或替换目标资源数据放在请求体中有响应体幂等不可缓存不安全DELETE删除指定资源可以由请求体可以由响应体幂等不可缓存不安全TRACE回显服务器收到的请求主要用于测试或诊断。无请求体无响应体幂等不可缓存不安全PATCH作为 PUT 的补充用于修改已知资源的部分有请求体无响应体非幂等不可缓存不安全 请求头字段 RFC 2068 提供了 17 种请求头字段但 HTTP 协议是易于拓展的我们可以根据自己的需要添加自己的请求头常见的请求头字段包括 字段作用示例HOST指明了要发送到的服务器的主机号和端口号这是一个必须字段缺失服务器一般会返回 400,端口号默认 80 和 443Host: www.baidu.comACCEPT告知服务器客户端可以处理的内容类型用MIME类型来表示。Accept: text/htmlUser-Agent用户代理标识Cookies用于维持会话……… 响应头格式 Response Status-Line*( general-header| response-header| entity-header )CRLF[ message-body ]类似于请求头响应头包括状态行和响应头字段两部分组成。 状态行包括协议版本状态码状态描述三部分组成类似 http/2 200 ok目前 http 使用的状态码分为 5 类 1xx: 信息响应类2xx: 正常响应类3xx: 重定向类4xx: 客户端错误类5xx: 服务端错误类 常见状态码 状态码描述作用100Continue迄今为止的所有内容都是可行的客户端应该继续请求200Ok请求成功201Created该请求已成功并因此创建了一个新的资源。这通常是在POST请求或是某些PUT请求之后返回的响应。301Moved Permanently永久重定向302Found临时重定向400Bad Request请求参数错误或语义错误401Unauthorized请求未认证403Forbidden拒绝服务404Not Found资源不存在429Too Many Requests超过请求速率限制节流500Internal Server Error服务端未知异常501Not Implemented此请求方法不被服务端支持502Bad Gateway网关错误503Service Unavailable服务不可用504Gateway Timeout网关超时505HTTP Version Not SupportedHTTP 版本不被支持 无状态的 HTTP HTTP 是一个无状态的协议为了维持会话每客户端请求时都应该携带一个 “凭证”证明 who am i, 目前维持会话常用的技术有cookie, session, token, 等 cookie RFC 6265 定义了 Cookie 的工作方式, Cookie 是服务器发送给客户端并存储在本地的一小段数据在用户第一次登录时服务器生成 Cookie 并在响应头里添加 Set-Cookie 字段客户端收到响应后将 Set-Cookie 字段的值Cookie存储在本地以后每次请求时客户端会自动通过 Cookie 字段携带 Cookie。 Cookie 以键值的形式储存除了必须的 Name 和 Value还可以为 Cookie 设置以下属性 Domain指定了哪写主机可以接收该 Cookie默认为 Origin 不包含子域名。Path规定了请求主机下的哪些路径时要携带该 Cookie。Expires/Max-Age: 规定该 Cookie 过期时间或最大生存时间该时间只与客户端有关。HttpOnly: JavaScript Document.cookie API 无法访问带有 HttpOnly 属性的cookie,用于预防 XSS 攻击用于持久化会话的 Cookie 一般应该设置 HttpOnly 。Secure标记为 Secure 的 Cookie 只能使用 HTTPS 加密传输给服务器因此可以防止中间人攻击但 Cookie 天生具有不安全性任何敏感数据都不应该使用 Cookie 传输哪怕标记了 secure.PrioritySameSite要求该 Cookie 在跨站请求时不会被发送用来阻止 CSRF 攻击它有三种可选的值 None在同站请求和跨站请求时都会携带上 CookieStrict只会在访问同站请求时带上 CookieLex与 Strict 类似但用户从外部站点导航至URL时例如通过链接除外新版浏览器一般以 Lex 为默认选项。 Cookie 被完全保存在客户端对客户端用户来说是透明的用户可以自己创建和修改 Cookie所以将敏感信息如用于持久化会话的用户身份信息等存放在 Cookie 中是十分危险的如果不得已需要使用 Cookie 来存储和传递这类信息应该考虑使用 JWT 等类似机制。 由于 Cookie 的不安全性绝大部分 Web 站点已经开始停止使用 Cookie 持久化会话但 Cookie 在一些对安全性要求不高的场景下依然被广泛使用如 个性化设置浏览器用户行为跟踪。 了解更多 超级 Cookie 和僵尸 Cookie 决战僵尸 Cookie SESSION Cookie 不安全的根源在于它将会话信息保存在了客户端为此就有了使用 Session 持久化会话的方案用户在第一次登录时服务器会将用户会话状态信息保存在服务器内存中同时会为这段信息生成一串唯一索引将这个索引作为 Cookie Name 一般为 SESSION_IDSESSION_ID返回给客户端客户端下一次请求时会自动携带这个 SESSION_ID, 服务器只需要根据 SESSION_ID 的值找到对应的状态信息就可以知道这次请求是谁发起的。 SESSION 很大程度上还是依赖于 Cookie但这时 Cookie 中保存的已经是一段对客户端来说无意义的字符串了因此使用 Session 能安全的实现会话持久化但 Session 信息被保存在服务器内存中可能造成服务器压力过大并且在分布式和前后端分离的环境下Session 并不容易拓展。 TOKEN Cookie 和 Session 都是开箱即用的 API因此他们不可避免地缺少灵活性在一般开发中往往采用更灵活地 TokenToken 与 Session 原理一致都是将会话信息保存到服务器然后向客户端返回一个该信息的索引token但 Token 完全由开发者实现可以根据需要将会话信息存储在内存数据库文件等地方而对于该信息的索引也可以根据具体需要选择使用请求头请求体或者 Cookie 传递也不必拘束于只 Cookie 传递。 JWT 全称 json web token, 是一种客户端存储会话状态的技术它使用数字签名技术防止了负荷信息被篡改jwt 包含三部分信息 Header包含 token 类型和算法名称Payload存储的负载信息敏感信息不应该明文存放在此Signature服务端使用私钥对 Header 和 Payload 的签名防止信息被篡改。 这三部分原本都是 json 字符串最终他们会经过 Base64 编码后拼接到一起使用 . 分割。 分布式解决方案 在分布式场景下同一用户的不同次请求可能会被打到不同的服务器上这时如果还像单机时那样存储就会出问题一般的解决方案包括 粘性 session将用户绑定到一台服务器上如 Nginx 负载均衡策略使用 ip_hash, 但这样如果当前服务器发生故障可能导致分配到这台服务器上的用户登录信息失效容错度低。session 复制一台服务器的 session 改变就广播给所有服务器但会影响服务器性能session 共享把所有服务器的 session 放在一起如使用 redis 等分布式缓存做 session 集群。客户端记录状态使用诸如 JWT 之类的方法。 连接管理 连接管理是一个 HTTP 的关键话题打开和保持连接在很大程度上影响着网站和 Web 应用程序的性能。在 HTTP/1.x 里有多种模型短连接 长连接和HTTP 流水线 短连接 HTTP 最早期的模型也是 HTTP/1.x 的默认模型是短连接。每发起一个HTTP请求都会通过三次握手建立一个TCP连接在接受到数据之后再通过四次挥手释放连接因为TCP连接的建立和释放都是一个耗时操作加之现代网页可能需要多次连续请求才能渲染完成这就显得这种简单的模型效率低下。 TCP 协议握手本身就是耗费时间的所以 TCP 可以保持更多的热连接来适应负载。短连接破坏了 TCP 具备的能力新的冷连接降低了其性能。 为此HTTP/1.1 时新增加了两种连接管理模式分别是长连接和流水线在HTTP/2 中又基于数据流采用了新的连接管理模式。 长连接 长连接是指在客户端接受完数据后不立刻关闭这个 TCP 连接这个连接还可以用来发送和接收其他 HTTP 数据这样一来可以减少部分连接建立和释放的耗时但这个连接也并不会一直保持服务端可以设置 Keep-alive 标头来指定一个最小的连接保持时间单位秒和最大请求数 HTTP/1.1 200 OK Connection: Keep-Alive Keep-Alive: timeout5, max1000HTTP/1.0 里默认并不使用长连接。把 Connection 设置成 close 以外的其它参数都可以让其保持长连接通常会设置为 retry-after。 在 HTTP/1.1 里默认就是长连接的协议头都不用再去声明它(但我们还是会把它加上万一某个时候因为某种原因要退回到 HTTP/1.0 呢)。 长连接并不总是好的比如他在空闲状态下仍会消耗服务器资源而在网络重负载时还有可能遭受 DoS 攻击。这种场景下可以使用非长连接即尽快关闭那些空闲的连接也能对性能有所提升。 流水线 默认情况下HTTP 请求是按顺序发出的。下一个请求只有在当前请求收到应答过后才会被发出。由于会受到网络延迟和带宽的限制在下一个请求被发送到服务器之前可能需要等待很长时间。 流水线是在同一条长连接上发出连续的请求而不用等待应答返回。这样可以避免连接延迟。理论上讲性能还会因为两个 HTTP 请求有可能被打包到一个 TCP 消息包中而得到提升就算 HTTP 请求不断的继续导致 TCP 包的尺寸增加通过设置 TCP 的 MSS(Maximum Segment Size) 选项流水线方式仍然足够包含一系列简单的请求。 使用流水线的另一个需要注意的问题是错误重传因此只有幂等的方法如 GETHEADPUT DELETE 等方法能够安全地使用流水线。 流水线只是针对客户端来说的服务器依然和非流水线方式那样工作这就导致如果第一个请求非常耗时那流水线上后面的请求就会被阻塞住这种现象被称为Head-of-line blocking队头阻塞除此之外复杂的网络环境和代理服务器也可能会导致流水线不能像预期的那样高效工作因此现代浏览器都没有默认启用流水线在 HTTP/2 里有更高效的算法代替了流水线。 三者比较 CORS 在前后端分离开发时你也许遇到过类似这样的报错 Access to XMLHttpRequest at * from origin * has been blocked by CORS policy: Response to preflight request doesnt pass access control check: No Access-Control-Allow-Origin header is present on the requested resource.这就是 CORS 的问题了所谓 CORS Cross-Origin Resource Sharing跨域资源共享它首先是一个系统由一系列 HTTP 头组成这些 HTTP 头决定了浏览器是否阻止前端 JavaScript 代码获取跨域请求的响应。 之所以需要 CORS是由于浏览器的同源安全策略 同源安全策略 同源安全策略用来限制一个源origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档减少可能被攻击的媒介。 只有两个 URL 的协议主机端口都相同时他们才被认为是“同源的”反之如http://www.a.com 和 https://www.a.com 则会被认为是不同源的协议不同在默认情况下同源策略会阻止通过不同源的URL获取资源而 CORS 就是提供了一种机制以允许不同源的资源进行共享。 原理 CORS 的原理很简单它通过添加一组 HTTP 头允许服务器声明哪些源站通过浏览器有权限访问哪些资源。另外规范要求对那些可能对服务器数据产生副作用的 HTTP 请求方法非简单请求浏览器必须首先使用 OPTIONS 方法发起一个预检请求从而获知服务端是否允许该跨源请求。服务器确认允许之后才发起实际的 HTTP 请求。在预检请求的返回中服务器端也可以通知客户端是否需要携带身份凭证包括 Cookies 或 HTTP 认证相关数据。 上面说到的 “可能对服务器数据产生副作用的 HTTP 请求” 就是非简单请求not-so-simple request与之对应的是简单请求simple request同时满足以下几个条件的属于简单请求。 请求方法是以下三种方法之一 HEADGETPOST 首部字段只包含被用户代理自动设置的首部字段例如 Connection User-Agent和允许人为设置的字段为 Fetch 规范定义的 对 CORS 安全的首部字段集合。该集合为 Accept Accept-Language Content-Language Content-Type, 只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain DPR Downlink Save-Data Width Viewport-Width 请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。 请求中没有使用 ReadableStream 对象。 只要有其一不满足就是费简单请求非简单请求在正式请求之前会先使用 OPTION 方法像服务器发起一个 预检请求如下面这个请求 var invocation new XMLHttpRequest(); var url http://bar.other/resources/post-here/; var body ?xml version1.0?personnameArun/name/person;function callOtherDomain(){if(invocation){invocation.open(POST, url, true);invocation.setRequestHeader(X-PINGOTHER, pingpong);invocation.setRequestHeader(Content-Type, application/xml);invocation.onreadystatechange handler;invocation.send(body);} }当前域为 foo.example.com,请求 bar.other, 属于跨域请求并且请求时自己添加了一个请求头 X-PINGOTHER ,并且 Content-Type 类型为 application/xml, 所以它属于一个非简单请求在实际请求之前需要使用 OPTION 方法发一个预检请求 OPTIONS /resources/post-here/ HTTP/1.1 Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre Accept: text/html,application/xhtmlxml,application/xml;q0.9,*/*;q0.8 Accept-Language: en-us,en;q0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q0.7,*;q0.7 Connection: keep-alive Origin: http://foo.example Access-Control-Request-Method: POST Access-Control-Request-Headers: X-PINGOTHER, Content-TypeHTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:39 GMT Server: Apache/2.0.61 (Unix) Access-Control-Allow-Origin: http://foo.example Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-PINGOTHER, Content-Type Access-Control-Max-Age: 86400 Vary: Accept-Encoding, Origin Content-Encoding: gzip Content-Length: 0 Keep-Alive: timeout2, max100 Connection: Keep-Alive Content-Type: text/plain预检请求头头中最重要的部分有下面几个 Host: 要请求的域Origin: 发起请求的域Host 和 Origin 不一样说明是跨域请求Access-Control-Request-Method: 正式的请求将要使用的方法Access-Control-Request-Headers: 正式请求将携带的自定义字段 服务器在收到这样的预检请求后就可以根据请求头决定是否允许即将发送的实际请求在服务器的响应中最重要的字段有以下几个 Access-Control-Allow-Origin 服务器允许的域允许所有域该值设置为 *Access-Control-Allow-Methods: 服务器允许的请求方法允许所有方法设置为 *Access-Control-Allow-Headers: 服务器允许的请求头Access-Control-Max-Age: 该响应的有效时间为 86400 秒也就是 24 小时。在有效时间内浏览器无须为同一请求再次发起预检请求。 接受到响应后浏览器会自动判断实际请求是否被允许如果不被允许将会报上面的错误。 对于简单请求通过请求中的 Origin 和响应中的 Access-Control-Allow-Origin 就可以实现简单的访问控制如果请求的 Origin 不在许可范围内服务器会返回一个正常的响应浏览器发现这个响应的头信息没有包含Access-Control-Allow-Origin字段就知道出错了从而抛出一个错误被XMLHttpRequest的onerror回调函数捕获。注意这种错误无法通过状态码识别因为HTTP回应的状态码有可能是200。 HTTP 缓存 缓存是一种保存资源副本并在下次请求时直接使用该副本的技术。当 web 缓存发现请求的资源已经被存储它会拦截请求返回该资源的拷贝而不会去源服务器重新下载。这样带来的好处有缓解服务器端压力提升性能(获取资源的耗时更短了)。对于网站来说缓存是达到高性能的重要组成部分。缓存需要合理配置因为并不是所有资源都是永久不变的重要的是对一个资源的缓存应截止到其下一次发生改变即不能缓存过期的资源。 缓存有很多种以服务对象分类缓存可以分为私有缓存和共享缓存以行为分类又可以把它分为强制缓存和对比缓存。 私有缓存又叫浏览器缓存只能用于单独用户。浏览器缓存拥有用户通过HTTP下载的所有文档。这些缓存为浏览过的文档提供向后/向前导航保存网页查看源码等功能可以避免再次向服务器发起多余的请求。它同样可以提供缓存内容的离线浏览。共享缓存又叫代理缓存共享缓存可以被多个用户使用。例如ISP 或你所在的公司可能会架设一个 web 代理来作为本地网络基础的一部分提供给用户。这样热门的资源就会被重复使用减少网络拥堵与延迟。强制缓存缓存数据未失效时都可以使用缓存。对比缓存使用数据前需要请求服务器验证缓存是否失效。 缓存控制 缓存的原理很简单客户端在从服务器获取到数据后可以选择将这些数据存储下来下一次请求同样的数据时就可以不请求服务器直接返回先前存储的数据了正确使用缓存可以提高响应速度降低服务器压力 这里的客户端可以是浏览器如私有缓存也可以是请求链路上的中间代理如共享缓存但对服务器来说他们都是一样的而服务器并没有办法主动向客户端推送数据这就导致必须有一种机制去保证缓存是“新鲜”的HTTP 协议通过一些列的头字段实现了缓存控制其中最重要的字段是 Cache-Control,他有以下几种值 Cache-Control: no-store: 禁用缓存缓存不会存储任何响应数据每次请求都从服务器获取最新的数据。Cache-Control: no-cache: 使用缓存但需要服务器重新验证此方式下每次有请求发出时缓存会将此请求发到服务器服务器端会验证请求中所描述的缓存是否过期若未过期返回304则缓存才使用本地缓存副本。Cache-Control: private: 私有缓存表示该响应是专用于某单个用户的中间人不能缓存此响应该响应只能应用于浏览器私有缓存中。Cache-Control: public:表示该响应可以被任何中间人比如中间代理、CDN等缓存。若指定了public则一些通常不被中间人缓存的页面默认是private比如 带有HTTP验证信息帐号密码的页面 或 某些特定状态码的页面将会被其缓存。Cache-Control: max-age31536000: 表示资源能被缓存的最大时间单位秒。Cache-Control: must-revalidate: 缓存在考虑使用一个陈旧的资源时必须先验证它的状态已过期的缓存将不被使用。 强制缓存 在某个资源的响应中如果 Cache-Control:max-age31536000, 则表明这个资源在未来一年内再次请求可以直接从缓存中拿如第一次请求 avatar.png 时响应里标明最大有效时间为 600s (10 分钟)第二次再次请求该资源时从 size 列就可以看倒该资源直接从缓存返回。 第一次未使用缓存第二次使用强制缓存[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GR4bBSEk-1613829654718)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210115164159878.png)] 这里的缓存就是强制缓存只要在10分钟内都可以使用缓存的资源。 如果过了10分钟缓存中的这个资源就可能是过期了的这时就需要询问服务器这个资源是不是“新鲜”的具体客户端会向服务器发起一个携带 [If-None-Match](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match) 头的请求 如果这个资源是“新鲜”的服务器会返回 304 (Not Modified)该响应不会有带有实体信息如果服务器发现这个资源已经过期了则会返回新的资源。 对比缓存 与强制缓存不同对比缓存每次使用缓存数据前都会向服务器查询该资源是否有效但由于查询和响应大部分情况下都只包含头部所以比起不使用缓存对比缓存也可以大大提高响应速度和降低服务器压力。它依赖于下面几个头部字段 Last-Modified: 响应头字段告诉客户端这个资源最后更新的时间If-Modified-Since: 请求头字段如果请求头中携带了这个字段服务器会将该字段的值和资源最后修改的时间做对比如果最后修改的时间大于字段值说明数据已经被修改则响应 200 返回最新的资源否则响应 304 告诉客户端资源未修改可以使用缓存。 上面两个头部字段是根据修改时间判断资源是否是新鲜的这样做的准确度不是很高还有一组头部字段 ETag 和 If-None-Match 使用资源的唯一标识来判断资源是否被修改 ETag: 响应头字段用于服务器告诉客户端资源的唯一标识标识的生成规则由服务端确定If-None-Match: 请求头字段如果请求头中包含此字段服务端会对比该字段的值与最新的资源的标识如果不相同说明资源被修改响应 200 返回最新的资源否则响应 304. ETag 和 If-None-Match 的优先级高于 Last-Modified 和 If-Modified-Since 除此之外与缓存相关的还有一个请求头Vary, 用来决定客户端使用新资源还是缓存资源使用vary头有利于内容服务的动态多样性。例如使用Vary: User-Agent头缓存服务器需要通过UA判断是否使用缓存的页面。如果需要区分移动端和桌面端的展示内容利用这种方式就能避免在不同的终端展示错误的布局。另外它可以帮助 Google 或者其他搜索引擎更好地发现页面的移动版本并且告诉搜索引擎没有引入Cloaking。 使用缓存 说了这么多我们应该怎么通过使用缓存来提高站点的性能呢 首先对于私有缓存开发者一般是不需要关注的浏览器会自动缓存请求成功的 GET 数据用来支持后退等功能。我们一般关注的是共有缓存也就是在代理服务器上缓存数据客户端请求到代理服务器上后就可以直接返回了下面以 Nginx 为例简单说明如何使用缓存。 http {# 缓存配置proxy_cache_path /usr/share/nginx/cache levels1:2 keys_zoneserver_cache:10m max_size5g inactive60m use_temp_pathoff;# 博客后端反代server {listen 8888 ssl http2;access_log /var/log/nginx/admin/access_fd.log smail;error_log /var/log/nginx/admin/error_fd.log;location ~ /api/ {proxy_cache server_cache;proxy_cache_valid 200 304 302 1h;proxy_cache_methods GET HEAD POST;add_header X-Proxy-Cache $upstream_cache_status;proxy_pass http://39.106.168.39:8888;}error_page 500 502 503 504 /50x.html;location /50x.html {root html;}}} }如上proxy_cache_path 用来配置缓存数据保存的路径里面的主要字段含义如下 levels: 在单个目录中包含大量文件会降低文件访问速度因此我们建议对大多数部署使用两级目录层次结构。如果未包含 levels Nginx会将所有文件放在同一目录中。keys_zone: 设置共享内存区域用于存储缓存键和元数据,后面的参数表示该区域的大小一般来说1 MB区域可以存储大约8,000个 key 数据。max-size: 缓存能占的最大内存。inactive指定项目在未被访问的情况下可以保留在缓存中的时间长度。在此示例中缓存管理器进程会自动从缓存中删除1分钟未请求的文件无论其是否已过期。默认值为10分钟10m。非活动内容与过期内容不同。Nginx 不会自动删除缓存header定义为已过期内容例如 Cache-Control:max-age120。过期陈旧内容仅在指定时间内未被访问时被删除。访问过期内容时Nginx 会从原始服务器刷新它并重置inactive计时器。 其次我们在 Location 块中配置了几个值 proxy_cache定义用于缓存的共享内存区域。proxy_cache_valid: 指定哪些状态的响应可以被缓存。proxy_cache_methods: 哪些方法的请求可以被缓存。 除此之外我们添加了一个响应头部字段 X-Proxy-Cache 用来查看缓存是否生效。 这里只是简单对数据进行了缓存服务端没有提供缓存验证的功能所以可能出现服务端数据已经改变但缓存没更新的情况。 HTTPS 细节 HTTPS 的原理 密码学基础 对称加密和非对称加密 对称加密: 加密和解密时使用的密钥是一样的比如 DES, 优点是速度快缺点是在协商密钥时可能会泄露密钥 非对称加密有两个密钥公钥和私钥使用公钥加密私钥解密公钥是公开的比如 RSA。 非对称加密有一个形象的比喻 A有一份机密文件想要发给B发之前先向B要一个打开的保险柜把文件装进保险柜锁住后再发给B整个过程中保险柜密码只有B知道这里的保险柜相当于公钥保险柜密码相当于私钥。 CA机构和证书 公钥是公开的那怎么证明这个公钥是属于你的呢接上面的比喻如果有一个中间人 C在 B 向 A 发保险柜的时候将 B 的保险柜换成自己的发给 A这样 C 就可以窃取到文件A 如果想要验证这个保险柜是不是 B 的就需要一个 A、B 都信任的第三方机构B 在发给 A 之前请求第三方机构在保险箱上盖一个戳A 收到后再请求第三方机构检查戳是不是真的就可以了这里的第三方机构就是 CA 机构这个戳就是证书具体来说 每个CA机构都会有自己的一组密钥对CA 的公钥是通信双方都信任的现在 B 有一个公钥他要证明这个公钥是他的就需要向 CA 机构请求一份该公钥的证书请求时B 需要向 CA 机构提供自己的信息以及要认证的公钥这些信息会组成CSR文件CA 机构收到请求后会检查 CSR 的真实性检查无误后CA 会将 CSR 的内容哈希后用自己的私钥签名然后将 CSR 中的信息和签名组合成证书发给 B。 所以一份证书中包含的典型内容包括 明文的证书持有者信息明文的公钥CA 的签名证书用途使用的算法证书过期时间颁发者信息CRL分发点等 B 有了 CA 机构的证书在向 A 发送公钥时就只需要发送证书了A 收到证书用 CA 机构的公钥解密签名然后对证书中的明文数据以同样的算法做哈希只需要对比两个哈希值就可以判断证书有没有被篡改了如果证书没被篡改则可以放心使用证书中的公钥与 B 通信了。 HTTPS 通信流程 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8HD5SxsD-1613829654732)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210122163508612.png)] 看上面的截图前三行 [SYN], [SYN, ACK], [ACK] 是典型的 TCP 三次握手那么在三次握手后客户端向服务端以 TLSV1.2 协议向服务端发送了一个 client Hello 包通过 Client Hello, 客户端会生成一个随机数并告诉服务端自己支持的加密哈希等算法我们可以在这个报文里看到这些内容: 其中Random 就是客户端选取的随机数Cipher Suites 中就是客户端支持的算法。 接下来就是 Server Hello, 在这一步服务端同样会生成一个随机数并且会从客户端支持的算法中选取一种通过 Server Hello 的方式告诉客户端 可以看到 Server Hello 和 Client Hello 的报文内容区别不大只是 Client Hello 中的 Cipher Suite 有许多项而 Server Hello 的只有一项因为服务端会选择安全性最高的加密方式需要注意的是这里选择的是一组算法以这里选择的 0xc02f 为例,它的名字叫 TLS_ECDHE_RSA_WITH_AES_128_GCM_ SHA256 (0xc02f) 其中包括 密钥交换算法ECDHE身份验证算法RSA对称加密算法AES_128_GCM摘要算法SHA256 在这之后服务端在一个 TLS 包里进行了三个负载 Certificate发送证书Server Key Exchange包含密钥交换算法 DHE/ECDHE 所需要的额外参数。Server Hello Done表明服务端相关信息发送结束这之后服务端会等待客户端响应。 到这一步客户端已经拿到了服务器的证书会检查证书是否有效如果证书失效客户端浏览器会阻止后续操作反之客户端会继续与服务端协商对称加密密钥 客户端向服务端发送一个响应id 67包含三个负载 Client Key Exchange类似 Server Key Exchange客户端生成一个新的随机数Premaster secret并使用数字证书中的公钥加密后发给服务端。Change cipher Spec: 已被废弃不携带数据Encrypted handshake message这个步骤客户端和服务器在握手完后都会进行以告诉对方自己在整个握手过程中收到了什么数据发送了什么数据保证中间没人篡改报文。 到现在为止我们总结一下客户端和服务器做了什么 客户端生成了一个随机数 Client Random 发给了服务端服务端也生成了一个随机数 Server Random 发给了客户端同时双方还协商了以后要用到的哈希加密算法。服务端把自己的证书发给了客户端。客户端又生成了一个新随机数并用服务端证书中的公钥进行加密后发给了服务端。客户端和服务端通过互发 Encrypted handshake message 确保了数据没被 中间人篡改。 现在根据三个随机数客户端和服务器就会根据约定好的对称加密算法生成最终的对称加密密钥后续的数据传输就会使用该密钥加密。 总结 HTTPS 建立连接的过程总结如下 TCP 三次握手客户端向服务器发送 Client Hello 包包含 TLS 版本客户端生成的随机数 Client Random, 客户端支持的算法等信息服务器向客户端发送 Server Hello 包包含服务端生成的随机数 Server Random服务端选择的算法等信息。服务端向客户端发送证书。客户端检查证书有效后生成一个新的随机数 Premaster secret 并用证书中的公钥加密发给服务端。服务端使用自己的私钥解密 Premaster secret。客户端和服务端分别使用三个随机数依照约定的算法生成对话密钥 session key。客户端和服务端使用 session key 加密后续的会话。 使用 HTTPS nginx 配置示例 server {listen 443 ssl http2;server_name *.junebao.top;# 证书ssl_certificate 1_www.junebao.top_bundle.crt;# 私钥ssl_certificate_key 2_www.junebao.top.key;ssl_session_timeout 5m;ssl_protocols TLSv1 TLSv1.1 TLSv1.2;ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;ssl_prefer_server_ciphers on;error_page 500 502 503 504 /50x.html;location /50x.html {root html;}}HTTP/2 细节 实现 2015 年HTTP/2 发布。HTTP/2 是现行 HTTP 协议HTTP/1.x的替代但它不是重写HTTP 方法/状态码/语义都与 HTTP/1.x 一样。HTTP/2 基于 SPDY3专注于性能最大的一个目标是在用户和网站间只用一个连接connection。 那么SPDY3是什么呢 SPDY是谷歌自行研发的 SPDY 协议主要解决 HTTP/1.1 效率不高的问题。谷歌推出 SPDY才算是正式改造 HTTP 协议本身。降低延迟压缩 header 等等SPDY 的实践证明了这些优化的效果也最终带来 HTTP/2 的诞生。 HTTP/2 由两个规范Specification组成 Hypertext Transfer Protocol version 2 - RFC7540HPACK - Header Compression for HTTP/2 - RFC7541 那么HTTP2在HTTP1.1的基础上做了哪些改进 二进制传输请求和响应复用Header压缩Server Push服务端推送 二进制传输 HTTP/2 采用二进制格式传输数据而非 HTTP 1.x 的文本格式二进制协议解析起来更高效。 HTTP / 1 的请求和响应报文都是由起始行首部和实体正文可选组成各部分之间以文本换行符分隔。HTTP/2 将请求和响应数据分割为更小的帧并且它们采用二进制编码。 新的二进制分帧机制改变了客户端与服务器之间交换数据的方式。 为了说明这个过程我们需要了解 HTTP/2 的三个概念 数据流已建立的连接内的双向字节流可以承载一条或多条消息。消息与逻辑请求或响应消息对应的完整的一系列帧。帧HTTP/2 通信的最小单位每个帧都包含帧头至少也会标识出当前帧所属的数据流。 这些概念的关系总结如下 所有通信都在一个 TCP 连接上完成此连接可以承载任意数量的双向数据流。每个数据流都有一个唯一的标识符和可选的优先级信息用于承载双向消息。每条消息都是一条逻辑 HTTP 消息例如请求或响应包含一个或多个帧。帧是最小的通信单位承载着特定类型的数据例如 HTTP 标头、消息负载等等。 来自不同数据流的帧可以交错发送然后再根据每个帧头的数据流标识符重新组装。 请求和响应复用 在 HTTP/1.x 中如果客户端要想发起多个并行请求以提升性能则必须使用多个 TCP 连接这是 HTTP/1.x 交付模型的直接结果该模型可以保证每个连接每次只交付一个响应响应排队。 更糟糕的是这种模型也会导致队首阻塞从而造成底层 TCP 连接的效率低下。 HTTP/2 中新的二进制分帧层突破了这些限制实现了完整的请求和响应复用客户端和服务器可以将 HTTP 消息分解为互不依赖的帧然后交错发送最后再在另一端把它们重新组装起来。 在 HTTP/2 中有了二进制分帧之后HTTP /2 不再依赖 TCP 链接去实现多流并行了在 HTTP/2 中 同域名下所有通信都在单个连接上完成。单个连接可以承载任意数量的双向数据流。数据流以消息的形式发送而消息又由一个或多个帧组成多个帧之间可以乱序发送因为根据帧首部的流标识可以重新组装。 这一特性使性能有了极大提升 同个域名只需要占用一个 TCP 连接使用一个连接并行发送多个请求和响应,消除了因多个 TCP 连接而带来的延时和内存消耗。并行交错地发送多个请求请求之间互不影响。并行交错地发送多个响应响应之间互不干扰。在 HTTP/2 中每个请求都可以带一个 31bit 的优先值0 表示最高优先级 数值越大优先级越低。有了这个优先值客户端和服务器就可以在处理不同的流时采取不同的策略以最优的方式发送流、消息和帧。 Header压缩 在 HTTP/1 中我们使用文本的形式传输 header在 header 携带 cookie 的情况下可能每次都需要重复传输几百到几千的字节。为了减少这块的资源消耗并提升性能HTTP/2 使用 HPACK 压缩格式压缩请求和响应标头元数据这种格式采用两种强大的技术 这种格式支持通过静态霍夫曼代码对传输的标头字段进行编码从而减小了各个传输的大小。这种格式要求客户端和服务器同时维护和更新一个包含之前见过的标头字段的索引列表换句话说它可以建立一个共享的压缩上下文此列表随后会用作参考对之前传输的值进行有效编码。 利用霍夫曼编码可以在传输时对各个值进行压缩而利用之前传输值的索引列表我们可以通过传输索引值的方式对重复值进行编码索引值可用于有效查询和重构完整的标头键值对。 作为一种进一步优化方式HPACK 压缩上下文包含一个静态表和一个动态表静态表在规范中定义并提供了一个包含所有连接都可能使用的常用 HTTP 标头字段例如有效标头名称的列表动态表最初为空将根据在特定连接内交换的值进行更新。 因此为之前未见过的值采用静态 Huffman 编码并替换每一侧静态表或动态表中已存在值的索引可以减小每个请求的大小。 注在 HTTP/2 中请求和响应标头字段的定义保持不变仅有一些微小的差异所有标头字段名称均为小写请求行现在拆分成各个 :method、:scheme、:authority 和 :path 伪标头字段。 如需了解有关 HPACK 压缩算法的完整详情请参阅 IETF HPACK - HTTP/2 的标头压缩。 Server Push HTTP/2 新增的另一个强大的新功能是服务器可以对一个客户端请求发送多个响应。 换句话说除了对最初请求的响应外服务器还可以向客户端推送额外资源如下图所示而无需客户端明确地请求。 为什么在浏览器中需要一种此类机制呢一个典型的网络应用包含多种资源客户端需要检查服务器提供的文档才能逐个找到它们。 那为什么不让服务器提前推送这些资源从而减少额外的延迟时间呢 服务器已经知道客户端下一步要请求什么资源这时候服务器推送即可派上用场。 事实上如果您在网页中内联过 CSS、JavaScript或者通过数据 URI 内联过其他资产请参阅资源内联那么您就已经亲身体验过服务器推送了。 对于将资源手动内联到文档中的过程我们实际上是在将资源推送给客户端而不是等待客户端请求。 使用 HTTP/2我们不仅可以实现相同结果还会获得其他性能优势。 推送资源可以进行以下处理 由客户端缓存在不同页面之间重用与其他资源一起复用由服务器设定优先级被客户端拒绝 服务端推送如何实现 所有服务器推送数据流都由 PUSH_PROMISE 帧发起表明了服务器向客户端推送所述资源的意图并且需要先于请求推送资源的响应数据传输。 这种传输顺序非常重要客户端需要了解服务器打算推送哪些资源以免为这些资源创建重复请求。 满足此要求的最简单策略是先于父响应即DATA 帧发送所有 PUSH_PROMISE 帧其中包含所承诺资源的 HTTP 标头。 在客户端接收到 PUSH_PROMISE 帧后它可以根据自身情况选择拒绝数据流通过 RST_STREAM 帧。 例如如果资源已经位于缓存中便可能会发生这种情况。 这是一个相对于 HTTP/1.x 的重要提升。 相比之下使用资源内联一种受欢迎的 HTTP/1.x“优化”等同于“强制推送”客户端无法选择拒绝、取消或单独处理内联的资源。 使用 HTTP/2客户端仍然完全掌控服务器推送的使用方式。 客户端可以限制并行推送的数据流数量调整初始的流控制窗口以控制在数据流首次打开时推送的数据量或完全停用服务器推送。 这些优先级在 HTTP/2 连接开始时通过 SETTINGS 帧传输可能随时更新。 过渡到 HTTP/2 上面说了这么多我们要如何启用HTTP2呢 如果你使用的是 nginx那么你只需要加一个 http2 即可 server {listen 8888 ssl http2;server_name *.junebao.top;# ... }如果你使用 Golang 的 Gin 框架他默认支持 HTTP/2你可以使用 RunTLS() 使用 HTTP/2,如下 package mainimport (github.com/gin-gonic/gin )func main() {engine : gin.Default()engine.GET(./, func(context *gin.Context) {context.JSON(200, map[string]string{msg: ok})})// 服务端推送engine.Static(/static, ./static)engine.GET(/push, func(context *gin.Context) {pusher : context.Writer.Pusher()if pusher ! nil {err : pusher.Push(/static/test.js, nil)if err ! nil {log.Println(push fail, err)}}context.JSON(200, map[string]string{msg: ok})})engine.RunTLS(:8888, ./root_cer.cer, ./root_private_key.pem) }如果你使用的是 spring boot 内置的 Tomcat 服务器那么只需要在配置文件中添加配置 server:http2:enabled: on只有 Tomcat 9 版本之后版本才支持 HTTP/2 协议。在 conf/server.xml 中增加内容 Connector port8443 protocolorg.apache.coyote.http11.Http11AprProtocol maxThreads150 SSLEnabledtrue UpgradeProtocol classNameorg.apache.coyote.http2.Http2Protocol/ SSLHostConfig honorCipherOrderfalse Certificate certificateKeyFileconf/ca.key certificateFileconf/ca.crt/ /SSLHostConfig /ConnectorHTTP/3 细节 为什么要出现HTTP3 虽然 HTTP/2 解决了很多之前旧版本的问题但是它还是存在一个巨大的问题主要是底层支撑的 TCP 协议造成的。 上文提到 HTTP/2 使用了多路复用一般来说同一域名下只需要使用一个 TCP 连接。但当这个连接中出现了丢包的情况那就会导致 HTTP/2 的表现情况反倒不如 HTTP/1 了。 因为在出现丢包的情况下整个 TCP 都要开始等待重传也就导致了后面的所有数据都被阻塞了。但是对于 HTTP/1.1 来说可以开启多个 TCP 连接出现这种情况反到只会影响其中一个连接剩余的 TCP 连接还可以正常传输数据。 那么可能就会有人考虑到去修改 TCP 协议其实这已经是一件不可能完成的任务了。因为 TCP 存在的时间实在太长已经充斥在各种设备中并且这个协议是由操作系统实现的更新起来不大现实。 基于这个原因Google 就更起炉灶搞了一个基于 UDP 协议的 QUIC 协议并且使用在了 HTTP/3 上HTTP/3 之前名为 HTTP-over-QUIC从这个名字中我们也可以发现HTTP/3 最大的改造就是使用了 QUIC快速 UDP Internet 连接。 QUIC QUICQuick UDP Internet Connection是谷歌制定的一种基于UDP的低时延的互联网传输层协议。在2016年11月国际互联网工程任务组(IETF)召开了第一次QUIC工作组会议受到了业界的广泛关注。这也意味着QUIC开始了它的标准化过程成为新一代传输层协议 。 优势 高效地建立连接: 将 TLS 协商密钥和协议作为打开连接握手地一部分加上对 client Hello 地缓存在大部分情况下QUIC 建立连接只需要 0RTT而普通的 HTTPS 则至少需要 2RTT改进地拥塞控制方案TCP 拥塞控制包括慢启动拥塞避免快速重传快速恢复QUIC 在 UDP 基础上实现了相关算法并做了改进使之具有可插拔高效地特点。基于 stream 和 connecton 级别的流量控制。没有 TCP 队头阻塞地多路复用HTTP/2 通过二进制分帧层避免了 HTTP 队头阻塞但由于依然使用 TCP 协议就避免不了 TCP 队头阻塞QUIC 基于 UDP多个 stream 之间没有依赖。这样假如 stream2 丢了一个 udp packet也只会影响 stream2 的处理。不会影响 stream2 之前及之后的 stream 的处理这也就在很大程度上缓解甚至消除了队头阻塞的影响。加密认证地报文:TCP 协议头部没有经过任何加密和认证所以在传输过程中很容易被中间网络设备篡改注入和窃听。比如修改序列号、滑动窗口。这些行为有可能是出于性能优化也有可能是主动攻击。但是 QUIC 的 packet 可以说是武装到了牙齿。除了个别报文比如 PUBLIC_RESET 和 CHLO所有报文头部都是经过认证的报文 Body 都是经过加密的.连接迁移:一条 TCP 连接是由四元组标识的源 IP源端口目的 IP目的端口。什么叫连接迁移呢就是当其中任何一个元素发生变化时这条连接依然维持着能够保持业务逻辑不中断。当然这里面主要关注的是客户端的变化因为客户端不可控并且网络环境经常发生变化而服务端的 IP 和端口一般都是固定的,而 QUIC 连接不再以 IP 及端口四元组标识而是以一个 64 位的随机数作为 ID 来标识这样就算 IP 或者端口发生变化时只要 ID 不变这条连接依然维持着上层业务逻辑感知不到变化不会中断也就不需要重连。由于这个 ID 是客户端随机产生的并且长度有 64 位所以冲突概率非常低。向前纠错: 每个数据包除了它本身的内容之外还包括了部分其他数据包的数据因此少量的丢包可以通过其他包的冗余数据直接组装而无需重传。向前纠错牺牲了每个数据包可以发送数据的上限但是减少了因为丢包导致的数据重传因为数据重传将会消耗更多的时间(包括确认数据包丢失、请求重传、等待新数据包等步骤的时间消耗);假如说这次我要发送三个包那么协议会算出这三个包的异或值并单独发出一个校验包也就是总共发出了四个包。当出现其中的非校验包丢包的情况时可以通过另外三个包计算出丢失的数据包的内容。当然这种技术只能使用在丢失一个包的情况下如果出现丢失多个包就不能使用纠错机制了只能使用重传的方式了。证书压缩等. 可见HTTP3在效率上和安全性上都有了很大程度上的修改但是由于目前这个标准还在论证中Nginx等也只是在测试版中加入了对HTTP3的支持等到技术真正的论证实现完成我们就可以使用上快速且安全的HTTP3协议了期待着这一天的到来。 参考 mozilla 开发文档 谷歌开发文档 HTTP2 简介 Nginx缓存最佳实践 让互联网更快新一代QUIC协议在腾讯的技术实践分享
http://www.pierceye.com/news/806997/

相关文章:

  • 素材下载网站电商自建站
  • 浙江省的网站建设公司有哪些代理注册公司一般多少钱
  • 如何在建设银行网站预约纪念币东莞网站建设服务有什
  • 有哪些可以做h5的网站代理网址上境外网
  • 做网站所需要的代码6红杏直播
  • 南通制作网站wordpress移动版设置
  • 哪个网站有免费ppt下载建筑类网站的推荐理由
  • 视觉差的网站公司外包
  • 基础做网站内蒙住房和城乡建设部网站
  • 发帖效果好的网站展馆展示设计公司排名
  • 童装网站建设文案什么网站做的号
  • 能打开的a站莆田网站建设建站系统
  • 上海市城乡建设管理局网站一个月做网站
  • 网站后台管理系统 aspwordpress拖拽上传
  • 华为手机官方网站登录爬虫做视频网站
  • 山东省工程建设信息官方网站河南网站seo推广
  • 低成本做网站 白之家重庆市建设执业资格注册管理中心网站
  • 电子商务网站建设需求在别的公司做的网站可以转走吗
  • 网站流量怎么做乡1万做网站需要几个人
  • 阿里云centos7做网站怀化网站seo
  • 我做的网站怎样被百度收录易语言 做网站mysql
  • 花店网站模板免费下载9个做简历的网站
  • 东港区网站制作seo推广模式是什么
  • 用织梦做网站能练技术吗广州专业网络推广公司
  • 下载ppt模板免费的网站在线做头像网站
  • 网络推广怎么免费做网站内部优化的方法
  • 沧州wap网站制作哈尔滨建设网证件查询
  • 一键查询注册过的网站快速排名教程
  • 响应式模板网站泰安招聘信息最新招聘2021
  • 信阳市住房和城乡建设厅网站wordpress加载速度