压测标准和接口

1、注意事项

★禁止跳过预发布环境压测直接在正式环境压测
★所有预发布环境和正式环境的压测禁止在交易日的6:00~16:30进行
★必须保证压测不能导致正式环境服务处于不可用状态,包括下游服务(压测过程中可以处于短时间高负载状态,但压测结束后必须恢复)
★压测前请使用本文末尾处给到的压测报告模板先创建压测报告,并且完成依赖服务的checklist才能开始压测

2、流程概述

此处省略部分细节,介绍压测流程,提供给已了解细节的人快速进行压测。强烈建议首次进行压测者详细阅读全文

注意最大qps和预期qps的区别

估算预期qps
准备数据,单一请求/固定值枚举随机/线上流量
测试环境80.188压测:
不求找到瓶颈,只为排查比较明显的程序问题,由于测试环境性能有限,可以将部分低性能依赖mock掉
这一步可以这样压:wrk -t8 c200 d60s --latency -H “Host: h o s t " − − l a t e n c y " {host}" --latency " host"latency"{url}”
预发布环境200.118压测:
这一步要指定qps分步多次压(使用wrk2指定qps):wrk2 -t8 c100 d60s -R 1000 -s access.log --latency -H “Host: h o s t " − − l a t e n c y " {host}" --latency " host"latency"{url}”
随后每次将qps增加一定数值比如500,重复压测,直到达不到指定的qps,认为找到了最大qps,然后以最大qps进行长时间压测
分析这十分钟的监控数据,排查各方面瓶颈并解决问题,具体参考【指南】如何压测#压测瓶颈排查
反复进行以上步骤直到没有问题,并保证最大qps大于1.5倍预期qps
完成预发布环境压测报告,主要体现遇到的问题、最大qps、长时间压测的各项监控图,逐渐增加qps的反复压测过程可以不一一记录
根据预发布压测结果调整正式环境资源和副本数
正式环境200.118压测:
和预发布环境一样逐渐升高qps,最后以预期qps对正式环境进行长时间压测,观察服务状态和监控指标是否正常
若出现异常第一时间停止压测并恢复服务,排查预发布和正式压测表现不一致原因,修复后重新压测
完成正式环境压测报告,主要体现长时间压测的各项监控图

3、适用范围

不修改数据,需要确认服务性能瓶颈、进行性能优化的GET请求。

POST请求等需要修改数据的,涉及的内容较多,难度较大,需要全链路压测平台提供相关功能,本文不作考虑。

4、确定压测目标

探测性能瓶颈,验证架构能力,主要体现在qps峰值上
老业务重构:需要确认老业务qps峰值,一般情况下重构后qps应该至少大于老业务qps,如果重构有新的TPC目标,那么需要以新TPC的增幅为参考,估算重构后的qps峰值

新业务上线:预估qps峰值,主要靠产品提供的当前场景PV、UV,当前场景下其他业务的qps作为参考,计算出预估qps峰值

排查问题
代码问题
配置问题
资源申请不合理
可用性
性能到达瓶颈后,系统是否还可用
流量恢复正常后,系统是否恢复正常

5、梳理系统架构

接入sentinel,在sentinel dashboard中可以在簇点链路界面看到所有sentinel资源,其中大部分的主流框架,例如 Web Servlet、Dubbo、Spring Cloud、gRPC、Spring WebFlux、Reactor的依赖都是默认做了适配的;redis等其他资源需要在代码中使用@SentinelResource自定义
接入skywalking,在拓扑图界面可以看到直接和间接的依赖服务
大中台控制台可以查看边车监控指标,其中包括所有通过边车接入的TCP和HTTP的依赖
梳理完之后需要告知依赖方并确认以下几点:
可压测的时间段
可以接受的最大qps,如果可接受的qps不足以支撑自己的预估qps峰值,需要做好限流
压测可能造成的影响以及处理方案

