服务端性能详解

一,服务端的性能测试
1,性能测试是模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行的测试。
2,对服务器端应用程序开展性能测试,是为了验证软件系统是否能够达到预期的性能指标,同时发现软件系统中存在的性能瓶颈,从而实现优化系统的目的

二, 性能测试测试方法:
1,基准测试
就像传统的功能测试一样,基准测试的目的更多地是关注业务功能的正确性,或者说验证测试脚本的正确性,然后,将基准测试时采集得到的系统性能指标,作为基准测试结果,为后续并发压力测试的性能分析提供参考依据
2,负载测试
负载测试,主要指的是模拟系统在正常负载压力场景下,考察系统的性能指标。这里说的正常负载,主要是指用户对系统能承受的最大业务负载量的期望值,即预计系统最大应该支持多大用户的并发量。通过负载测试,目的是验证系统是否能满足预期的业务压力场景。
3,压力测试
压力测试是为了发现在多大并发压力下系统的性能会变得不可接受,或者出现性能拐点(崩溃)的情况。在加压策略上,压力测试会对被测系统逐步加压,在加压的过程中考察系统性能指标的走势情况,最终找出系统在出现性能拐点时的并发用户数,也就是系统支持的最大并发用户数。
4,疲劳强度测试
疲劳强度测试的加压策略跟负载测试也很接近,都是对系统模拟出系统能承受的最大业务负载量,差异在于,疲劳强度测试更关注系统在长时间运行情况下系统性能指标的变化情况,例如,系统在运行一段时间后,是否会出现事务处理失败、响应时间增长、业务吞吐量降低、CPU/内存资源增长等问题。

三,性能测试常用指标
业务性能指标可以直观地反映被测系统的实际性能状况,常用的指标项有:
并发用户数
事务吞吐率(TPS/RPS)
事务平均响应时间
事务成功率
系统资源性能指标,主要是反映整个系统环境的硬件资源使用情况,常用的指标包括:
服务器:CPU利用率、处理器队列长度、内存利用率、内存交换页面数、磁盘IO状态、网卡带宽使用情况等;
数据库:数据库连接数、数据库读写响应时长、数据库读写吞吐量等;
网络:网络吞吐量、网络带宽、网络缓冲池大小;
缓存(Redis):静态资源缓存命中率、动态数据缓存命中率、缓存吞吐量等;
测试设备(压力发生器):CPU利用率、处理器队列长度、内存利用率、内存交换页面数、磁盘IO状态、网卡带宽使用情况等。

四,性能测试工具基本组成
压力生成器(Virtual User Generator): 并发请求资源(就是请求)
结果采集器(Result Collector): 对每一个并发请求,进行记录结果(操作耗时错误进行监控和记录)
负载控制器(Controller): 协调控制,实现并发操作(发起请求)
系统资源监控器(Monitor): 被测系统的各项性能指标,对指标进行汇总、分析
结果分析器(Analysis): 请求各操作消耗的时长进行汇总,计算其平均值

五,locust 性能测试工具
1, LoadRunner和Jmeter这类采用进程和线程的测试工具,都很难在单机上模拟出较高的并发压力。而协程和线程的区别在于,协程避免了系统级资源调度,由此大幅提高了性能
2, Locust 的并发机制摒弃了进程和线程,采用协程(gevent)的机制,减少了线程切换消耗(IO的阻塞和线程的sleep会不可避免的导致并发效率下降)
3, Locust HTTP请求完全基于Requests ,功能强大。Locust也可以测试其它任意协议的系统,只需要采用Python调用对应的库进行
4,而对于其它协议类型的系统,Locust也提供了接口,只要我们能采用Python编写对应的请求客户端,就能方便地采用Locust实现压力测试。从这个角度来说,Locust可以用于压测任意类型的系统

六, Locust 常用业务场景编写
1, 基于 TaskSet, 适用 请求比例权重测试场景, 适用于 web 接口没有关联
from locust import  TaskSet, task, HttpUser, between


class UserTask(TaskSet):
    
    # 测试比例 权重,权重越高,请求测试越多
    @task(3)
    def readBook(self):
        print('I am reading a book.')

    @task(7)
    def listenMusic(self):
        print('I am listening to music.')

    @task(2)
    def logOut(self):
            # interrupt()方法的调用是非常重要的,这可以让一个用户跳出stay这个类有机会执行leave这个任务
        self.interrupt()

    @task(1)
    def leave(self):
        print('I don not like this page.')


