掘金 后端 ( ) • 2024-04-30 14:30

目标

在做性能压测之前,首先我们需要明白我们压测的目标是什么?是性能摸底? 还是测试是否满足设计指标,你可能会有疑问,这两个有什么不同吗?

性能摸底:测试机器最大处理能力,比如cpu已经超过80%,内存超过80%以及jvm的使用情况。

设计指标压测:只要压测的指标满足设计即可,不一定非得对容量进行摸底。

压测环境

硬件环境:

服务 配置 awardService 容器(单实例) 8C 16G mysql 容器(单实例) 4C 8G redis集群 架构:集群内存:6G 3分片;网络信息:最大连接30,000 个;最大网络吞吐 3456Mb/s

软件环境: jdk11、springboot

测试方法

在样本数量相同的前提下,观察不同的并发数所带来的指标的变化情况。

本次的样本是按照未来期望的百万用户的十分之一的(100000)数量进行尝试摸底,从而估算百万用户的情况。

测试工具

常用的三款工具ab,locust,jemter

ab - Apache HTTP server benchmarking tool - Apache HTTP Server Version 2.4 该工具非常轻量级,适合程序员,而且都是命令操作 使用起来非常简单

ab -B http -c 1000 -t 

刚开始我们用的是ab,觉得非常好用,但有个问题是不能传复杂的参数,当时解决的方案是通过修改代码来满足传参,但压测完需要把代码改回去,后来觉得麻烦,选择了下边的locust。

locust : python语言写的压测工具 Locust - A modern load testing framework

我们用locust库写了脚本来满足压测场景

from locust import FastHttpUser, task, TaskSet
import  random
import  json
class TaskTest(TaskSet):

    def assign(self,identifier):
        request_url="/api/v1/award"
        data ={
          "poolKey": "24523ced",
          "poolPwd": "xx232daaadv",
          "identifier": identifier
        }
        header = {"Content-Type": "application/json;charset=UTF-8"}
        response=self.client.request(method='POST', path=request_url, data=json.dumps(data), headers=header, name='抽奖', verify=False, allow_redirects=False)
        return response
 
    def receive(self,awardKey,awardPwd):
     receive_url="/api/v1/receive";
     data={
      "key": awardKey,
      "pwd": awardPwd
     }
     header = {"Content-Type": "application/json;charset=UTF-8"}
     response=self.client.request(method='POST', path=receive_url, data=json.dumps(data), headers=header, name='兑奖', verify=False, allow_redirects=False)
     return response

    @task
    def execute(self):
       identifer='identifer'+str(random.randint(0,10000000));
       response=self.assign(identifer)
       if(response.json().get('code')==200):
        response=self.receive(response.json().get('key'),response.json().get('pwd'))
       else:
        print('end')

class AwardMgt(FastHttpUser):
    host = 'http://127.0.0.1:8080'
    # 每次请求停顿时间
    tasks = [TaskTest]

刚开始我们使用的是HttpUser,但后来因为性能问题,我们把HttpUser换成了FastHttpUser, 据官网介绍FastHttpUser比HttpUser快很多,一秒钟可以启动5000个请求,HttpUser只能850个

但locust仍然有个问题: 由于python的全局锁,导致只能使用到机器的一个cpu,在压测场景中cpu很容易到100%

解决的方式:locust提供了分布式的压测方案,可以启动多个进程的方式,进程之间的全局锁不互相影响

启动多个locust进程

locust -f afast.py --worke #命令详看 locust --help 该命令会等待worker的启动 
locust -f afast.py -r 100.00 -t 5m -u 3000 --expect-workers 8 --master --headless

压测工具比较

工具 优点 缺点 适用场景 ab 小巧、简单、易上手 无法传参,没有图形界面 简单的http压测 locust 可以传参,功能更强大,可以启动多个进程压测 有一定的学习成本 复杂的场景压测,可以按照比例分配并发

关于jemter

在我过去的工作经历中,我接触到的第一款压测工具就是jemter,这次之所以没使用,因为上边的两款工具已经能满足我们的压测场景了,而且从使用上来讲比jemter更方便一些,但jemter是有图形界面的,这可能对初次使用的同学来说更友好一些。

压测结果

这是我们用Ab的压测结果

image.png

总结

有人说,压测是QA的事情,你说的没错,但我觉得研发也需要掌握基本的压测技能,一方面对自己写的东西随时摸底,心里有数,提前发现问题,另外不需要依赖QA的排期,你知道很多公司的QA资源是非常有限的,等QA的排期往往要等很久,包括很多大公司,因为大公司有研发和QA的人数比,大概是3:1。自己写的东西自己可以随时拿到结果,是不是很爽?