6、准备压测数据和脚本

不同场景下需要准备的数据不同

若接口是单一请求,可以不需要准备数据,压测时指定好基本参数即可
若接口参数是少量或者固定的一些参数,并且随机分布,准备好参数的全部枚举值即可
例:https://news.10jqka.com.cn/app/theme/v1/theme?themeId=TZ-702,这个接口的参数只有主题ID,所有主题ID大概700+个,可以枚举出来,放在文件中,供wrk使用。例:theme.txt
接口参数是大量、不固定的一些参数,或者不随机分布,有冷热之分,需要准备线上真实流量
若是新上业务,没有真实流量,可以通过先进行公测来获取线上少量流量再进行放大,公测环境搭建可以参考wifi公测环境搭建
线上流量的获取,资讯部门的业务直接找 汪先红,一般要求工作日上午9:30~9:45早高峰的数据,可以让运维直接传到压测机器上,需要注意日志文件不要过大,以免影响压测机器
压测脚本使用lua实现,大概原理是wrk每次执行一个请求都会调用一次request函数,所以只要在request函数里传入读取文件的一行,做一下解析,替换掉path等参数即可。这里给出两个压测脚本的demo,若有问题可以找 陈雪涛

分时压测脚本demo,demo中解析了线上nginx的access.log。

--环境(prod/test)
env = "prod"
--access.log文件名
file_name = "0930_timeline.log"
--access.log的参数个数,正式环境18个,测试环境20个
--access.log中各个参数的位置,正式环境分别为1,2,13,16,测试环境分别为2,3,14,17
if(env == "prod") then
	accesslog_size = 18
	request_index = 4
	host_index = 13
	port_index = 16
elseif(env == "test") then
	accesslog_size = 20
	request_index = 5
	host_index = 14
	port_index = 17
else
	return
end


setup = function(thread)
end

f = io.open(file_name,"r")
init = function(args)
end

delay = function()
end

request = function()
	local line = f:read()
	if(line == nill or line == "") then
		return
	end

	return get_request(line)
end

response = function(status,headers,body)
end

done = function(summary, latency, requests)
end

function string:split()
	local splits = {}
	--解析access.log中[]中的内容
       	for str in string.gmatch(string.gsub(self,"\n",""), '%[[%s%S]-%]') do
               	table.insert(splits, string.sub(str,2,-2))
       	end
	return splits
end

function string:split2()
    	local splits = {}
	--分割空格
        for str in string.gmatch(self, '[^%s]+') do
                table.insert(splits, str)
        end
	return splits
end

function get_request(line)
    	local t = string.split(line)

	if t == nil or table.getn(t) < accesslog_size then
        	return
    	end
	local temp = string.split2(t[request_index])
	wrk.method = temp[1]
	wrk.path = temp[2]
	wrk.host = t[host_index]
	wrk.port = t[port_index]
	return wrk.format()
end

主题压测脚本demo,demo中解析了主题id的枚举值theme.txt


file_name = "theme.txt"
local themes = {}

setup = function(thread)
end

init = function(args)
        f = io.open(file_name,"r")
        local line = f:read()
        while(line~=nil)
        do
                table.insert(themes,line)
                line = f:read()
        end
end

delay = function()
end

request = function()

        return get_request()
end

response = function(status,headers,body)
end

done = function(summary, latency, requests)
end

