Skip to content

Latest commit

 

History

History
140 lines (80 loc) · 12.9 KB

HTTP 请求的发送的详细流程.md

File metadata and controls

140 lines (80 loc) · 12.9 KB

HTTP 请求的发送的详细流程

1、域名解析

DNS 服务器,一定要设置成高可用、高并发和分布式的。

img

  • 根 DNS 服务器 :返回顶级域 DNS 服务器的 IP 地址
  • 顶级域 DNS 服务器:返回权威 DNS 服务器的 IP 地址
  • 权威 DNS 服务器 :返回相应主机的 IP 地址

DNS 解析流程

很多网络都会就近部署 DNS 缓存服务器。

本地 DNS 解析器先查看看本地的缓存是否有这个记录。如果有则直接使用,因为递归过程太复杂了,如果每次都要递归解析,就太麻烦了。如果本地无缓存,则需要请求本地的 DNS 服务器,也就是下边的过程:

  1. 电脑客户端会发出一个 DNS 请求,问 www.163.com 的 IP 是啥啊,并发给本地域名服务器 (本地 DNS)。那本地域名服务器 (本地 DNS) 是什么呢?如果是通过 DHCP 配置,本地 DNS 由你的网络服务商(ISP),如电信、移动等自动分配,它通常就在你网络服务商的某个机房。
  2. 本地 DNS 收到来自客户端的请求。你可以想象这台服务器上缓存了一张域名与之对应 IP 地址的大表格。如果能找到 www.163.com,它直接就返回 IP 地址。如果没有,本地 DNS 会去问它的根域名服务器:“老大,能告诉我 www.163.com 的IP地址吗?”根域名服务器是最高层次的,全球共有13套。它不直接用于域名解析,但能指明一条道路。
  3. 根 DNS 收到来自本地 DNS 的请求,发现后缀是 .com,说:“哦,www.163.com啊,这个域名是由.com区域管理,我给你它的顶级域名服务器的地址,你去问问它吧。”
  4. 本地 DNS 转向问顶级域名服务器:“老二,你能告诉我 www.163.com 的 IP 地址吗?”顶级域名服务器就是大名鼎鼎的比如 .com、.net、 .org这些一级域名,它负责管理二级域名,比如 163.com,所以它能提供一条更清晰的方向。
  5. 顶级域名服务器说:“我给你负责 www.163.com 区域的权威DNS服务器的地址,你去问它应该能问到。”
  6. 本地 DNS 转向问权威 DNS 服务器:“您好,www.163.com 对应的 IP 是啥呀?”163.com 的权威 DNS 服务器,它是域名解析结果的原出处。为啥叫权威呢?就是我的域名我做主。
  7. 权威 DNS 服务器查询后将对应的 IP 地址 X.X.X.X 告诉本地 DNS。
  8. 本地 DNS 再将 IP 地址返回客户端,客户端和目标建立连接。

img

2、TCP 的三次握手,建立连接

3、包由 TCP 层到 IP 层到 MAC 层

  1. ​ HTTP 协议是基于 TCP 协议的,所以它使用面向连接的方式发送请求,通过 stream 二进制流的方式传给对方。当然,到了 TCP 层,它会把二进制流变成一个的报文段发送给服务器。
  2. ​ TCP 层发送每一个报文的时候,都需要加上自己的地址(即源地址)和它想要去的地方(即目标地址),将这两个信息放到 IP 头里面,交给 IP 层进行传输。
  3. ​ IP 层需要查看目标地址和自己是否是在同一个局域网。如果是,就发送 ARP 协议来请求这个目标地址对应的MAC 地址,然后将源 MAC 和目标 MAC 放入 MAC 头,发送出去即可;
  4. ​ 如果不在同一个局域网,就需要发送到网关,还要需要发送 ARP 协议,来获取网关的 MAC 地址,然后将源 MAC 和网关 MAC 放入 MAC 头,发送出去。
  5. ​ 其中在网关(通常是一个路由器,它有多个(5个)网口或者网卡,分别连着多(五)个局域网)这层,任何一个想发往其他局域网的包会被拿下 MAC 头和 IP 头,根据自己的路由算法(静态路由或动态路由),加上IP头和MAC,通过另一个网卡丢出去。
  6. ​ 网关收到包发现 MAC 符合,取出目标 IP 地址,根据路由协议找到下一跳的路由器,获取下一跳路由器的 MAC 地址,将包发给下一跳路由器。
  7. ​ 这样路由器一跳一跳终于到达目标的局域网。这个时候,最后一跳的路由器能够发现,目标地址就在自己的某一个出口的局域网上。于是,在这个局域网上发送 ARP,获得这个目标地址的 MAC 地址,将包发出去。
  8. ​ 目标的机器发现 MAC 地址符合,就将包收起来;发现 IP 地址符合,根据 IP 头中协议项,知道自己上一层是 TCP 协议,于是解析 TCP 的头,里面有序列号,需要看一看这个序列包是不是我要的,如果是就放入缓存中然后返回一个 ACK,如果不是就丢弃。

