深入学习HTTP协议

深入学习HTTP协议

小结

  1. 域名使用字符串来代替 IP 地址,方便用户记忆,本质上一个名字空间系统;
  2. DNS 就像是我们现实世界里的电话本、查号台,统管着互联网世界里的所有网站,是一
    个“超级大管家”;
  3. DNS 是一个树状的分布式查询系统,但为了提高查询效率,外围有多级的缓存;
  4. 使用 DNS 可以实现基于域名的负载均衡,既可以在内网,也可以在外网。

自己动手,搭建HTTP实验环境

  1. 现实的网络环境太复杂,有很多干扰因素,搭建“最小化”的环境可以快速抓住重点,
    掌握 HTTP 的本质;
  2. 我们选择 Wireshark 作为抓包工具,捕获在 TCP/IP 协议栈中传输的所有流量;
  3. 我们选择 Chrome 或 Firefox 浏览器作为 HTTP 协议中的 user agent;
  4. 我们选择 OpenResty 作为 Web 服务器,它是一个 Nginx 的“强化包”,功能非常丰
    富;
  5. Telnet 是一个命令行工具,可用来登录主机模拟浏览器操作;
  6. 在 GitHub 上可以下载到本专栏的专用项目源码,只要把 OpenResty 解压到里面即可完
    成实验环境的搭建。

键入网址再按下回车,后面究竟发生了什么/h2>

深入学习HTTP协议

header

  1. HTTP的header一般都很大,HTTP 报文经常是只有 header 而没 body
  2. 不过这个“大头”也不能太大,虽然 HTTP 协议对 header的大小没有做限制

请求行

描述了客户端想要如何操作服务器端的资源。GET / HTTP/1.1,由请求方法,请求目标,版本号组成

状态行

服务器响应的状态。HTTP/1.1 200 OK,由版本号,状态码,和原因组成

头部字段

深入学习HTTP协议

唯一的区别是起始行

GET /09-1 HTTP/1.1
Host: www.chrono.com

GET /09-1 HTTP/1.1
Host : www.chrono.com

Host后面一定要接着:,不然就会报400 Bad Request

小结

  1. HTTP 报文结构就像是“大头儿子”,由“起始行 + 头部 + 空行 + 实体”组成,简单地说就是“header+body”;
  2. HTTP 报文可以没有 body,但必须要有 header,而且header 后也必须要有空行,形象地说就是“大头”必须要带着“脖子”;
  3. 请求头由“请求行 + 头部字段”构成,响应头由“状态行 + 头部字段”构成;
  4. 请求行有三部分:请求方法,请求目标和版本号;
  5. 状态行也有三部分:版本号,状态码和原因字符串;
  6. 头部字段是 key-value 的形式,用“:”分隔,不区分大小写,顺序任意,除了规定的标准头,也可以任意添加自
    定义字段,实现功能扩展;
  7. HTTP/1.1 里唯一要求必须提供的头字段是 Host,它必须出现在请求头里,标记虚拟主机名。

应该如何理解请求方法

目前 HTTP/1.1 规定了八种方法,单词都必须是大写的形式:

  1. GET:获取资源,可以理解为读取或者下载数据;
  2. HEAD:获取资源的元信息;
  3. POST:向资源提交数据,相当于写入或上传数据;
  4. PUT:类似 POST;
  5. DELETE:删除资源;
  6. CONNECT:建立特殊的连接隧道;
  7. OPTIONS:列出可对资源实行的方法;
  8. TRACE:追踪请求 – 响应的传输路径。

请求其实就相当于指示,由客户端发出,但是决定权在服务端那里

GET和HEAD

HEAD与GET类试,但是HEAD只获取资源的元信息,HEAD被看成是GET的简化版。例如:比如,想要检查一个文件是否存在,只要发个 HEAD 请求就可以了,没有必要用 GET 把整个文件都取下来。再比如,要检查文件是否有最新版本,同样也应该用 HEAD,服务器会在响应头里把文件的修改时间传回来。

POST/PUT

PUT 的作用与 POST 类似,也可以向服务器提交数据,但与 POST 存在微妙的不同,通常 POST 表示的是“新建”“create”的含义,而 PUT 则是“修改”“update”的含义

安全与幂等

在 HTTP 协议里,所谓的“安全”是指请求方法不会“破”服务器上的资源即不会对服务器上的资源造成实质的
修改。例如,GET和HEAD是获取,不会造成损害,而POST和PUT就会修改资源。

所谓的“幂等”实际上是一个数学用语,被借用到了 HTTP协议里,意思是多次执行相同的操作,结果也都是相同的,即多次“幂”后结果“相等”。

POST 是“新增或提交数据”,多次提交数据会创建多个资源,所以不是幂等的