function get_request()
        local theme = themes[math.random(1,#themes)]

        wrk.path = "/app/theme/v1/theme?themeId=" .. theme

        return wrk.format()
end

7、施压机器和压测环境

测试环境:10.10.80.188
预发布环境:192.168.230.86 通过docker,例:docker run --rm -v pwd:/data williamyeh/wrk -t8 -c200 -d3s -s accesslog.lua -H “Host: h o s t " − − l a t e n c y " h t t p : / / {host}" --latency "http:// host"latency"http://{ip}😒{port}”
正式环境:192.168.200.118
我们在压测前需要明确,最终压测报告必须已正式环境压测报告为准,测试环境的压测是为了帮助我们排查一些比较明显的代码或者配置上的问题,预发布环境的压测是为了帮助我们找到系统的瓶颈、各组件参数配置的最佳值等以及发布到正式之前的可靠性验证。

8、使用wrk

-t:线程数,等于当前机器的cpu核数,避免线程切换,保持不变。可以通过以下命令查看机器CPU核数

cat /proc/cpuinfo| grep “processor”| wc -l

-c:总连接数,逐步调大,找到qps极限值,可以以100为基准,每次加50
-d:持续时间
-s:使用lua脚本
–latency:打印压测响应时间结果
大概qps = 1000/r * c (r是理想情况的平均响应时间)

9、压测过程

根据机器cpu总核数确定t参数
将c逐渐调大,d不变,可以设为1分钟,当发现调大c时qps不再增长,认为找到了临界点cmax
将c设为1.5cmax,增大d,一般需要10分钟以上,再次进行压测,观察系统是否崩溃,以及压测完之后系统是否恢复正常
单台机器进行压测时需要关注该机器cpu占用率,如果cpu占用率达到100%,并且qps已经很高了但没法再上升,同时服务各指标还没有瓶颈,可能是施压机制约了压测qps,目前由于施压机比较少,所以这个问题暂时不好解决。可以通过对单副本压测再预估总qps来作为临时解决方案

10、压测瓶颈排查

CPU:使用量占比超过80%,被限制的时间不为0,说明CPU接近打满或者已经打满,可通过以下方式排查
分析火焰图,找出直观上占用cpu高的方法,即业务代码中最宽的那一段。按照经验,最有可能出问题的就是各种json序列化反序列化/反射代码,包括各种beanutil.copy方法
联系运维或直接在运维处操作,使用jstack等命令直接查看异常线程,死锁等
gc是否异常,有可能是代码问题或者因为内存大小设置不合理导致gc频繁回收/回收时间长。首先查看内存大小设置,垃圾收集器设置,排除是内存的问题后,用jmap等命令输出dump文件,找到占用最多空间的对象并定位到代码
内存:内存不含cache使用量持续增长直至100%或接近100%,说明内存可能有泄露或者内存设置不够大
正常情况下内存不含cache使用量会缓慢增长,直到老年代第一次GC后,不再增长,如果还在持续增长,可能是老年代回收有问题
fullGC几个小时进行一次是可以接受的,理想状况是几天甚至一周进行一次。如果频率较高,有可能是老年代太小,也有可能是年轻代太小(大量对象放不下直接进入老年代)
youngGC平均时长最好在100ms以内,如果不能满足,考虑使用G1收集器
IO:通过观察IO吞吐量和每秒读取/写入次数,一般来说除非有频繁读写磁盘的业务,IO不会是瓶颈
网络:通过观察网络流量总字节数,若查询参数或者返回结果较大时需要关注,特别是返回列表的业务,还需要关注一下物理机状态,如果是千兆网卡的物理机,Network Packets/sec超过120会驱逐掉包量最多的副本,所以如果达到这个量了需要万兆网卡,这个可以在工作负载的调度策略里配置

依赖:有的情况下,压测qps上不去,其他指标都没什么异常,只有响应时间特别长,那么很有可能是依赖瓶颈
询问依赖方能承受多少并发,从而进行限流,防止高于预期的流量把依赖打挂
询问依赖方平均响应时间,一般使用P99作为基准,配置熔断策略,防止依赖服务出现性能问题影响到我们服务的性能
如果是有一致性要求的依赖,要做好超时、重试、告警手动处理的机制

11、压测报告

模板:【模板】压测报告模板
需要包含:压测环境、压测对象、压测数据、压测过程(监控截图)、压测结论
一个示例:【压测】修改CPU绑定后压测报告

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值