一个web请求到底发生了什么?

        HTTP其实就是一个客户端与服务器之间的一种通讯协议,http客户端发起请求,就会在服务端建立一个端口,而http服务器就在端口监听客户端的请求,HTTP服务器返回状态和内容。css

1、从输入一个网址开始

当咱们在浏览器输入一个网址,而后按下回车,接下来浏览器显示了页面。网速好的话这之间可能就一秒,但在这一秒内到底发生了什么?前端

本文主要内容是试图记录一个完整 Web 请求的详细过程,从用户在浏览器中输入 URL 地址提及,而后浏览器如何找到服务器地址的过程,并发起请求;分析请求在达反向代理服务器内部处理过程;最后到请求在服务器端处理完成后,浏览器渲染响应页面过程。web

大体过程以下:数据库

Web请求的工做原理能够简单地概括为:浏览器

  1. 浏览器经过 DNS 把域名解析成对应的IP地址;
  2. 根据这个 IP 地址在互联网上找到对应的服务器,创建 Socket 链接;
  3. 客户端向服务器发送HTTP协议请求包,请求服务器里的资源文档;
  4. 在服务器端,实际上还有复杂的业务逻辑:服务器可能有多台,到底指定哪台服务器处理请求,这须要一个负载均衡设备来平均分配全部用户的请求;
  5. 还有请求的数据是存储在分布式缓存里仍是一个静态文件中,或是在数据库里;
  6. 当数据返回浏览器时,浏览器解析数据发现还有一些静态资源(如:css,js或者图片)时又会发起另外的请求,而这些请求可能会在CDN上,那么CDN服务器又会处理这个用户的请求。
  7. 客户端与服务器断开。由客户端解释HTML文档,在客户端屏幕上渲染图形结果。

一个 HTTP 事务就是这样实现的,看起来很简单,原理实际上是挺负杂的。须要注意的是客户机与服务器之间的通讯是非持久链接的,也就是当服务器发送了应答后就与客户机断开链接,等待下一次请求。缓存

但须要注意的是,从 HTTP 1.1 开始,服务器能够与客户端保持长链接,不必定是请求完成后就断开链接,这取决于服务器的操做。安全

2、DNS 域名解析

首先来看看最早发生的事情——DNS 域名解析,简单的说就是把域名翻译成 IP 地址。例如:把 www.test.com 这个域名翻译成对应 IP 192.168.1.1,这里只是举个例子。服务器

若是你在浏览器中直接输入的 IP 地址,那么实际上会跳过这个步骤,不然会经理下面几部:微信

一、浏览器缓存检查网络

浏览器会首先搜索浏览器自身的 DNS 缓存,缓存时间比较短,大概只有1分钟,且只能容纳1000条缓存,看自身的缓存中是否有对应的条目,并且没有过时,若是有且没有过时则解析到此结束。

二、操做系统缓存检查 + hosts 解析

若是浏览器的缓存里没有找到对应的条目,操做系统也会有一个域名解析的过程,那么浏览器先搜索操做系统的 DNS 缓存中是否有这个域名对应的解析结果,若是找到且没有过时则中止搜索,解析到此结束。

在 Linux 中能够经过 /etc/hosts 文件来设置,能够将任何域名解析到任何可以访问的 IP 地址。若是在这里指定了一个域名对应的 IP 地址,那么浏览器会首先使用这个 IP 地址。当解析到这个配置文件中的某个域名时,操做系统会在缓存中缓存这个解析结果,缓存的时间一样是受这个域名的失效时间和缓存的空间大小控制的。

三、本地区域名服务器(Local DNS Server)解析

若是在 hosts 文件中也没有找到对应的条目,浏览器会发起一个 DNS 的系统调用,会向本地配置的首选 DNS 服务器发起域名解析请求(经过的是 UDP 协议向 DNS 的 53 端口发起请求,这个请求是递归的请求,也就是运营商的DNS服务器必须得提供给咱们该域名的IP地址)。

在咱们的网络配置中都会有“DNS 服务器地址”这一项,这个地址就用于解决前面所说的若是两个过程没法解析时要怎么办。操做系统会把这个域名发送给这里设置的 LDNS,也就是本地区的域名服务器。

这个 DNS 一般都提供给你本地互联网接入的一个 DNS 解析服务,例如你是在学校接入互联网,那么你的 DNS 服务器确定在你的学校;若是你是在一个小区接入互联网的,那这个 DNS 就是提供给你接入互联网的应用提供商,即电信或者联通。大约 80% 的域名解析都到这里就已经完成了,因此 LDNS 主要承担了域名的解析工做。

四、根域名服务器解析(Root Server)

若是 LDNS 没有找到对应的条目,则由运营商的 DNS 代咱们的浏览器发起迭代 DNS 解析请求。它首先是会找根域的 DNS 的 IP 地址,找到根域的 DNS 地址,就会向其发起请求。而后根域名服务器返回给本地域名服务器一个所查询域的主域名服务器(gTLD Server)地址。

五、主域名服务器(gTLD Server)

本地域名服务器(LDNS Server)再向上一步返回的 gTLD 服务器发送请求。

接受请求的 gTLD 服务器查找并返回此域名对应的 Name Server 域名服务器的地址,这个 Name Server 一般就是你注册的域名服务器,例如你在某个域名服务提供商申请的域名,那么这个域名解析任务就由这个域名提供商的服务器来完成。

Name Server 域名服务器会查询存储的域名和IP的映射关系表,正常状况下都根据域名获得目标IP记录,连同一个 TTL 值返回给 DNS Server 域名服务器。