PUT是“替换或更新数据”,多次更新一个资源,资源还是会第一次更新的状态,所以是幂等的

POST 理解成 INSERT,把 PUT 理解成 UPDATE

小结

  1. 请求方法是客户端发出的、要求服务器执行的、对资源的一种操作;
  2. 请求方法是对服务器的“指示”,真正应如何处理由服务器来决定;
  3. 最常用的请求方法是 GET 和 POST,分别是获取数据和发送数据;
  4. HEAD 方法是轻量级的 GET,用来获取资源的元信息;
  5. PUT 基本上是 POST 的同义词,多用于更新数据;
  6. “安全”与“幂等”是描述请求方法的两个重要属性,具有理论指导意义,可以帮助我们设计系统。

你能写出正确的网址吗/h2>

URI 不完全等同于网址,它包含有 URLURN两个部分.网址实际上是 URL

URI 的格式

URI 本质上是一个字符串,这个字符串的作用是唯一地标记资源的位置或者名字

深入学习HTTP协议

主机名之前的**身份信息“user:passwd@”**因为它把敏感信息以明文形式暴露出来,存在严重的安全隐患(一斤不使用了)

第二个多出的部分是查询参数后的片段标识符“#fragment”。片段标识符仅能由浏览器这样的客户端使用,服务器是看
不到的。所以也不会存在

URI 的编码

URI 转义的规则有点“简单粗暴”,直接把非 ASCII 码或特殊字符转换成十六进制字节值,然后前面再加上一个“%”

小结

  1. URI 是用来唯一标记服务器上资源的一个字符串,通常也称为 URL;

  2. URI 通常由 scheme、host:port、path 和 query 四个部分组成,有的可以省略;

  3. scheme 叫**“方案名”或者“协议名”**,表示资源应该使用哪种协议来访问;

  4. “host:port”表示资源所在的主机名和端口号

  5. path 标记资源所在的位置;

  6. query 表示对资源附加的额外要求

  7. 在 URI 里对“@&/”等特殊字符和汉字必须要做编码,否则服务器收到 HTTP 报文后会无法正确处理。

  8. HTTP 协议允许在在请求行里使用完整的 URI,但为什么浏览器没有这么做呢/p>

    没有必要,因为在请求头的字段中都有,没必要重复

  9. URI 的查询参数和头字段很相似,都是 key-value 形式,都可以任意自定义,那么它们在使用时该如何区别呢/p>

    query参数针对的是资源(uri),而字段针对的是本次请求,也就是报文。
    一个是长期、稳定的,一个是短期、临时的

响应状态码该怎么用/h2>

深入学习HTTP协议

HTTP有哪些优点有哪些缺点/h2>
  1. 简单、灵活、易于扩展(最重要也是最突出),容易上手,heder字段,状态码,还有body数据等都可以自己修改和扩展
  2. 应用广泛、环境成熟从台式机上的浏览器到手机上的各种 APP,从看新闻、泡论坛到购物、理财、“吃鸡”,你很难找到一个没有使用 HTTP 的地方。
  3. 无状态
    1. 优点:所以就不需要额外的资源来记录状态信息,不仅实现上会简单一些,而且还能减轻服务器的负担,能够把更多的 CPU 和内存用来对外提供服务。很容易地组成集群(负载均衡),一位内服务器都是相同的(无状态)。不会因为状态不一致导致处理出错。
    2. 缺点无法支持需要连续多个步骤的“事务”操作,例如电商项目中的,添加购物车其实是要验证登陆的(要知道用户的身份),但是,如果每次都询问一遍身份信息就太麻烦了,还要增加了数据的传输量从而有了cookie技术
  4. 明文,协议里的报文(准确地说是 header 部分)不使用二进制数据,而是用简单可阅读的文本形式
    1. 优点:为我们的开发调试工作带来极大的便利
    2. 缺点毫无隐私可言
  5. 不安全,与“明文”缺点相关但不完全等同的另一个缺点是“不安全”。HTTP 协议也不支持“完整性校验”,数据在传输过程中容易被窜改而无法验证真伪。为了解决 HTTP 不安全的缺点,所以就出现了 HTTPS,这个我们以后再说。
  6. 性能不算差,不够好,当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一并被阻塞,会导致客户端迟迟收不到数据

小结

  1. HTTP 最大的优点是简单、灵活和易于扩展
  2. HTTP 拥有成熟的软硬件环境应用的非常广泛,是互联网的基础设施;
  3. HTTP 是无状态的,可以轻松实现集群化,扩展性能,但有时也需要用 Cookie 技术来实现“有状态”;
  4. HTTP 是明文传输,数据完全肉眼可见,能够方便地研究分析,但也容易被窃听;
  5. HTTP 是不安全的,无法验证通信双方的身份,也不能判断报文是否被窜改;
  6. HTTP 的性能不算差,但不完全适应现在的互联网,还有很大的提升空间

