高并发下如何缩短响应时间
定义
网站响应时间是指系统对请求作出响应的时间。通俗来讲就是我们把网址输入进浏览器然后敲回车键开始一直到浏览器把网站的内容呈现给使用者的这段时间。网站响应时间是越短越好,因为网站页面开启速度越快,就意味着我们的使用者可以更快的访问站点或者我们的服务器。一般我们网站的响应时间保持在100~1000ms即可。1m=1000ms,开启速度越快对使用者体验度越好。响应时间并不能直接反映网站效能的高低,但是在一定程度上反应了网站系统的处理能力,也是给使用者最直观上的感受。如果网站的响应时间过长,比如10秒以上,使用者的流失率会大大增加,所以把响应时间控制在一定范围内是提高使用者体验度的第一要素。
解决方案
当用户请求一个网站资料的时候,实际上是传送了一个http请求,在宏观上可以分为两个部分:1. http请求到达目标网站服务器之前2. http请求到达目标网站服务器之后如果忽略其中硬件部分和部分细节,请求一个网站资料的大体过程如下图所示(其中CDN和快取部分可以省略):

我们要想缩短一个网站的响应时间,本质上是提高资料的返回速度,说的直白一点就是要把请求资料过程中的各个步骤提高速度,这样整体下来响应时间就会缩短。
把资料放在离使用者越近的地方响应时间越快
客户端
客户端是发起一个网站请求的源头,其实这个源头可以施加一定的策略来大大缩短某些资料的获取时间。其中最为常用的就是快取,一些常用的,很少变动的资源快取在客户端,不但能缩短获取资源的时间,而且在很大程度上能减轻服务端的压力。比如一些图片,css,js档案,甚至一些界面的资料或者整个网页内容都可以在客户端做快取。另外http请求的合并也可以减少对服务端的请求次数,在一定程度上可以缩短请求的响应时间。
DNS
一般网站的访问方式都采用域名的方式(很少见IP方式),既然是域名就涉及到DNS解析速度的问题,如果DNS服务解析的速度比较慢,整体过程的响应时间也会加长,不过这个过程其实很少出现慢的问题(不是说没有)。
网络
客户端获取到网站IP之后通过网络卡把Http请求传送出去,目标地址为相应的网站服务器。在这个过程当中如果客户端和服务器端有一方带宽比较小的话,就会加大响应时间。我司曾经就因为服务器带宽过小导致客户端响应时间很长的情况,当时排查了很长时间才发现。
当然网络是不可靠的,这个过程的响应时间其实取决于很多因素,比如路由器的路由策略是否最优,整个过程通过的闸道器资料量等。所以有很多网站其实是多地区多机房部署的,目的就是为了让使用者通过很短的网络路径就能到达网站(其实这个过程运营商的选择也有影响)。
网站
当一个请求到达网站服务器,服务器便开始处理请求,一般会有专门处理业务请求的一个业务层,有的体现为rpc协议的微服务,有的体现为简单的一个程式码分层。最终请求的资料会通过查询数据库来返回。其实这个过程和车站购票流程一样,每个视窗的处理能力是有限的,对应到服务器处理能力。由于这个原因,所以诞生了负载均衡的策略,核心思想就是:分。一台服务器不够,那就两台,三台,四台..... 直到并发的所有请求的响应时间都在可控范围之内。
数据库的情况类似,一个数据库扛不住压力,就加到N个数据库分散压力。一个表扛不住压力,就把这个表拆分开,拆分成多个表,甚至拆分到多个不同服务器数据库,这就是我们常用的拆表策略。有的时候在同一个数据库中进行表拆分,效能的提升并非最大化,因为一台服务器的磁盘IO是有上限的,就算拆成100个表,还是在同一个物理磁盘上,当然这样可缓解锁单表的情况。
现在有很多的场景采用NOsql代替关系型数据库来缩短响应时间,在正常情况下,由于关系型数据库的本身因素在特定场景下的读写速度比Nosql要慢很多,所以系统设计初期,可以考虑采用关系型数据库和Nosql混用的方案。
快取
当并发的请求到达一定程度,瓶颈大部分情况下发生在DB层面,甚至DB无论怎么优化总有上限。为了避免频繁查询数据库产生瓶颈,诞生了快取。在访问数据库之前加入了快取层,当然这里的快取采用的方案在资料的响应时间上要比数据库小很多,比如常用的redis,Memcache,但是这些第三方的快取元件还是要走网络,比起程序内的快取还是要慢的多。
现在一般流行的设计在网站层和服务层都有快取策略,只不过快取的资料和策略有所不同,但是最终目的都是为了加快请求的响应。当然加了快取之后,资料的一致性需要仔细设计才可以,如果发生资料不一致的情况,程序员可能要背锅了。
缓解数据库压力并不是引入快取的唯一因素。
CDN加速
一些小厂可能用不到cdn,但是cdn带来的加速还是很客观的。cdn依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、排程等功能模组,使使用者就近获取所需内容,降低网络拥塞,提高使用者访问响应速度和命中率。CDN就是把离使用者最近的资料返回给使用者。