4、包到 HTTP 服务器

​ 首先到达 LSV 或者 Nginx 反向代理,做负载均衡。

​ TCP 头里面还有端口号,HTTP 的服务器正在监听这个端口号。于是,目标机器自然知道是 HTTP 服务器这个进程想要这个包,于是将包发给 HTTP 服务器。

​ HTTP 服务器不直接跟业务类打交道,而是根据端口把请求交给 Servlet 容器去处理,Servlet 容器会将请求转发到具体的 Servlet,如果这个 Servlet 还没创建,就加载并实例化这个 Servlet,然后调用这个 Servlet 的接口方法。

​ 首先会根据应用层协议确定使用哪个连接器,然后经过 Service(就是一个web服务,一个web服务包含多个连接器和一个web容器) 组件的链接器,链接器中的 ProtocolHandler 组件抽象化出实现 TCP/IP 协议的组件 EndPoint,然后由它进行 Socket 接收和发送,接着组件 Processor 接收来自 EndPoint 的 Socket,读取字节流解析成 Tomcat Request 和 Response 对象,并通过 Adapter 将其提交到容器处理。Servlet 容器把 ServletResponse 对象返回给 HTTP 服务器,HTTP 服务器会把响应发送给客户端。

附:

1、ICMP 协议

​ ping 是基于ICMP协议工作的。ICMP 全称Internet Control Message Protocol,就是互联网控制报文协议。ICMP 报文是封装在IP包里面的。因为传输指令的时候,肯定需要源地址和目标地址,而且它本身非常简单。

2、MAC 头和 IP 头的细节

​ 一旦配置了 IP 地址和网关,往往就能够指定目标地址进行访问了。由于在跨网关访问的时候,牵扯到 MAC 地址和 IP 地址的变化。

img

​ 在 MAC 头里面,先是目标 MAC 地址,然后是源 MAC 地址,然后有一个协议类型,用来说明里面是 IP 协议。IP 头里面的版本号,目前主流的还是 IPv4,服务类型TOS,TTL。另外,还有 8 位标识协议。这里到了下一层的协议,也就是,是 TCP 还是 UDP(端口就是在TCP 和 UDP 层确定的)。最重要的就是源 IP 和目标 IP。先是源 IP 地址,然后是目标 IP 地址。

3、DNS 负载均衡

DNS 除了可以通过名称映射为 IP 地址,它还可以做另外一件事,就是负载均衡

内部负载均衡

​ 在域名解析的时候,我们只要配置策略,这次返回第一个IP,下次返回第二个IP,就可以实现负载均衡了。例如,某个应用通过域名访问另外一个应用的时候。

全局负载均衡

​ 为了保证我们的应用高可用,往往会部署在多个机房,每个地方都会有自己的 IP 地址。当用户访问某个域名的时候,肯定希望北京的用户访问北京的数据中心,上海的用户访问上海的数据中心,这样,客户体验就会非常好,访问速度就会超快。这就是全局负载均衡的概念。

​ 当一个客户端要访问 object.yourcompany.com 的时候,需要将域名转换为IP地址进行访问。对于不需要做全局负载均衡的简单应用来讲,yourcompany.com 的权威 DNS 服务器可以直接将 object.yourcompany.com 这个域名解析为一个或者多个 IP 地址,然后客户端可以通过多个 IP 地址,进行简单的轮询,实现简单的负载均衡。

​ 但是对于复杂的应用,尤其是跨地域跨运营商的大型应用,则需要更加复杂的全局负载均衡机制,因而需要专门的设备或者服务器来做这件事情,这就是全局负载均衡器GSLBGlobal Server Load Balance)。

