一次完整的网络请求这个问题虽然很平凡,但仔细想想它涉及了计算机网络协议栈、操作系统、数据库系统原理、服务器端架构、网络安全…如果还考虑前端渲优化,可能连用户体验、心理学(如何让用户感觉面页加载更快)都用上了….好好想想这个问题,梳理下各个环节。

  1. APP客户端、浏览器端处理、用户代理:协商加密、RSA、AES、HTTP协议、URL处理、请求头构造、表单构造、前端缓存、Ajax、域名缓存TTL
  2. DNS、DNS-poll、hosts文件、客户端通过正向代理
  3. 操作系统层面,系统级I/O操作:epoll、poll、select、线程并发或进程并发、IO复用、数据从内核空间到用户空间
  4. TCP、三四次握手、流量控制、拥塞控制、滑动窗口、超时重传、Nagle算法、长连接、管线化
  5. IP、前置代理、VPN、路由选择算法、ARP(考虑socks翻墙)
  6. 链路层、网络接口层、通信原理、差错检测、纠错原理
  7. 反向代理、服务器端、入侵检测系统、DoS、SYNC洪流
  8. 负载均衡、LVS、反向代理、CDN服务器、高可用性、容灾性(为什么LVS不能代替DNS轮询)
  9. HTTP解析、RESTful风格
  10. 应用服务器、子域名、业务应用、业务拆分、robot协议、IP地址访问权限、IP地址访问频次控制、防网络爬虫
  11. 缓存、网络安全、注入攻击、Session、Cookie、用户认证
  12. 数据库操作、搜索引擎、访问日志记录、消息队列、分布式系统、微服务、BASE特性、分布式下的数据一致性处理
  13. MVC架构模式视图、JSON、XML、前后端分离的工程化
  14. 逆着TCP/IP栈、从解包、封装的角度
  15. 前端、HTML、CSS、JavaScript、渲染、用户体验、状态码、重定向、交互设计、多媒体流
    补充:HTTP2.0、websocket、RTC、UDP在各种业务下的使用、解析完毕后的片段定位

从网络请求到响应一共分了十五层,下面详细说这十五层。

APP客户端、浏览器端

APP客户端、浏览器在用户资源请求的代理,负责构造请求相关的信息。包括HTTP层面的处理、封装,资源缓存等。

  • 请求方式、URI方案
    客户端在处理URL前确定请求方式和URI方案,通常URI方案有FTP、HTTP、HTTPs,这里以HTTP为例,因为它更有代表性。常见的请求方式包括GET、POST、PUT、DELETE。请求方式和URI方案会用在请求行中。请求行的结构如下:<Request-Method> URL <Request-Schema> \<version>[CRLF]

  • URL处理
    浏览器解析URL,分割出域名部分和资源路径、请求参数部分,同时除掉片段部分(”#”后面部分)。资源路径和请求参数用于请求行。域名用于域名解析找到其对于的主机IP地址。

  • 请求头构造
    浏览器根据操作系统类型构造User-Agent字段,Accept首部告知服务器客户端期望接收的类型。文本类型通常是text/html,媒体类型有image/jpeg等。Accept-Charset告知服务器用户代理(客户端)支持的字符集。Accept-Encoding首部告知服务器用户代理支持的内容编码。通常如下:Accept-Encoding:gzip,deflate。Accept-Language告知服务器用户代理期待接收的语言。Host首部保存主机首部。通常在虚拟主机上使用,用以区分同一IP主机上不同应用。还有和缓存有关的首部。

  • 表单处理
    浏览器会把用户表单,包括用户在客户端上的输入,用户名、密码等进行包装和转换。这部分会封装到HTTP请求报文的实体上。

  • 前端缓存
    在发送请求前,浏览器会先确定本地是否有请求资源的缓存。如果有且和服务器协商后没有过期会直接使用缓存而不再发送该资源的请求。

  • Ajax
    有时候发送请求的可能是浏览器面业上的JavaScript触发的。Ajax负责发送请求而局部更新面页而不用浏览器整体刷新。

  • 协商加密
    其实在浏览器进行HTTP请求前,会在TCP上建立一条安全通道。先通过RSA非对称加密协商加密算法,通常是AES,协商成功后。然后HTTP上的通信会用过AES算法加密。

  • 域名-IP缓存检测
    浏览器会检测缓存中有没有域名对应的解析过的IP地址,如果有且没有超过缓存有效时间(通过TTL来设置),就使用该IP地址,地址解析过程结束。否则,进行下一步的域名解析过程。

域名解析过程

浏览器处理完HTTP部分后,HTTP报文都已经构造完成了,需要通过域名找到目标主机的IP地址。

  • hosts文件
    浏览器先在操作系统的/etc/hosts文件中查找指定域名的IP地址,如果找到就使用该IP地址,否则向DNS系统发起请求。但这里有一个安全问题,域名劫持,该域名不是指向对应的IP地址,而是指向其他不安全的IP地址。解决方法是hosts文件只读。如果这一部分无法解析出IP地址,则调到DNS解析。

  • DNS
    DNS是一个分布式系统,在CAP理论中满足AP特性,在一致性上是最终一致性,当更新一个域名的IP以后,根据配置策略以及缓存控制的策略,最终所有客户端都能看到最新的值。这个时间间隔包括缓存的TTL和网络延时。DNS查询过程包括递归查询和迭代查询。它的大致过程。

  1. 操作系统向本地服务器发送域名解析请求。这个域名解析服务器负责域名解析的缓存。当查询的域名对应的IP在缓存中且没有超时,就返回给操作系统。如果没有命中就进入下一步。

  2. 本地服务器向根服务器发起域名解析请求。根域名服务器返回给本地服务器一个所有查询域的主域名服务器(gTLD)IP地址。它们负责解析.com、.cn、.org这类域名。

  3. 本地服务器根据解析的域名的后缀向指定主域名服务器发起解析请求。接受请求的主域名服务器返回此域名对应的Name Server的IP地址。Name Server指该域名注册的服务器。

  4. 本地服务器向该域名的Name Server发起解析请求,Name Server接受请求后,返回域名对应的IP地址和TTL缓存时间。这些保存到本地服务器中,同时把IP地址返回给操作系统。用户根据TTL值设置本地缓存,域名解析过程结束。

请求在操作系统层面的处理

域名解析结束后,操作系统需要发送该HTTP请求。

  • 线程、进程并发,并发访问网络资源

  • I/O复用,包括select、poll、epoll

正向代理与反向代理

正向代理为客户端负责,连接到该代理的客户端,可以通过代理访问任何其他服务器。

反向代理为服务器负责,当客户端要访问该服务器时,反向代理代理客户端的请求,并转发给服务器。