这个问题定期思考,感受自己的成长与变化。
一个请求过来都经过了什么?(2017年http版)
一个请求过来都经过了什么?(Thrift版)
一个http请求进来都经过了什么(2021版)
网络链路
一个请求如果请求了静态资源,会优先查找缓存,包括浏览器缓存、CDN加速缓存。
浏览器缓存,是指浏览器本地缓存了已请求成功过的服务器文件,在下次加载文件时,根据缓存策略从浏览器本地缓存中读取或者从服务器读取。
浏览器缓存的发起方是服务器(包括应用服务器、CDN、Nginx代理服务器等)。服务器在某次HTTP的response中设置header参数,表示启用浏览器缓存,浏览器收到后,遵循HTTP的规范,在下一次request中触发浏览器缓存。
服务器在response头中设置Cache-Control(request头中也可以设置),如图所示。
如果是动态资源,DNS会进行域名解析,找到目标服务器。过程中数据包在网络中可以被路由器转发,每次转发ttl数值减一;
内网链路
到达目标服务器所在的外网DMZ区,DMZ区是一个隔离区域,可以进行流量清洗,避免攻击直接渗透到内网,提升攻击成本。经过接入路由器、接入交换机、接入防火墙,达到内网DMZ区的核心交换机,核心交换机转到对应的生产云spine交换机、F5设备、生产云leaf交换机,到达公司的负载均衡设备,比如nginx。
负载均衡设备作为服务端会与客户端进行三次握手建立连接,同时负载均衡设备自身又会作为客户端与下一层的服务,比如Web应用服务建立连接。
web应用链路
传统前后端不分离的spring mvc处理流程:
如果Web应用服务使用的是jetty容器,内嵌servlet,请求被前端控制器DispatcherServlet所拦截,调用HandlerMapping来根据请求URL找到具体的处理器,DispatcherServlet会通过返回的处理器对象选择合适的HandlerAdapter;HandlerAdapter会调用Controller,Controller执行完成后,会返回一个ModelAndView对象;HandlerAdapter将ModelAndView对象返回给DispatcherServlet;DispatcherServlet会将ModelAndView对象选择一个合适的VIewResolver;ViewResolver解析后,会向DispatcherServlet中返回具体的View;DispatcherServlet对View进行视图渲染,渲染结果返回给客户端。
现在通用的前后端分离的Spring MVC主要可以分为两大过程,一是初始化,二就是处理请求。初始化的过程主要就是将我们定义好的 RequestMapping 映射路径和 Controller 中的方法进行一一映射存储,这样当收到请求之后就可以处理请求调用对应的方法,从而响应请求。
SQL处理链路
抛开中间件不谈,Web应用一般会访问数据库。一条SQL查询语句执行的流程:
客户端与MYSQL服务端基于通讯协议建立连接,使用半双工的通信方式。半双工指的是同一时刻,要不发送数据,不要接收数据。线程状态会标识线程目前是处于哪种状态。如果开启了查询缓存,并且找到了完全一致的SQL(还需要同时满足结果集不大于设置阈值、没标识不使用查询缓存、并且查询中不存在函数等不确定参数时),则直接返回结果集。如果没有找到完全一致的SQL或者没有开启查询缓存,则进行下面的处理。值得注意的是自从MYSQL5.7之后,查询缓存功能就被移除了,因为数据库更新频繁导致缓存失效的情况较多,引发了性能上的问题。
解析器会把SQL做语法解析,生成解析树,预处理器对其进行语法检查,生成新的解析树。查询优化器生成一个最优的执行计划,交给查询执行引擎,执行引擎根据存储引擎不同调用不同的接口,返回结果,并且根据设置决定是否缓存。