# Web服务高并发与压测
# 高并发
高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。 高并发相关常用的一些指标有响应时间 RT(Response Time)、吞吐量(Throughput)、每秒查询率 QPS(Query Per Second)、每秒事务处理率 TPS (Transactions Per Second)、并发用户数等。
- 响应时间:系统对请求做出响应的时间。例如系统处理一个 HTTP 请求需要 200ms,这个 200ms 就是系统的响应时间。
- 吞吐量:单位时间内处理的请求数量。
- QPS:每秒响应请求数。在互联网领域,这个指标和吞吐量区分的没有这么明显。
- TPS: 每秒事务数,它是软件测试结果的测量单位。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。
- RT: 响应时间,执行一个请求从开始到最后收到响应数据所花费的总体时间,即从客户端发起请求到收到服务器响应结果的时间。
- 并发用户数:同时承载正常使用系统功能的用户数量。例如一个即时通讯系统,同时在线量一定程度上代表了系统的并发用户数。
从服务端视角看高并发服务端处理请求需要耗费服务端的资源,比如能同时开启的进程数、能同时运行的线程数、网络连接数、CPU、I/O、内存等,由于服务端资源是有限的,那么服务端能同时处理的请求也是有限的。
高并发问题的本质就是:资源的有限性
# 高并发带来的问题
服务端的处理和响应会越来越慢,甚至会丢弃部分请求不予处理,更严重的会导致服务端崩溃。高并发问题并不是互联网应用独有。
高并发问题的层面比如:前端请求、Web 服务器、Web 应用、数据库等。
# 优化高并发的基本思路
客户端处理的基本原则是能不访问服务端就不要访问
- 尽量减少请求数量,比如:依靠客户端自身的缓存或处理能力
- 尽量减少对服务端资源的不必要耗费,比如:重复使用某些资源,如连接池
服务端的处理基本原则是分而治之,并提高单个请求的处理速度
增加资源供给
- 更大的网络带宽
- 使用更高配置的服务器
- 使用高性能的 Web 服务器
- 使用高性能的数据库
请求分流
使用集群
分布式的系统架构
应用优化
- 使用更高效的编程语言
- 优化处理业务逻辑的算法
- 优化访问数据库的 SQL
# Web 压力测试
压力测试(Stress Test),也称为强度测试、负载测试,通过加压测试,确定一个系统的瓶颈或者应用不能服务的性能点,来获得应用系统能提供的最大的服务级别的测试。目的是验证软件是否符合客户需求,提高应用系统可用性,减少系统的宕机时间和因此带来的损失。最终产物是包括测试环境,方法和结果的测试报告。
通俗点说压力测试的目标,是搞死服务器,从而找到瓶颈点
# 测试工具
一款用 Node.js 编写的快速 HTTP / 1.1 基准测试工具。
npm install -g autocannon
使用方式
提供两种使用方式
- 命令行
autocannon -c 100 -d 5 -p 2 http://127.0.0.1:3000/test
简单快速 - api 调用
autocannon(opts[, cb])
便于编写脚本
关键参数有这么几个
-c/--connections NUM
并发连接的数量,默认 10-p/--pipelining NUM
每个连接的流水线请求请求数。默认 1-d/--duration SEC
执行的时间,单位秒-m/--method METHOD
请求类型 默认 GET-b/--body BODY
请求报文体
使用样例
# 第一步 启动服务
node server.js
# 第二步,运行压测命令
mrgaogang@mrgaogang-MB0 autocannon % `autocannon -c 100 -p 5 -d 10 http://127.0.0.1:3000`
# 生成的报告如下
Running 10s test @ http://127.0.0.1:3000
100 connections with 5 pipelining factor
┌─────────┬──────┬──────┬───────┬───────┬─────────┬─────────┬───────┐
│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │
├─────────┼──────┼──────┼───────┼───────┼─────────┼─────────┼───────┤
│ Latency │ 5 ms │ 6 ms │ 8 ms │ 11 ms │ 6.38 ms │ 1.85 ms │ 62 ms │
└─────────┴──────┴──────┴───────┴───────┴─────────┴─────────┴───────┘
┌───────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Req/Sec │ 58335 │ 58335 │ 73791 │ 75391 │ 72094.4 │ 4736.85 │ 58324 │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Bytes/Sec │ 6.48 MB │ 6.48 MB │ 8.19 MB │ 8.37 MB │ 8 MB │ 525 kB │ 6.47 MB │
└───────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘
Req/Bytes counts sampled once per second.
721k requests in 10.02s, 80 MB read
- Latency:接口的延迟程度
- Req/Sec: 每秒能处理的请求数 TPS
- Bytes/Sec: 每秒返回的字节数
# 方法一: 性能文件与分析
通过压测工具可帮助我们快速找到有问题的接口或方法(出现阻塞/内存泄漏),对接口或方法进行剖析并不可视化,可能很多时候需要一份性能报告,进行更好的剖析。
# V8 Profiler
V8 官方提供了Profiler 工具 (opens new window) 使用快速收集性能数据
- 生成报告
node --prof server.js // server.js 服务入口文件
在启动命令中加上
--prof
,在项目根目录会生成isolate-xxxxxxx-v8.log
格式的文件,用来记录运行期间的调用栈和时间等信息。- 分析报告
node --prof-process --preprocess isolate-xxxxxxxx-v8.log > v8.json
生成的 log 文件分析,生成报告包含六部分:Shared libraries、JavaScript、C++、Summary、C++ entry points 和 Bottom up (heavy) profile,JavaScript 部分列出了 JavaScript 代码执行所占用的 CPU ticks(CPU 时钟周期),C++ 部分列出了 C++ 代码执行所占用的 CPU ticks,Summary 列出了各个部分的占比,Bottom up 列出了所有 CPU 占用时间从大到小的函数及堆栈信息。
检查性能
文件的方式不直观,那我们换个 UI 界面的,步骤如下
- 先 clone v8 的仓库下来
git clone https://github.com/v8/v8.git
- 将日志文件转换成 json 格式
node --prof-process --preprocess isolate-xxxxxxxxxx-v8.log > v8.json
- 打开
v8/tools/profview/index.html
文件,是个静态界面,在界面中心选择刚生成的 v8.json 文件,文件解析成功后,界面如下
# 方法一: clinic
我们需要用一些方法去诊断我们的程序。一个很不错的诊断性能问题的工具便是 Node Clinic (opens new window)。它也可以用 npm 安装:
- 安装依赖
npm install -g clinic
- 运行压测检测命令:
clinic doctor -- node server.js # server.js为node入口文件
- 运行压测命令:
autocannon -c 100 -p 5 -d 10 http://127.0.0.1:3000
Running 10s test @ http://127.0.0.1:3000
效果如下:
# 参考
- 本文链接: https://mrgaogang.github.io/nodejs/Web%E6%9C%8D%E5%8A%A1%E9%AB%98%E5%B9%B6%E5%8F%91%E4%B8%8E%E5%8E%8B%E6%B5%8B.html
- 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 许可协议。转载请注明出处!