背景介绍
项目越做越大,用户量和请数量可能随时发生井喷,如果等到系统崩溃时再补救,损失可就大了,所以得想个办法提前预防。
想要预防,就得知道系统的哪个环比较节薄弱,顶不住压力,还要对系统的承受能力有个全面的评估,心里有底,好提前预防,这种评估分析预防优化等一系列手段全被性能测试涵盖在内。
性能的指标
不同角色对性能的理解不尽相同,对于用户来说,操作流不流畅就是性能,对于研发人员来说,接口慢不慢和顶不顶得住并发就是性能,对于运维人员来说,网络带宽大小和资源占用高低就是性能。
那就必要统一性能指标了,首先,用户与研发人员都关注速度,实际上是接口的处理速度,再细一些是客户端发起请求到收到服务端返回的时间,那就把这个指标定为响应时间吧。
我们做一款产品最需要的就是用户,用户越多越好,但随着用户量地增加,同时发起操作的用户也越来越多,一时之间服务器可能要处理上万的请求,在这同一时刻处理的请求数就叫做并发数,不知何时起,处理过高并发的人成为了大家眼中的瑰宝,而并发数也成为了产品做大做强的标志,所以并发数也要列入性能的指标。
并发数只能代表同时请求的数量很多,但并没有赋予太多含义,与他人谈论时也无法让人整体把握系统的概况,所以需要将并发数进行变种以应对不同业务不同场景的描述,比如一天有多少人访问,一个小时能处理多少业务,每秒处理的事务数(TPS),每秒HTTP的请求数(HPS),每秒查询数(QPS)等等,这个指标我们为其命名为吞吐量。
除此之外,还要满足运维人员的要求,他们需要根据系统负载、内存占用、CPU占用、网络磁盘I/O等各项指标进行分析,以便于为扩容做准备,这种一系列的硬件指标我们统称为性能计数器。
简单说明一下系统负载,它是指CPU当前正在执行的与等待执行的进程数总和,该数量可以体现出系统是否繁忙,我们最希望看到的是没有进程排队等候,所以最理想的负载数量就是CPU的数量。
四种测试类型
我们在开发时会对系统的性能有个初步的预期,然后通过模拟请求程序逐步加大请求压力,直到你认为服务器资源的消耗已经无法接受了,此时再观察系统性能是否达到了预期,这种方式就是性能测试。注意,名称虽与上述重复但不是一个概念。
我们继续加大请求压力,直到服务器的某个资源已经达到饱和了,或者性能计数器中的某个指标达到了安全临界值,简单地说,再请求下去,系统的处理能力不但不能提高,反而会下降了。这种测试方式叫做负载测试。
还可以继续加大压力,不去管资源和性能指标如何,就疯狂请求,不停地请求,直到服务器崩溃,不能再继续工作了,这个时候就测出了系统最大承受能力,而这种测试方式被称为压力测试。
没办法再继续施压了,因为服务器已经没有响应,那就模拟一些比较真实的场景吧,因为真实场景下的请求压力是不均匀的,我们可以在特定环境、硬件和时间下给系统一定压力,看看业务是否能稳定运行,这种测试方式叫做稳定性测试。
优化手段
因为一个完整的WEB请求包含前端和后端两个部分,优化手段也从这两部分出发。
WEB前端优化
减少请求。现在大部分请求使用的是HTTP1,每个图片、脚本以及样式等资源的获取都要客户端单独跑线程建立连接,资源过多时消耗会很大,可以将不同类型的资源各整合至一个文件,这样少量的请求就能拿到需要的数据。
浏览器缓存。因为图片、脚本、样式等资源使用频率很低,没有必要每次请求都重新下载,可以通过设置HTTP的头部信息将资源缓存起来,这样可以有效降低加载速度,被缓存的资源需要更新时,可以通过修改资源文件名称的方式让浏览器重新下载。
压缩。图片、脚本、样式等静态资源一般都比较大,服务端可以将资源文件进行压缩,压缩后的文件较小,下载速度也会变快,但是前后解压缩文件会造成一定的压力,所以压缩手段要视业务情况而定。
CSS与JS顺序。因为浏览器会加载完所有的CSS后才去渲染页面,所以应该将样式文件放在上面加载。而JS刚好相反,浏览器刚加载完JS就会执行,如果放在前面会出现页面卡顿的现象,所以脚本文件应该放到页面最后加载。
CDN加速。原理与浏览器缓存类似,可以通过运营商将样式、脚本、图片等资源文件缓存到离用户最近的节点上,这样用户在发起请求时就能直接在最近的节点上找到需要的静态资源。
反向代理。在客户端与要交互的那台真实服务器中间再加一台服务器,所有的请求都由这台机器转发,当客户端第一次请求资源时将资源缓存到反向代理服务器,其他客户端就可以直接在反向代理服务器拿到资源,节省了转发的时间。
服务端优化
缓存。与前端一样,缓存是性能优化考虑的第一要素,目前流行的NoSQL数据库都是在内存读取的,速度会快,可以将读写频率很高但很少发生变化的数据放入缓存,可以有效提升系统吞吐量。
异步。像日志记录这种一定要去做但不需要等它做完的逻辑,应该把它放到消息队列当中,再由消费者进程逐条读取消息队列中的数据,慢慢执行,就像医院的排队取号,可以有效解决瞬时并发较大的业务场景。
集群。因为单台机器的处理能力有限,如果并发请求量过大,可能无法承受,可以加一些机器分担其压力,使得请求平均分配到每台机器上,这些由相同功能组成的机器群就是集群。
优化代码。不能秉着技术不够机器来凑的原则,回到实际代码当中来,多数性能问题还是代码写的不够优秀,比如三条语句能搞定的数据,查了十多条,几十行代码算出的变量,却没有地方使用,用不到的数据表联了又联等。