海纳百川:HTTP的实体数据

从 HTTP 的 body 谈起。

数据类型与编码

MIME 把数据分成了八大类(MIME 是一个很大的标准规范,但HTTP知识取了其中的一部分)

  1. text,即文本格式的可读数据
  2. image,图像文件
  3. audio/video,音频和视频数据
  4. application,数据格式不固定,可能是文本也可能是二进制必须由上层应用程序来解释。常见的有
    application/json,application/javascript、application/pdf 等

因为 HTTP 在传输时为了节约带宽,有时候还会压缩数据,为了不要让浏览器继续“”,还需要有一个“Encoding type”,告诉数据是用的什么编码格式,这样对方才能正确解压缩,还原出原始的数据

  1. gzip,最流行的格式,nginx也一般用这个
  2. deflate,流行程度仅次于gzip
  3. br,一种专门为 HTTP 优化的新压缩算法

数据类型使用的头字段

深入学习HTTP协议
  1. 数据类型表示实体数据的内容是什么,使用的是 MIMEtype可以类比成你快递的物品),相关的头字段是 Accept(告诉服务器,客户端支持什么类型,以防服务器发过来的数据不认识,凡是有返回就可以带上) 和 Content-Type(请求和响应里都可以用,作用是指明body数据的类型,凡是有body数据都要带上);
  2. 数据编码表示实体数据的压缩方式,相关的头字段是Accept-EncodingContent-Encoding;(可以类比成物品的包装方式)
  3. 语言类型表示实体数据的自然语言,相关的头字段是Accept-Language 和 Content-Language
  4. 字符集表示实体数据的编码方式,相关的头字段是Accept-Charset 和 Content-Type
  5. 客户端需要在请求头里使用 Accept 等头字段与服务器进行“内容协商”,要求服务器返回最合适的数据;
  6. Accept 等头字段可以用“,”顺序列出多个可能的选项还可以用“;q=”参数来精确指定权重

把大象装进冰箱:HTTP传输大文件的方法

数据压缩

对处理视频,音频这些媒体数据的效果不佳。但是处理文本还是不错的。在Nginx 里就会使用“gzip on”指令,启用对“text/html”的压缩。

分块传输

‘这种“化整为零”的思路在 HTTP 协议里就是“chunked分块传输编码,在响应报文里用头字段“Transfer-Encoding: chunked”来表示,意思是报文里的 body 部分不是一次性发过来的,而是分成了许多的块(chunk)逐个发送。

分块传输也可以用于“流式数据”(就是stream,它像从源头持续不断地,慢慢地”流“过来的,而不是一次性,一整块发过来的),对于未知长度的数据,还是挺好用的“Transfer-Encoding: chunked”和“Content-
Length”这两个字段是互斥的。这里补充一下:举个例子,从GitHub上下载源码包,GitHub要实时压缩实时发送,而不是一下子压缩好再发送,这样body的长度一开始就是未知的。所以就要用分块编码,压缩一部分,就发一部分,这部分的长度是已知的,但总长度只有压缩完才能知道chunked编码用在“流式”收发数据的时候,通常数据是即时生成的,也就是动态数据

深入学习HTTP协议

深入学习HTTP协议

小结

  1. 压缩 HTML 等文本文件是传输大文件最基本的方法;
  2. 分块传输可以流式收发数据,节约内存和带宽,使用响应头字段“Transfer-Encoding: chunked”来表示,分块的格式是 16 进制长度头 + 数据块;
  3. 范围请求可以只获取部分数据,即“分块请求”,实现视频拖拽或者断点续传,使用请求头字段“Range”和响应头字段“Content-Range”,响应状态码必须是 206;这个“Content-Range”针对的是原文的数据,与压缩后的数据无关,因为我们在看视频的时候,拖拽进度条,拖拽的是原视频的长度,而不是压缩后的长度。
  4. 也可以一次请求多个范围,这时候响应报文的数据类型是“multipart/byteranges”,body 里的多个部分会用boundary 字符串分隔。

排队也要讲效率:HTTP的连接管理

短连接

因为客户端与服务器的整个连接过程很短暂不会与服务器保持长时间的连接状态

长连接

用的就是**“成本均摊”的思路,既然 TCP 的连接和关闭非常耗时间,那么就把这个时间成本由原来的一个“请求 – 应答”均摊到多个“请求 – 应答”上**。

连接相关的头字段

由于长连接对性能的改善效果非常显著,所以在 HTTP/1.1中的连接都会默认启用长连接“Connection: keepalive”
字段,服务器端通常不会主动关闭连接,但也可以使用一些策略。例如使用nginx的keepalive_timeout

队头阻塞

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

性能优化