​ 在 yourcompany.com 的 DNS 服务器中,一般是通过配置 CNAME 的方式,给 object.yourcompany.com 起一个别名,例如 object.vip.yourcomany.com,然后告诉本地 DNS 服务器,让它请求 GSLB 解析这个域名,GSLB 就可以在解析这个域名的过程中,通过自己的策略实现负载均衡。

​ 图中画了两层的 GSLB,是因为分运营商和地域。我们希望不同运营商的客户,可以访问相同运营商机房中的资源,这样不跨运营商访问,有利于提高吞吐量,减少时延。

  1. 第一层 GSLB,通过查看请求它的本地 DNS 服务器所在的运营商,就知道用户所在的运营商。假设是移动,通过 CNAME 的方式,通过另一个别名 object.yd.yourcompany.com,告诉本地 DNS 服务器去请求第二层的GSLB。
  2. 第二层 GSLB,通过查看请求它的本地 DNS 服务器所在的地址,就知道用户所在的地理位置,然后将距离用户位置比较近的 Region 里面,六个 内部负载均衡SLB,Server Load Balancer)的地址,返回给本地DNS 服务器。

img

4、静态路由和动态路由

路由表:

​ 路由器就是一台网络设备,它有多张网卡。当一个入口的网络包送到路由器时,它会根据一个本地的转发信息库,来决定如何正确地转发流量。这个转发信息库通常被称为路由表

​ 一张路由表中会有多条路由规则。每一条规则至少包含这三项信息:

  • 目的网络:这个包想去哪儿?
  • 出口设备:将包从哪个口扔出去?
  • 下一跳网关:下一个路由器的地址。

通过 route 命令和 ip route 命令都可以进行查询或者配置。

例如,我们设置 ip route add 10.176.48.0/20 via 10.173.32.1 dev eth0,就说明要去 10.176.48.0/20 这个目标网络,要从 eth0 端口出去,经过 10.173.32.1。

静态路由

​ 静态路由其实就是在路由器上,配置一条一条规则:访问的网站需要从哪个口出去。

动态路由

​ 使用动态路由路由器,可以根据路由协议算法生成动态路由表,随网络运行状况的变化而变化。那路由算法是什么样的呢?

1.距离矢量路由算法

​ 它是基于 Bellman-Ford 算法的。这种算法的基本思路是,每个路由器都保存一个路由表,包含多行,每行对应网络中的一个路由器,每一行包含两部分信息,一个是要到目标路由器,从那条线出去,另一个是到目标路由器的距离。由此可以看出,每个路由器都是知道全局信息的。

2.链路状态路由算法

​ 基于Dijkstra算法。这种算法的基本思路是:当一个路由器启动的时候,首先是发现邻居,向邻居say hello,邻居都回复。然后计算和邻居的距离,发送一个echo,要求马上返回,除以二就是距离。然后将自己和邻居之间的链路状态包广播出去,发送到整个网络的每个路由器。这样每个路由器都能够收到它和邻居之间的关系的信息。因而,每个路由器都能在自己本地构建一个完整的图,然后针对这个图使用Dijkstra算法,找到两点之间的最短路径。

5、转发网关(不改变IP地址的网关)和 NAT 网关(改变IP地址的网关)

IP 头和 MAC 头哪些变、哪些不变?

​ MAC 地址是一个局域网内才有效的地址。因而,MAC地址只要过网关,就必定会改变,因为已经换了局域网。转发网关和 NAT 网关两者主要的区别在于 IP 地址是否改变。

转发网关:

​ 每到一个新的局域网,MAC都是要变的,但是IP地址都不变。在IP头里面,不会保存任何网关的IP地址。**所谓的下一跳是,某个 IP 要将这个 IP 地址转换为 MAC 放入 MAC 头。**IP 地址在多个局域网都可见,在多个局域网之间的网段都不会冲突。在多个网段之间传输包,IP 头不改变。

NAT 网关:

​ 局域网之间没有商量过,各定各的网段,因而 IP 段冲突了。

​ 当网络包发送到中间的局域网的时候,服务器A也需要有个国际身份,因而在国际上需要有一个跟局域网对应的国际IP。

​ 从服务器B接收的包可以看出,源IP为服务器A的国际身份,因而发送返回包的时候,也发给这个国际身份,由路由器A做NAT,转换为国内身份。