下图汇总了上面所说的 DNS 解析过程:

3、TCP 的 3 次握手

拿到域名对应的 IP 地址后,User-Agent(通常是指浏览器)会以一个随机端口(1024 < 端口 < 65535)向服务器的 WEB 程序发起 TCP 的链接请求。

这里还涉及 ARP(地址解析协议):是根据 IP 地址获取物理地址 (MAC 地址) 的一个协议。
当一个数据帧通过屡次路由到达目的网络时,路由器只能知道其数据帧中的目的 IP 地址,而不知目标主机的硬件地址,网络层使用的是 IP地址,可是在实际网络链路上传送数据帧时,最终必须使用该网络的硬件地址,此时须要目的主机的硬件地址,就要使用 ARP 来获取到对应 IP 地址主机的物理地址。

这个链接请求(原始的 Http 请求通过 TCP/IP 4层模型的层层封包)到达服务器端后(这中间经过各类路由设备,局域网内除外),进入到网卡,而后是进入到内核的 TCP/IP 协议栈(用于识别该链接请求,解封包,一层一层的剥开),还有可能要通过Netfilter防火墙(属于内核的模块)的过滤,最终到达WEB程序,最终创建了TCP/IP的链接。

  1. Client 首先发送一个链接试探,SYN = 1 表示这是一个链接请求或链接接受报文,同时表示这个数据报不能携带数据,seq = x 表示 Client 本身的初始序号(seq = 0 就表明这是第 0 号包),这时候 Client 进入 syn_sent 状态,表示客户端等待服务器的回复。

  2. Server 监听到链接请求报文后,如赞成创建链接,则向 Client 发送确认。报文中的 SYN 和 ACK 都置 1 ,ACK = x + 1 表示指望收到对方下一个报文段的第一个数据字节序号是 x+1,同时代表 x 为止的全部数据都已正确收到(ACK = 1 实际上是 ACK = 0 + 1,也就是指望客户端的第 1 个包),seq = y 表示 Server 本身的初始序号(seq = 0 就表明这是服务器这边发出的第 0 号包)。这时服务器进入 syn_rcvd,表示服务器已经收到 Client 的链接请求,等待确认。

  3. Client 收到确认后还需再次发送确认,同时携带要发送给 Server 的数据。ACK 置 1 表示确认号 ack= y + 1 有效(表明指望收到服务器的第 1 个包),Client本身的序号 seq= x + 1(表示这就是个人第1个包,相对于第0个包来讲的),一旦收到Client的确认以后,这个TCP链接就进入 Established 状态,就能够发起请求了。

4、Nginx 反向代理

一、反向代理

反向代理(Reverse Proxy)方式是指:代理服务器来接受 Internet 上的链接请求,而后将请求转发给内部网络上的服务器,并将从内部网络上服务器获得的结果返回给 Internet 上请求链接的客户端。此时代理服务器对外就表现为一个服务器,反向代理服务器对于客户端而言它就像是原始服务器,而且客户端不须要进行任何特别的设置。

反向代理的做用:

  1. 保证内网的安全,可使用反向代理提供 WAF 功能,阻止 web 攻击。

  2. 负载均衡,经过反向代理服务器来优化网站的负载。

二、正向代理

既然有反向代理,就确定有正向代理。什么叫正向代理呢?

正向代理(Forward Proxy)一般都被简称为代理,就是在用户没法正常访问外部资源,能够经过代理的方式,让用户绕过防火墙,从而链接到目标网络或者服务。

正向代理的工做原理就像一个跳板。

好比:我访问不了 google.com,可是我能访问一个代理服务器 A,A 能访问 google.com,因而我先连上代理服务器 A,告诉它我须要 google.com 的内容,A 就去取回来,而后返回给我。

从网站的角度,只在代理服务器来取内容的时候有一次记录,有时候并不知道是用户的请求,也隐藏了用户的资料,这取决于代理告不告诉网站。

正向代理是一个位于客户端和原始服务器(origin server)之间的服务器。为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),而后代理向原始服务器转交请求并将得到的内容返回给客户端。

三、正向代理与反向代理对比

5、关闭 TCP 链接

这一步不是全部的网页都会这么作,例如网页版微信就没有关闭 TCP 链接,由于微信上别人能够随时发消息给你,实际上别人先把消息发送到了微信服务器,微信服务器再经过 TCP 连接,把消息推送到你的屏幕上。

试想一下,若是网页版微信关闭了 TCP 链接会怎样?

结果是:你不刷新网页,就永远收不到消息了。同时,若是你频繁的发消息给别人,那么就在频繁的建立链接,关闭链接,这是很消耗资源的。因此微信就干脆不关闭 TCP 链接,这样微信服务器就能够给咱们的浏览器发消息。

下图是一次 Http 请求报文头部信息,其中 Connection: keep-alive 意味着此次请求结束后不会关闭 TCP 链接。

固然不是全部的 HTTP 请求都没有关闭链接,例如一篇博文,浏览器收到数据显示就能够了,没有那么多动态数据,我看完就关了,这时就应该关闭 TCP 链接,固然这仍是取决于请求的服务器。说了这么多,还没说关闭链接。

关闭 TCP 链接专业点说叫作“四次挥手”,与 TCP 创建链接的“三次握手”相对应。

因为TCP链接是全双工的,所以每一个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个 FIN 来终止这个方向的链接。收到一个 FIN 只意味着这一方向上没有数据流动,一个TCP链接在收到一个 FIN 后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另外一方执行被动关闭。


结束语: 作一个努力、勤奋、主动的前端工程师

相关文章
相关标签/搜索