![](https://i-blog.csdnimg.cn/blog_migrate/31e7f29659219c6e9e40d2e1a81acf31.gif)
我最近一直在面试,而且正如大多数开发人员所知道的那样,在面试过程中可能会问到的问题的广度和深度几乎是无法衡量的。 考虑到这一点,我一直在对招聘人员进行调查,以探讨我在技术回合中可能会遇到的问题。 有时,我很难维持所有可能会想到的问题类别,更不用说问题本身了。 我倾向于忘记压力下的事情, 像那样 |
在bash中用于进程/程序,而 >
通常用于文件 。 为了更好地保留信息并强迫自己写作,我决定开始发布我所刷过的内容的演练。 我倾向于至少需要3个资料来源才能获得关于主题的完整,正确且写得很好的解释。 我想为其他人巩固这一点。
这周,我讨论了HTTP请求生命周期 。 这是一个相当广泛的概述,它是针对简单的HTTP 1.1请求而不是持久性连接的,但是对于HTTP / 2和持久性连接请求,它可以充当良好的起点。 我不会过多介绍各种HTTP方法,因为这可能是一个单独的文章,并且因为它们与许多开发人员的工作流程非常接近,以至于读者可能已经在这里重述了基础知识。
注意:Medium不支持脚注,因此所有脚注都链接到原始dev.to
步骤1:本地处理
根据您想要获得的深度,在此步骤中可能会发生很多事情,具体取决于发出请求的应用程序。 我将继续理解此请求是由浏览器发出的,而不是cURL,类似于Postman的API客户端或其他一些应用程序。
- 您的浏览器提取“方案” /协议(我们已经建立了
(将是HTTP),主机( www.example.com)和可选端口号,资源路径以及以<protocol>://<host><:optional port>/<path/to/resource><?query>
形式指定的查询字符串<protocol>://<host><:optional port>/<path/to/resource><?query>
。 示例是|http|://|www.example.com||:5000||/mainpage||?query=param&query2=param2|
- 现在,浏览器具有请求的预期主机名,它需要解析IP地址¹ 。 然后,浏览器将浏览其自己的最近请求的URL缓存,操作系统的最近查询的缓存,路由器的缓存和DNS缓存。
![](https://i-blog.csdnimg.cn/blog_migrate/2754cb47acac8de5d01f32b05c18369a.gif)
步骤2:解析IP
像在本地进行的处理一样,从“ DNS服务器” ²解析IP是一个包括许多步骤的序列,并且在第一个请求未能返回地址时包括故障转移。
![](https://i-blog.csdnimg.cn/blog_migrate/edff95a2c4229534f455ed0f38774886.gif)
- 如果缓存查找失败(我们假设会失败),则您的浏览器会使用UDP触发DNS请求 ³ 。 DNS请求在DNS标头中包含为DNS服务器预先配置的IP和返回IP。 您要解析IP的主机名位于请求的“问题”部分。 UDP是一种轻量级的协议,但要权衡的是它在传递方面不提供任何保证,除了发送和接收响应外,没有其他确认。
- 您的请求现在将必须经过许多网络设备才能到达其目标DNS服务器。 每当数据包到达某台联网设备时,该设备就会使用路由表来确定它所连接的哪个其他设备最有可能位于到达目的地的最短路径上。 ⁴
- 您的请求到达配置的DNS服务器后,服务器将查找与请求的主机名关联的地址。 如果找到一个,它将发送响应。 另一方面,如果您定位的DNS服务器无法找到给定的主机名,则会将请求传递到配置为延迟到的另一个DNS服务器。 递归地进行此操作,直到找到该地址或命中“权威”名称服务器为止。 如果无法解析给定域的地址,则服务器响应失败,并且浏览器返回错误。
- 鉴于所有这些仍然是前提条件,因此我们将假定请求是成功的。 如果响应返回(请记住,使用UDP无法保证!),发出请求的客户端现在具有目标IP。 它还将收到一条信息作为答案的一部分,这将使其知道可以将返回的答案缓存多长时间。 这意味着后续请求将采用从步骤1.2到此处的快捷方式。
步骤3:建立TCP连接
现在,客户端有一个IP地址,它可以发送一个HTTP ⁵请求,对不对? 几乎,但是首先,因为请求是通过TCP发送的 ⁶是类似于UDP的传输层协议 ,客户端必须打开TCP连接。
- TCP和UDP之间的主要区别之一是TCP确保传递和有序的数据传输。 使用发送的每个字节的序列号 ,可以很简单地完成许多工作。 这使接收方可以将接收到的数据包重新排序为原始顺序,并允许发送方重新传输未得到接收方确认的任何数据包。
- 这些保证和更多保证可以在Wikipedia上找到,并且值得一读,但是最重要的是,TCP连接是使用所谓的三向握手打开的。 服务器必须已经在端口上“侦听”,执行被动打开 ,然后客户端可以发起主动打开 ,握手的工作方式如下:
- 客户机通过发送一个主动打开
SYN
⁷ “对照” ⁸分组到服务器。 为了安全起见,客户端故意将第一个数据包的序列号设置为随机值。 我们现在将这个数字称为x
。 - 服务器以
SYN-ACK
消息响应 ,该消息包含始终为x+1
的原始消息的确认号和响应本身的新序列号,即另一个随机数y
。 - 在第三步骤中,客户端发送一个
ACK
消息¹⁰回服务器具有顺序号等于x+1
,这应与SYN-ACK
消息的确认号,并确保我们的数据被可靠地传递。ACK
消息的确认号(因为它正在确认SYN-ACK
)被设置为比接收到的序列号多一,即y+1
。 - 现在,我们已经完成了三向握手,并且建立了连接,客户端和服务器都已收到对方的连接确认。 该连接还为每个通信方向(客户端->服务器,服务器->客户端)建立了随机的顺序序列11 ,允许沿着连接进行双向并发通信,这也称为全双工通信 。
步骤4:发送HTTP请求
哇,那是一堆步骤! 但是现在客户端有了IP地址和 TCP连接,它终于可以发送HTTP请求了! 除了……..我在开玩笑,这次我们可以发送真实的请求!
![](https://i-blog.csdnimg.cn/blog_migrate/0baac68171d7c6592273564d30459796.png)
- 该请求由“请求行”,请求标头和正文组成。 “请求行”仅是指示HTTP 方法 ,请求的资源和协议版本的行。 请求的头由成对的格式为
name:value <CR><LF>
。 两对连续的<CR><LF>
对指示标头部分的结尾。 HTTP请求中唯一的必填字段是HOST
,它包含将请求发送到的域和端口(domain.com:8080
),尽管在某些情况下可以省略该端口。 在主机字段之外,常见的标准HTTP标头字段包括Origin
,Accept
,Accept-Encoding
等。 该请求还可以包括任何非标准头字段,并且过去非标准字段通过在字段名称前添加X-
来表示。 HTTP请求的主体内容是完全可选的,但通常包含诸如表单数据或JSON之类的内容。 - 发送HTTP请求后,它将遵循与前面讨论的路由过程类似的路由过程,不同之处在于,使用TCP魔术序列号功能,服务器可以确保以正确的顺序接收到整个请求。
- 服务器接收到请求,对其进行处理并找到所请求的资源后,就会生成HTTP响应。 HTTP响应具有与HTTP请求类似的结构,包含“状态行”,响应标头字段和可选主体。 状态行包含指示请求成功,失败或错误状态的HTTP状态代码 ,以及提供详细信息的“原因消息”。
- 生成响应后,服务器将响应该请求。 在TCP层,客户端接收第一个数据包,其第一个字节应包含HTTP响应标头。 更多的数据包开始进入,并在TCP层根据需要对其进行重新排序。 对于客户端在TCP层收到的每两个数据包,它将向服务器发送
ACK
消息。 这一直持续到(希望)响应完全加载为止。
步骤5:拆除并清理
我们快到了!
- 响应完全传递后,客户端将在TCP级别发送
FIN
数据包,服务器以ACK
响应该FIN
数据包,然后通常发送其自身的FIN
,客户端以其自身的ACK
信号进行响应。 然后,客户端等待短暂的超时,在此期间它不能接受新的连接,以防止来自先前连接的延迟数据包在端口上的后续活动期间到达。 这种四向握手 ¹² 表示TCP连接结束。 - 此时,浏览器开始处理它收到的内容。 如果是浏览器内部某些应用程序正在使用的图像,数据或其他媒体文件,则可能会发生各种情况。 如果收到的数据是HTML,则浏览器将开始解析HTML,并呈现您请求的页面。 在解析过程中,浏览器可能会遇到指向其所接收HTML外部的图像或其他媒体的链接,并将启动对该内容的新请求,从而重新启动整个过程(尽管通常由于缓存而跳过了步骤1和2)。 )。 但是,鉴于我们只对单个请求的生命周期感兴趣:恭喜,我们(应用程序)的工作已经完成!
同样,以上所有内容仅是对简单HTTP事务的描述,而不是对多个请求维持相同连接的持久性事务的描述,但是该模型与TCP连接一旦发生时的行为没有太大差异。打开并交换第一个控制数据包。 它还不涉及并行HTTP事务,该事务在建立第一个请求的连接后会为后续请求增加额外的连接,但是生命周期不会发生太大变化。 首先,这些其他方法可以帮助缓解您在阅读时可能注意到的问题:单个TCP连接的握手旋转和拆除过程可能非常耗时,并且开发人员可以避免重新执行或执行他们连续。
就是这样,这就是单个HTTP请求的多层生命周期! 感谢您的阅读,请让我知道您的想法,如果您需要任何更正,请与我们联系!
本来在发表 dev.to 。 来源列表可在 原始帖子 的末尾找到 。
From: https://hackernoon.com/things-i-brushed-up-on-this-week-the-http-request-lifecycle-a321775a1282