class WebsiteUser(HttpUser):
    host = 'http://127.0.0.1'
    tasks = [UserTask]
    # 每个任务之间设置间隔时间,随机从3~5区间内取,单位是 s
    wait_time = between(0, 0)
    
# 不基于 web    
# locust -f 1.py --headless -u 100 -r 20  -t 3 --csv=example
View Code
  2, 基于SequentialTaskSet, 适用 接口之间有关联的测试,从上往下,没有权重概念,最后一个task 执行完就结束
from locust import  task, between, HttpUser,SequentialTaskSet

class UserTask(SequentialTaskSet):

    # 可以使用 curTime 实现 task之间传参
    curTime = None

    def on_start(self):
        # 测试启动 初始化
        pass

    @task
    def unlock(self):
        r = self.client.get("/14280110.html")
        # 成功失败的校验(测试报告基于此来判断 fails 个数)
        assert r.status_code == 200
        UserTask.curTime = 2
        print("当前函数 home_index {}".format(UserTask.curTime))
        # assert 200 == 200

    @task
    def getsession(self):
        r = self.client.get("/12129303.html")
        assert r.status_code == 200
        # 获取传参
        print("当前函数 sale {}".format(UserTask.curTime))


    def on_stop(self):
        '''销毁数据,每个虚拟用户只执行一次'''
        # self.client.post("https://www.baidu.com")
        pass


class WebsiteUser(HttpUser):
    host = 'https://www.cnblogs.com/shi-qi/articles'

    tasks = [UserTask]
    # 每个任务之间设置间隔时间,随机从3~5区间内取,单位是 s
    wait_time = between(0, 0)


# if __name__ == "__main__":
#     # -u 并发量 为 100  -r 指定并发加压速率  -t 脚本运行时间
#     os.system('locust -f 1.py --headless -u 100 -r 20 -t 120')



    #  locust -f 1.py --headless -u 100 -r 20  -t 3 --csv=example
View Code
   3,使用异步库进行压力测试
import json
import os
from locust import TaskSet, task
from locust.contrib.fasthttp import FastHttpUser



class UserTask(TaskSet):

    header = {'Content-Type': 'application/json'}

    def on_start(self):
        pass

    @task
    def unlock(self):
        self.data = {"id": 1, "jsonrpc": "2.0", "params": ["24h"], "method": "filscan.BaseFeeTrend"}
        self.data = json.dumps(self.data)
        r = self.client.post("/rpc/v1",self.data,headers = self.header)
        unlock_re = json.loads(r.text)
        # print(self.u)
        # assert unlock_re['code'] == "200"


    def on_stop(self):
        '''销毁数据,每个虚拟用户只执行一次'''
        # self.client.post("https://www.baidu.com")
        pass


class WebsiteUser(FastHttpUser):
    host = 'http://192.168.1.185:8889'

    tasks = [UserTask]
    # 每个任务之间设置间隔时间,随机从3~5区间内取,单位是 s
    # wait_time = between(0, 2)




if __name__ == "__main__":
    # -u 并发量 为 100  -r 指定并发加压速率  -t 脚本运行时间
    os.system('locust -f pressureMesurement.py --web-host="127.0.0.1"')


#  locust -f 1.py --headless -u 100 -r 20  -t 3 --csv=example


#  locust -f 1.py --headless -u 1 -r 1  -t 1 --csv=example



# locust -f 1.py --web-host="127.0.0.1"
View Code
七, Locust 常用指标解读
1,90% 90%的样本都没有超过这个时间。这个值是指把所有数据按由小到大将其排列,就是排列在第90%的值
2,Median:中位数。50%的样本都没有超过这个时间。这个值是指把所有数据按由小到大将其排列,就是排列在第50%的值
3,RPS:每秒请求数
4,Throughput: 吞吐量
八,Locust web 参数设置

Number of users to simulate:要负载的vuser数量
Hatch rate :每秒启动多少vuser
比如10个用户,你想每没5s增加1个vuser,Hatch rate就填0.2
九,locust 分布式搭建:

master 节点不充当压力机的作用
locust -f  pressure.py  --web-host 192.168.1.119  --web-port 8001 --master
worker节点
1,master 和每一台 worker 机器,在运行分布式测试时都必须要有 locust 的测试文件。
2,本次测试使用一台服务器启动一个master和三个 worker,每个处理器内核运行一个 worker
    locust -f pressure.py  --worker --master-host=192.168.1.119
    locust -f pressure.py --worker --master-host=192.168.1.119
    locust -f pressure.py --worker --master-host=192.168.1.119

posted @ 2021-01-16 16:00  十七楼的羊  阅读(432)  评论(0编辑  收藏  举报