要解决队头阻塞,就要进行并发连接,缺陷就是:很容易造成连接数过多,而从被服务器认为是恶意攻击,反而造成”拒绝服务“

域名分片,还是用数量来解决质量的思路。多开几个域名,而这些域名都指向同一台服务器。

小结

  1. 早期的 HTTP 协议使用短连接,收到响应后就立即关闭连接,效率很低

  2. HTTP/1.1 默认启用长连接,在一个连接上收发多个请求响应,提高了传输效率;

  3. 服务器会发送**“Connection: keep-alive”字段表示启用了长连接**;

  4. 报文头里如果有**“Connection: close”就意味着长连接即将关闭**;

  5. 过多的长连接会占用服务器资源,所以服务器会用一些策略有选择地关闭长连接;

  6. **“队头阻塞”问题会导致性能下降,可以用“并发连接”和“域名分片”**技术缓解。

四通八达:HTTP的重定向和跳转

跳转动作是由浏览器的使用者主动发起的,可以称为“主动跳转

跳转是由服务器来发起的,称为“被动跳转

以上方法统一叫“重定向”(Redirection)

重定向的过程

Location”字段属于响应字段,必须出现在响应报文里。它标记了服务器要求重定向的 URI

注意,在重定向时如果只是在站内跳转,你可以放心地使用相对 URI。但如果要跳转到站外,就必须用绝对 URI

重定向状态码

  1. 301俗称**“永久重定向”**意思是原 URI 已经“永久”性地不存在了,今后的所有请求都必须改用新的 URI
  2. 302俗称“临时重定向
  3. 303 See Other,要求重定向后的请求改为GET 方法
  4. 307 Temporary Redirect:,重定向后请求里的方法和实体不允许变动
  5. 308 Permanent Redirect:,不允许重定向后的请求变动,但它是 301“永久重定向”的含义

重定向的应用场景

一个最常见的原因就是“资源不可用”,需要用另一个新的URI 来代替。另一个原因就是“避免重复

301:原来的 URI 已经不能用了(比如启用了新域名、服务器切换到了新机房、网站目录层次重构),必须用 301“永久重定向”

302:原来的 URI 在将来的某个时间点还会恢复正常,常见的应用场景就是系统维护。另一种用法就是“服务降级”,比如在双十一促销的时候,把订单查询、领积分等不重要的功能入口暂时关闭,保证核心服务能够正常运行

重定向的相关问题

第一个问题是“性能损耗”,重定向应当适度使用,决不能滥用。

第二个问题是“循环跳转”,可能会出现“A=>B=>C=>A”的无限循环

小结

  1. 重定向服务器发起的跳转要求客户端改用新的 URI重新发送请求,通常会自动进行,用户是无感知的;
  2. 301/302 是最常用的重定向状态码,分别是“永久重定向”和“临时重定向”;
  3. 响应头字段 Location 指示了要跳转的 URI,可以用绝对或相对的形式;
  4. 重定向可以把一个 URI 指向另一个 URI,也可以把多个URI 指向同一个 URI,用途很多;
  5. 使用重定向时需要当心性能损耗,还要避免出现循环跳转。

一句话,转发是服务器行为,重定向是客户端行为。具体解释可以看这篇文章https://blog.csdn.net/meiyalei/article/details/2129120


让我知道你是谁:HTTP的Cookie机制

什么是 Cookie/h3>

相当于是服务器给每个客户端都贴上一张小纸条,上面写了一些只有服务器才能理解的数据,需要的时候客户端把这些信息发给服务器,服务器看到 Cookie,就能够认出对方是谁了。

Cookie 的工作过程

这要用到两个字段:响应头字段Set-Cookie和请求头字段Cookie

深入学习HTTP协议

Cookie 是由浏览器负责存储的,而不是操作系统。所以,它是“浏览器绑定”的,只能在本浏览器内生效

Cookie 的属性

首先,我们应该设置 Cookie 的生存周期,以使用 ExpiresMax-Age 两个属性来设置。“Expires”俗称“过期时间”,用的是绝对时间点,可以理解为“截止日期”(deadline)。“Max-Age”用的是相对时间。Expires 和 Max-Age 可以同时出现,但浏览器会优先采用 Max-Age 计算失效期

其次,我们需要设置 Cookie 的作用域,让浏览器仅发送给特定的服务器和 URI,避免被其他网站盗用

“Domain”和“Path”指定了 Cookie 所属的域名和路径

最后要考虑的就是Cookie 的安全性了,尽量不要让服务器以外的人看到。

这些信息,在application面板都能看到

Cookie 的应用

  1. 身份识别
  2. 广告跟踪

小结

  1. Coo

    来源:Professor麦

    声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2020年4月9日
下一篇 2020年4月9日

相关推荐