服务性能指标:PV、UV、TPS、QPS
名词解释
PV
Page View,网页浏览量。网页被读者调用浏览的次数。网页每次打开或刷新一次页面,记录一次。用户对同一页面的多次访问,访问量累计。
UV
Unique Visitor,独立访问者。是指通过互联网访问、浏览这个网页的自然人。在一定时间内,访问网站的不同访客的数量,且每个访客只被统计一次。同一个客户端的电脑,00:00~24:00访问页面多次,只计算1次。例如,假设用户周三访问3次,周四访问1次,则周三记为1次PV,周四也记为1次PV。一般通过Cookies进行计算。
TPS
Transactions Per Second(每秒传输的事物处理个数),即服务器每秒处理的事务数。PS包括一条消息入和一条消息出,加上一次用户数据库访问。
QPS(或RPS Request Per Second)
Queries Per Second。每秒查询率。在规定时间内所处理流量多少的衡量标准。
对应fetches/sec,即每秒的响应请求数,也即是最大吞吐能力。
QPS = 并发数 / 平均响应时间
系统服务端性能影响的因素
衡量服务性能的指标,主要有两个:
- QPS(Query Per Second,每秒请求数)
- 响应时间(Response Time,RT),它可以理解为服务器处理响应的耗时。
正常情况下,响应时间越短,QPS则越高。在单线程的情况下,是呈线性关系。但也不是无限增长,RT总会有极限值。
多线程时,总QPS = (1000ms/ 响应时间)* 线程数。
响应时间与QPS的关系
对于Web系统,响应时间一般由CPU的处理时间和线程的等待时间组成。
通过减少线程的等待时间,对于系统的性能提升并不是很大。真正对性能有影响的是 CPU 的执行时间。
经过实际的测试,如果减少 CPU 一半的执行时间,就可以增加一倍的 QPS。
线程数对QPS的影响
根据公式 总QPS = (1000ms/ 响应时间)* 线程数
,直觉上,线程数增多QPS越高。实际上,线程数并不是越多越好。因为线程本身也占用资源,也受其他因素制约。例如,线程越多系统的线程切换成本就会越高,而且每个线程也都会耗费一定内存。(单线程语言,即使是在单台服务器上建立多个实例,也会受到服务器本身资源的限制。例如,nodeJS可以使用PM2,在一台服务器上启动多个线程,但是服务器本身资源的有限。)
如何设置合理的线程数
那么如何设置服务器上的线程数呢?通用公式如下:
线程数 = 2 * CPU核数 + 1
最佳实践的公式:
线程数 = [(线程等待时间 + 线程 CPU 时间) / 线程 CPU 时间] × CPU 数量
当然,最好的办法是通过性能测试发现系统的最佳线程数。
如何发现瓶颈
我们可以通过系统的监控工具,发现系统的性能瓶颈。通常会发生性能瓶颈的地方有CPU、内存、磁盘、网络、数据库等。
常见地,缓存系统容易发生瓶颈的地方是内存,储存型系统则是I/O。
如何简答判断CPU是否发生瓶颈了?我们可以观察,当 QPS 达到极限时,服务器的 CPU 使用率是不是超过了 95%,如果没有超过,那么表示 CPU 还有提升的空间。
性能优化的过程
- 发现短板。
- 减少数据。事实上,有两个地方特别影响性能。一是服务端在处理数据时不可避免地存在字符到字节的相互转化,二是 HTTP 请求时要做 Gzip 压缩,还有网络传输的耗时,这些都和数据大小密切相关。
- 数据分级。首屏数据、重要信息优先,次级信息异步加载。
- 减少中间环节。
附:性能测试指标
并发 | 响应时间 | 应用服务器cpu | 数据库服务器cpu | TPS |
---|---|---|---|---|
50 | 1s | 50% | 20% | 50 |
压测工具:stresstester
pom.xml文件引入包
<dependency> <groupId>com.taobao.stresstester</groupId> <artifactId>stresstester</artifactId> <version>1.0</version> </dependency>
编写测试代码:
/** * @Title: PressTest * @Description: 压力测试,测试一下获取用户信息的方法的qps * @param 参数 * @return void 返回类型 * @throws */ @Test public void PressTest(){ int concurrencyLevel =100;//并发数 int totalRequest = 1000;//总请求数 StressResult result = StressTestUtils.test(concurrencyLevel, totalRequest, new StressTask() { @Override public Object doTask() throws Exception { getUserDetail(); return “”; } }); System.out.println(StressTestUtils.format(result)); }
测试结果:
上图测试结果很明显有问题,做长的请求3秒多,这是不能接受的,通过分析,定位到连接池设置过小,数据库连接过小,并发过大,导致请求阻塞等待资源中,优化方式:加大连接池线程数,加大数据库连接数
资料:https://mp.weixin.qq.com/s/4pjydskyaBqyjk0TDNtSVA