一次网络请求的完整生命周期

五层协议

层级 协议 协议 协议 协议 协议 协议 协议 协议
应用层 DHCP HTTP HTTPS RTMP P2P DNS GTP RPC
传输层 UDP TCP
网络层 ICMP IP OSPF BGP IPSec GRE
链路层 ARP VLAN STP
物理层 网络跳线

一次网络请求的完整周期

从客户端发起请求,网络数据是从上而下的

应用层

以 Laravel 学院为例,要访问这个网站,首先需要在浏览器中输入 laravelacademy.org,这只是网站的域名,浏览器并不知道要去哪里访问对应的资源,这个时候就需要用到DNS协议对域名进行解析,在域名注册商(如阿里云旗下的万网)那里绑定了域名与对应的服务器IP地址,所以DNS就可以通过域名获取到与之绑定的 IP 地址,比如114.215.241.29,IP地址相当于互联网世界的「门牌号」。

知道了目标 IP 地址后,浏览器就开始打包本次请求,这里根据传输数据加密与否分为 HTTP 请求和 HTTPS 请求,使用的分别是 HTTP 协议和 HTTPS 协议,无论使用哪种协议,都要封装请求头和请求参数,以便服务器返回相应的响应:

报文 格式
HTTP头 GET、URL、HTTP1.1正文格式、正文长度
- 请求数据

DNS、HTTP、HTTPS 所在的层是应用层,经过应用层封装后,浏览器将应用层的包交个下一层去完成,这个过程通过 socket 编程来实现。

传输层

下一层是传输层,传输层有两种协议,一种是无连接的 UDP 协议,一种是面向连接的 TCP 协议,UDP 无需建立连接即可通信,但是不可靠,可能会丢包,TCP 需要三次握手建立连接,能够保证数据包达到目的地,但是有额外的开销,性能和速度不如 UDP。具体使用哪个协议,需要根据具体需求来定。

对于 HTTP/HTTPS 请求来说,都是基于 TCP 协议的可靠连接,TCP 协议有两个端口,一个是浏览器监听的端口(监听服务器响应),一个是服务器监听的端口(监听客户端请求,对于 HTTP 请求,通常是 80 端口,对于 HTTPS 请求,通常是 443 端口)。操作系统会根据端口来判断,将得到的包转发给哪个进程:

报文 格式
TCP头 浏览器端口:12345服务器端口443
HTTP头 GET、URL、HTTP1.1正文格式、正文长度
- 请求数据

网络层

传输层封装完成后,浏览器将包交给操作系统的网络层,网络层的协议是 IP 协议,在这一层,会给传输层传递过来的包加上 IP 头,其中包含源 IP 地址(浏览器所在机器)、目标 IP 地址(服务器所在机器)等信息:

报文 格式
IP头 客户端IP:192.168.0.1服务器IP:114.215.241.29
TCP头 浏览器端口:12345服务器端口443
HTTP头 GET、URL、HTTP1.1正文格式、正文长度
- 请求数据

操作系统知道目标机器 IP 地址后,就开始根据它来寻找目标机器,如果是本机局域网内的机器,可以直接通过 IP 地址判断出来,如果是局域网之外的机器,则需要通过网关去外面的世界查找。显然,这里的目标 IP 不在本地局域网。

链路层

操作系统启动的时候,就会通过 DHCP 协议配置 IP 地址,以及默认网关的 IP 地址:192.168.1.1。操作系统会通过 ARP 协议通过 IP 地址获取网关的 MAC 地址,并将本地网关和计算机的 MAC 地址添加到 MAC 头中:

报文 格式
MAC头 本地客户端MAC地址本地网关MAC地址
IP头 客户端IP:192.168.0.1服务器IP:114.215.241.29
TCP头 浏览器端口:12345服务器端口443
HTTP头 GET、URL、HTTP1.1正文格式、正文长度
- 请求数据

这样,操作系统就将 IP 包交给了下一层 —— 链路层,再经由网卡发送出去(客户端机器与网关之间还有物理层的线路连接)。

注:使用网卡(NIC)的情况下,MAC地址会被烧到ROM中,任何一张网卡的MAC地址都是全球唯一的。有人可能会问,有了IP地址为什么还要MAC地址?MAC地址就相当于你的身份证号,一旦出生就写死了,一辈子都不会变,而且具有全局唯一性。IP地址可以动态分配,不能保证全局唯一,只能保证局域网内唯一,相当于你的居住地址,可能过段时间就会变。 网关收到包以后,会根据自己的知识判断下一步怎么走,网关往往是一个路由器,到某个目标 IP 地址怎么走,有一个路由表。网络请求包往往需要经过多个网关的跳转,才能达到最终的目标机器。

假设网络包经过多个网关之后,最终到达了目标服务器所在的网关,通过 ARP 协议,目标服务器根据目标 IP 地址返回一个 MAC 地址,表示目标服务器在此,然后网络包通过这个 MAC 地址在服务器所在局域网内找到目标机器。

服务端接收请求的时候,与客户端发送请求相反,网络流是自下而上的

目标服务器发现与网络请求包的 MAC 地址对上了,取下MAC头,将包传递给上一层网络层,发现 IP 也对上了,就取下 IP 头,然后交给传输层。

在传输层里,对于收到的每一个包,都要回复包收到了,这个回复不是此次请求的响应,仅仅是回复包已收到而已,这个回复会沿着包的来路回去。如果过了一段时间(超时时间),客户端还是没有收到来自服务器的回复,会重新发送这个包,直到收到回复为止。同样,这个重发也不是重新发起上面那个客户端请求,而是传输层将同一个请求反复重试,对用户来说,只有一次请求。

回到目标服务器,当网络包到达传输层后,TCP头中有一个服务器监听端口号,通过这个端口号,可以找到 Laravel 学院网站正在监听的端口,即 Nginx 中配置的 443 端口,端口对上之后,取下 TCP 头,将网络包交给应用层,开始对 HTTP/HTTPS 请求进行处理。

如果是前端资源的话,直接通过 Nginx 进行响应,如果是 PHP 动态请求的话,再由 Nginx 将请求转发给后台运行的 PHP-FPM 进程进行处理。当然如果 Nginx 做了负载均衡,以及后端服务是分布式系统或者提供了微服务的化(涉及到RPC远程调用),还有更加复杂的处理逻辑,这些我们放到后面去讲。

当后台服务处理完成后,就会返回一个 HTTPS 的响应包,告知用户请求成功,并返回响应内容,同样这个网络响应包和请求包一样,自上而下经过层层打包,顺着来路经过层层「关卡」(网关),回到发起请求的客户端,然后再经过自下而上的处理,最终在客户端浏览器显示 Laravel 学院首页。

好了,通过了解一次网络请求的完整生命周期,你应该对网络包流转过程中网络分层和使用到的协议,乃至 Web 请求和响应的全貌有了一个更加清晰的认知。

原文来自Laravel学院君

你可能感兴趣的:(一次网络请求的完整生命周期)