0%

说明

  • 本次混合场景为单个线程组
  • 结合if控制器,计数器,循环控制器
  • jmeter v5.4.1
  • 自己搭建的jforum
  • 场景为:登录20:浏览帖子:40:回帖:15:发帖10,比例为:5:8:3:2

设置线程组

  • 每秒钟并发两个登录请求,循环10次,也就是共发20次登录

image-20211102180619354

  • 参数化数据设置,注意的是线程共享模式

    • 所有线程,默认选项,表示按照顺序执行,不会出现多次登录使用同一个用户,《全栈性能测试修炼宝典JMeter实战》书中作者,自己实现此功能,可能是书中用的jmeter版本比较老,新版本已经有了此功能
    • 当前线程,在这种情况下,每个用户都会从头到尾读取 CSV 文件。
    • 当前线程组,每个文件由每个线程组单独打开(不要与每个线程单独读取文件的“当前线程”混淆。这基本上意味着每个线程组中的每个线程从头到尾读取 CSV 文件,互不影响。要实际展示这种共享模式,您需要再创建一个线程组。
    • 更详细说明请参考这篇文章

    image-20211103094204881

  • 新增了一个登录计数器

    image-20211103095147850

登录简单控制器

  • 登录成功后把模块id提出来

image-20211103095319643

进入板块的if控制器

  • 按照每登录4次的比例对帖子进行操作

    image-20211103095436383

浏览帖子循环控制器

  • 循环8次,刚好为共浏览5*8=40次,提取帖子id,最后进入到帖子详情

image-20211103095727165

回复帖子循环控制器

  • 循环次数为3次,共发送3*5=15

image-20211103100141261

发帖循环控制器

  • 循环2次,共发送2*5=10

image-20211103100343560

查看运行结果

  • 发送的请求数量刚好对上

image-20211103100519007

补充

  • 今天在测试过程中,发现这样的脚本用问题,直接多次回帖和发帖子虽然请求成功了,但是没有插入数据库,用抓包的方式也是如此

  • 后续经过测试,要改成这样的流程,不能单独循环发帖/回帖:

    • 发帖:进入板块,选择发帖按钮,发送发帖请求
    • 回帖:进入板块,选择帖子,点击回复帖子,发送回帖请求

    image-20211111175757903

说明

  • 本次实践是基于win虚拟机分布式压测
  • 被压测网站是我自己搭建的jform论坛

为什么要压测

  • 需要使用jmeter模拟大并发的情况时,单台压测机不能满足需求,可进行分布式压测。
  • 简单来说就是,多台机器同时安装jmeter,选择一台机器作为调度机,其他作为压力机。进行相应的配置后,就可以用调度机操控压力机发起请求。

安装虚拟机

  • 官方下载工具

    image-20211029180146221

  • 打开后下载ios文件到本地

安装过程报错

  • 出现一个类似错误

image-20211029180545713

  • 解决办法是禁用Hyper-V,以管理员权限打开 CMD 或 Windows PowerShell ,输入如下命令,然后重启电脑
1
bcdedit /set hypervisorlaunchtype off

网络设置

  • 再虚拟机可以ping通主机的ip,再主机却无法ping通虚拟机ip
  • 经过排查,发现虚拟机ip和主机ip的前面三个网段对不上,VirtualBox设置下虚拟机的网络方式为桥接网卡,就可以了

image-20211029163300356

压力机(master控制机)

  • 我装好的win10虚拟机
  • 执行当前压力机下jmeter安装包bin目录下的jmeter-server的批处理文件,此时该机器上启动一个java进程,并随机分配端口,监听来自调度机的请求。
  • 配置固定端口:打开bin目录下的jmeter.properties文件,更改server_portserver.rmi.localport的端口为要配置的端口。

image-20211029173427158

  • 第一个ip为本机ip,也可以作为负载机使用

  • 把下面的选项打开设置为true

    image-20211029173713156

调度机(slave负载机)

  • 真实机器
  • 打开jmeter安装包bin目录下的jmeter.properties文件,更改remote_hosts为压力机本机ip及执行jmeter-server后启动的端口。

image-20211029173856668

  • 把下面的选项打开设置为true,和master控制机一样

image-20211029173713156

keystore配置

  • 这样一来算是配置完成了接下来因为jmeter4.0版本及以上时,为了安全 分布式压测需要一个密匙才能正常实现 打开控制机的bin目录运行create-rmi-keystore.bat,用notepad++打开文件 复制这个命令,使用管理员运行

    image-20211029174237855

  • 执行完后,会出现一个rmi_keystore.jks文件,把这个文件放到master和slave中的jmeter/bin目录中

运行

  • 运行控制机jmeter.bat
  • 运行负载机jmeter-server.bat

image-20211029174523893

  • 控制机jmeter.bat ,打开脚本,运行中看到了两个远程启动的地址,点击运行中的远程启动所有,就能看到jmeter-server.bat中日志出现(图片如上)starting(开始发请求)和finished(发送请求结束),但是我这里的虚拟机一直只有starting的日志,没有finished的日志,造成监控到的请求没有成功,可能是我的笔记本配置太差引起的,后续有条件用真机测试

image-20211029174949327

其他

说明

  • 为了模拟分布式性能压测,本地搭建虚拟机达到模拟的方式
  • 本机为win10

image-20211029110605615

下载win10 ios镜像

  • 使用官网的下载地址

    image-20211029110819907

  • 打开工具选择ios文件即可,我一开始使用我之前存的ios文件一直安装不成功

    image-20211029111449747

下载Oracle VM VirtualBox

  • 我的版本为6.1

  • 安装步骤省略,再按照过程中出现弹框报错信息,里面包含类似于下面的错误

    image-20211029111956127

    • 解决办法是禁用Hyper-V。以管理员权限打开 CMD 或 Windows PowerShell ,输入如下命令:bcdedit /set hypervisorlaunchtype off再重启电脑
  • 启动虚拟机进行安装win10

image-20211029112134604

安装增强功能

  • 安装次功能主要是为了方便虚拟机使用宿主机的共享文件夹

  • 进入系统后我们点击VirtualBox菜单栏“设备”—-“安装增强功能”。

image-20211029152348003

  • 然后进入VirtualBox虚拟系统的“我的电脑”找到光驱

image-20211029152501476

  • 选择好对应的安装程序,打开开始安装

    image-20211029152536763

说明

  • 本次用jmeter进行登录并发的压测实例
  • jmeter version 5.4.1
  • 压测平台是自己搭建的jform
  • 压测机器为单机win

20个并发登录

设置线程组

  • 1秒钟发20个线程

image-20211027161520958

参数化登录数据

  • 下图为参数化设置,文件名使用相对路径,指向%JMETER_HOME%上一级目录,比如我放到的是D:\exe\apache-jmeter-5.4.1

    image-20211027161648791

  • 参数化格式为

1
2
3
4
5
6
test1008,123456
test1009,123456
test1010,123456
test1011,123456
test1012,123456
test1013,123456

登录接口

image-20211027162309389

运行

  • 运行成功后,查看测试报告

    image-20211027162426589

服务器监控

  • 下载ServerAgent-2.2.3,放到服务器上,给其他插件提供性能指标数据

  • 下载jpgc,监控cpu,men等

    image-20211027162740355

    • 解压后把perfmon-2.2.2.jar放到D:\exe\apache-jmeter-5.4.1\lib\ext目录下面
  • 重启jmeter,新增监听器可以看到PerfMon插件

    image-20211027163542732

  • 新增监控指标

    • CPU:combined : 综合CPU使用情况

    • Memory:usedperc:内存使用比例

    • DIsk IO:usedperc:磁盘IO占用比例

    • Swap:分区通常被称为交换分区,这块儿分区位于硬盘的某个位置,当系统内存(物理内存)不够用的时候,如果开启了交换分区,部分内存里面暂时不用的数据就会Swap out(换出)到这块儿分区;当系统要使用这部分数据的时候,存储在Swap分区的数据就会Swap in(换入)到内存当中。

      简而言之,Swap分区就类似于内存的后备内存(只是做了下缓冲)

image-20211027163910713

设置ServerAgent

  • 把压缩包放在服务器(centos7)上后,解压
1
2
3
4
5
6
7
8
9
10
11
12
[root@racknerd-4dbd89 local]# tar -zxvf ServerAgent-2.2.3.tar.gz
ServerAgent-2.2.3/
ServerAgent-2.2.3/CMDRunner.jar
ServerAgent-2.2.3/lib/
ServerAgent-2.2.3/lib/avalon-framework-4.1.5.jar
ServerAgent-2.2.3/lib/cmdrunner-1.0.2.jar
ServerAgent-2.2.3/lib/jorphan-2.6.jar
ServerAgent-2.2.3/lib/libsigar-amd64-freebsd-6.so
ServerAgent-2.2.3/lib/libsigar-amd64-linux.so
ServerAgent-2.2.3/lib/libsigar-amd64-solaris.so
ServerAgent-2.2.3/lib/libsigar-ia64-hpux-11.sl
...
  • 启动发现4444端口被使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    [root@racknerd-4dbd89 ServerAgent-2.2.3]# sh startAgent.sh
    INFO 2021-10-27 04:55:56.640 [kg.apc.p] (): Binding UDP to 4444
    INFO 2021-10-27 04:55:57.767 [kg.apc.p] (): Binding TCP to 4444
    ERROR 2021-10-27 04:55:57.778 [kg.apc.p] (): Can't accept TCP connections
    java.net.BindException: Address already in use
    at sun.nio.ch.Net.bind0(Native Method)
    at sun.nio.ch.Net.bind(Net.java:438)
    at sun.nio.ch.Net.bind(Net.java:430)

  • 修改端口

1
2
3
4
5
[root@racknerd-4dbd89 ServerAgent-2.2.3]# java -jar ./CMDRunner.jar --tool PerfMonAgent --udp-port 7777 --tcp-port 7777
INFO 2021-10-27 04:57:38.028 [kg.apc.p] (): Binding UDP to 7777
INFO 2021-10-27 04:57:39.040 [kg.apc.p] (): Binding TCP to 7777
INFO 2021-10-27 04:57:39.048 [kg.apc.p] (): JP@GC Agent v2.2.3 started

  • jmeter这里也要修改端口为7777

    image-20211027164933790

再次运行

  • 发现启动后,监听器jpgc这里一直卡着,jmeter也一直卡死,用任务管理器结束任务后,查了下相关资料,说要设置文件名路径,我设置后依然如此

  • 等待漫长五分钟后,终于看到结果出现timed out提示

    image-20211027174053337

  • 想到应该是服务器端口没有开放,设置防火墙端口开放

    1
    2
    firewall-cmd --zone=public --add-port=7777/tcp --permanent
    firewall-cmd --relod
  • 重启服务器上的serverAgent

    1
    2
    3
    4
    5
    [root@racknerd-4dbd89 ServerAgent-2.2.3]# netstat -lnpt |grep 7777
    tcp6 0 0 :::7777 :::* LISTEN 23648/java
    [root@racknerd-4dbd89 ServerAgent-2.2.3]# kill -9 23648
    [root@racknerd-4dbd89 ServerAgent-2.2.3]# java -jar ./CMDRunner.jar --tool PerfMonAgent --udp-port 7777 --tcp-port 7777

  • 再次运行jmeter脚本后,查看到服务器这里已经连接上了

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    gent --udp-port 7777 --tcp-port 7777
    INFO 2021-10-27 05:22:24.028 [kg.apc.p] (): Binding UDP to 7777
    INFO 2021-10-27 05:22:25.036 [kg.apc.p] (): Binding TCP to 7777
    INFO 2021-10-27 05:22:25.070 [kg.apc.p] (): JP@GC Agent v2.2.3 started
    INFO 2021-10-27 05:23:06.182 [kg.apc.p] (): Accepting new TCP connection
    INFO 2021-10-27 05:23:06.194 [kg.apc.p] (): Yep, we received the 'test' command
    INFO 2021-10-27 05:23:27.425 [kg.apc.p] (): Starting measures: swap: memory:cpu:
    INFO 2021-10-27 05:23:30.179 [kg.apc.p] (): Client disconnected
    INFO 2021-10-27 05:26:35.347 [kg.apc.p] (): Accepting new TCP connection
    INFO 2021-10-27 05:26:39.514 [kg.apc.p] (): Closing TCP connection
    INFO 2021-10-27 05:31:26.064 [kg.apc.p] (): Accepting new TCP connection
    INFO 2021-10-27 05:31:26.067 [kg.apc.p] (): Yep, we received the 'test' command
    INFO 2021-10-27 05:31:26.274 [kg.apc.p] (): Starting measures: swap: memory:cpu: disks i/o:
    INFO 2021-10-27 05:31:28.823 [kg.apc.p] (): Client disconnected

出现提示框

  • 再次运行是,出现一个弹框

    image-20211028103314940

  • 打开jmeter.properties设置resultcollector.action_if_file_exists=DELETE,如下图展示,action_if_file_exists有三个值ask,append,delete看字面意思就很清楚了。

  • 修改后重新打开jmeter,再次运行脚本就不会出现提示

    image-20211028103515713

查看测试报告

查看服务器的测试报告

image-20211027174638748

  • X 10000000表示放大的次数,助于观察

  • 查看cpu情况

    image-20211027174848666

image-20211027175002092

  • 我的服务器是单核cpu,配置比较差,直接就100%

  • 磁盘使用情况还不错

    image-20211027175148394

  • 其他情况就不分析了,类似

查看其他监听报告
  • 汇总报告,单位为ms

image-20211028105143043

  • 聚合测试报告,单位为ms,其中Throughput(吞吐量)——默认情况下表示每秒完成的请求数(Request per Second),当使用了 Transaction Controller 时,也可以表示类似 LoadRunner Transaction per Second 数(该值越大越好,表示服务器处理能力越强。)

    image-20211028105302902

简单负载登录测试

  • 1秒钟增加2个线程,运行100次
  • 分别看20,40,60并发下的表现

并发20的线程组设置

image-20211028114406461

参数化

  • 沿用上述

集合点设置

image-20211028114550041

  • Number of Simulated Users to Group by:每次释放的线程数量。如果设置为0,等同于设置为线程租中的线程数量

  • Timeout in milliseconds:

    • 如果设置为0,Timer将会等待线程数达到了”Number of Simultaneous Users to Group”中设置的值才释放
    • 如果大于0,那么如果超过Timeout in milliseconds中设置的最大等待时间(毫秒为单位)后还没达到”Number of Simultaneous Users to Group”中设置的值,Timer将不再等待,释放已到达的线程。默认为0
  • 注意:如果设置Timeout in milliseconds为0,且线程数量无法达到”Number of Simultaneous Users to Group by”中设置的值,那么Test将无限等待,除非手动终止。

  • Synchronizing timer 仅作用于同一个JVM中的线程,所以,如果使用并发测试,确保”Number of Simultaneous Users to Group by”中设置的值不大于它所在线程组包含的用户数。

  • 备注:像聚合报告这类监听器最好少添加,一个线程组用一个足以。之所以建议少添加是因为这类组件非常消耗性能,容易对压测结果产生影响。

查看服务器报告

  • swap波动比较大

    image-20211028152612334

  • cpu再并发请求的时候直接100%

    image-20211028152720062

场景设计

  • 在建立测试模型时已经确定了测试的业务种类,场景设计是组织虚拟用户、组合业务种类到一个测试单元,根据测试模型与测试目标,整理出如表 11-11 所示测试场景。
  • 并发数的计算来源于这里

image-20211026103114157

image-20211026103138117

Sec_101 基准测试:

  • 主要用来验证测试环境、验证脚本正确性、得到系统的性能基准,为后续的测试执行提供参考。基准测试采用单业务场景、单用户的方式来执行脚本;执行时长视响应时间调整,测试结果采样样本尽量大(比如响应时间1秒,1000 个事务就需要运行 1000 秒以上;响应时间 200 毫秒,运行 600 秒就可以完成 3000 个事务的采样,600*1000/200=3000)。

Sec 102 配置测试:

  • 帮助分析系统相关性能配置,确保系统配置适合于当前性能需求,一般场景为混合场景(多个业务同时执行)。测试过程是一个实验过程,先是找出不合理配置,然后进行修改,最后进行验证;周而复始只到配置满足要求。

Sec 103 负载测试场景:

  • 负载测试的目的是帮助我们找出性能问题与风险,对系统进行定容定量,分析系统性能变化趋势;为系统优化、性能调整提供数据支撑。
  • 负载测试在执行时又分为单场景与混合场景;单场景有利于分析性能问题,因为排除了其他业务的干扰;混合场景更贴近于用户实际使用习惯,是一个综合的性能评估。建议读者先做单场景的性能执行工作,后做混合场景的执行工作。可以看到表 11-11 中的负载场景有多个不同负载量。

image-20211026104416276

  • 曲线是常见的性能变化趋势图,1这个点,通常就是我们估算的满足性能需求的点
  • 2这个点达到系统最大吞吐量,通常是系统拐点(之后性能变差)
  • 3这个点是系统已经过载吞吐量已经开始减小;负载测试原则上需要找出这3个点。在负载测试执行时找出这3个点还是比较麻烦的,常常会因为一些配置、程序问题而受到干扰;通常找出这3个点需要很多次的执行,所以测试执行也是一个耗时的工作。

Sec 104 稳定性测

  • 稳定性测试的目的是验证在当前软硬件环境下,长时间运行一定负载,确定系统在满足性能指标的前提下是否运行稳定,执行时采用混合场景。
  • 按惯例要求执行时间不低于 8 小时,在此我们计划运行 12 小时。稳定性测试原则上是时间越长越好,有些隐藏较深的诸如内存溢出的问题是需要长时间运行才能反映出来的。
  • 注:实例 Jforum 系统场景比较简单,直接把多个业务组织一起即可;实际工作中会遇到一些场景复杂的业务。比如 WMS (仓库管理系统)系统, WMS 中都会有盘点功能,此功能就不应该与日常功能混合在一起,因为盘点通常都是一月一次,所以组织场景时尽量要与实际业务情况一致。

场景实现

  • 基准测试很好实现,只要保证脚本能正常跑就可以了

配置测试

  • 运行多个线程组,实现配置测试

    image-20211026105457474

用户估算

  • 在实现场景之前先搞清楚业务关联关系(登录/浏览帖子/发新帖/回复帖子的比例为
    20:40:7:10),发帖与回帖时需要登录,回帖之前会浏览帖子,浏览帖子是可以不用登录的,发帖
    与回帖的并发数小于登录,所以有部分用户是登录后只浏览帖子。按20:40:7:10的比例来算,回
    帖用户10个,发新帖用户7个,回贴与发帖都需要登录,这样登录已经有17个用户,还需要3
    个用户,可以安排3个用户登录后浏览帖子,最后还需要27个浏览帖子的用户。27个用户的来
    源是40个测览用户减10个回帖用户(回帖前会登录及浏览帖子),再减3个登录后浏览的用户

线程组设置

JMeter线程组之Stepping Thread Group插件参数详情

如图11-49所示

  • This group will start 30 threads - 设置单台负载机,线程组启动的线程总数为30个

  • First,wait for n seconds - 启动第一个线程之前,需要等待1秒

  • Then start 10 threads - 设置最开始启动10个线程

  • Next,add 10 threads every 600 seconds ,using ramp-up 10 seconds - 每隔600秒(十分钟),在10秒内启动10个线程

  • Then hold load for 600 seconds - 单台负载机启动的线程总数达到30个,持续运行600秒

  • Finally,stop 5 threads every 1 seconds - 最后每隔1秒,停止5个线程数

回帖,发帖,浏览帖子Stepping Thread Group设置
  • 图11-49是回帖线程组设置,负载分3个阶段加载,分别是并发10个、20个、30个线程

    image-20211026110301084

  • 图11-50是发帖线程组设置,负载分3个阶段加载,分别是并发7个、14个、21个线程

    image-20211026110321179

  • 图11-51是浏览帖子线程组设置,负载分3个阶段加载,分别是并发27个、54个、81个线程。

    image-20211026110338721

此方式优势:
  • 3个线程组互不干扰,独立设置(3个线程组的并发用户之和刚好与只运行一个线程组的
    场景相等),简单明了,易于维护。
此方式劣势
  • 由于3个线程组分开设置,相当于3个不同的脚本,所以参数化都需要分开,而且登录
    账号同样也不能有冲突,所以可以把用户的参数文件分成3份,每个线程组一份。虽然 JMeter
    也支持多个线程组共用一份参数文件,但是不能保证每个线程取到的参数唯一性。所以在此
    还是建议大家分开做参数化。

负载场景设计

  • 以只运行一个线程组为例来设置负载场景。图11-52是一个典型的负载场景,分3个阶段运行负载
  • 第一阶段只运行77个并发用户,运行10分钟。
  • 第二阶段再加上77个并发用户共计154个用户,运行10分钟。
  • 第二阶段再加上77个并发用户共计231个用户,运行10分钟。
  • 这种场景帮助我们来进行定容定量的测试,最终测试结果整理呈如图11-53所示。当然,测试执行过程中没有这么巧合,不是测试三个点就可以得到结果曲线,常常是不断的试验,

image-20211026113216382

本文抄录于《全栈性能测试修炼宝典JMeter实战》

说明

  • 环境介绍

    • jmeter 5.4
    • jforum 2.7
    • badboy 2.2
  • badboy录制了jforum:登录,打开主题,发布帖子

  • 回放过程中,发现无法发帖成功,按照书籍中把发帖请求,设置为跟随重定向,发现依然无法发帖成功

    image-20211021170752994

解决思路

  • 采用fiddler抓包发帖请求,发现出现了一个OWASP_CSRFTOKEN参数,和录制过来的参数不一致,是一个可变参数,并且尝试输入此参数用fiddler发包,也会造成发帖失败
  • 搜索到相应关键字,发现有人遇到同样问题,只要去掉tomcat下面的apache-tomcat-XX\webapps\jforum-2.5.0\WEB-INF\web.xml,所有关于csrf的验证去掉,然后再服务器上重启tomcat,就能正常发帖成功

说明

作为性能测试的压测目标网站,本次教程主要是在centos7上搭建iforum论坛的步骤

按照mysql

1
wget hhttps://repo.mysql.com//mysql80-community-release-el7-3.noarch.rpm
  • 安装MySql源
1
2
3
4
5
6
[root@racknerd-4dbd89 local]# rpm -ivh mysql80-community-release-el7-3.noarch.rpm
warning: mysql80-community-release-el7-3.noarch.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY
Preparing... ################################# [100%]
Updating / installing...
1:mysql80-community-release-el7-3 ################################# [100%]

  • 安装MySQL服务器
    yum install mysql-community-server

  • 开启mysql服务

1
service mysqld start
  • mysql安装成功后创建的超级用户‘root‘@’localhost’的密码会被存储在/var/log/mysqld.log,可以使用如下命令查看密码
1
grep 'temporary password' /var/log/mysqld.log
  • 输入 mysql -u root -p,输入得到的密码,然后修改密码:

    1
    ALTER USER 'root'@'localhost' IDENTIFIED BY 'new password';
  • 添加远程登录用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use mysql;
mysql> select host, user from user;
+-----------+------------------+
| host | user |
+-----------+------------------+
| localhost | mysql.infoschema |
| localhost | mysql.session |
| localhost | mysql.sys |
| localhost | root |
+-----------+------------------+
4 rows in set (0.01 sec)
# 查看表格中 root 用户的 host,默认应该显示的 localhost,只支持本地访问,不允许远程访问。

update user set host='%' where user ='root';
# 说明: % 代表任意的客户端,可替换成具体IP地址。
flush privileges;
  • 防火墙中开放mysql的访问端口
1
2
3
4
5
6
7
firewall-cmd --zone=public --add-port=3306/tcp --permanent
firewall-cmd --reload # 配置立即生效
firewall-cmd --zone=public --list-port # 查看防火墙所有开放的端口
firewall-cmd --state # 查看防火墙状态
netstat -lnpt # 查看监听的端口
netstat -lnpt |grep 3306 # 查看监听的具体端口

  • 用HeidiSQL远程连接mysql成功

    image-20211020114616786

  • 新建数据库,名字为:iforum

    image-20211020163450656

安装java

  • 我的服务器上已经按照好了java

    1
    2
    3
    4
    [root@racknerd-4dbd89 ~]# java -version
    java version "1.8.0_291"
    Java(TM) SE Runtime Environment (build 1.8.0_291-b10)
    Java HotSpot(TM) 64-Bit Server VM (build 25.291-b10, mixed mode)

安装tomcat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
wget https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.72/bin/apache-tomcat-8.5.72.tar.gz
tar zxvf apache-tomcat-8.5.72.tar.gz

# 启动tomcat
[root@racknerd-4dbd89 bin]# sh startup.sh
Using CATALINA_BASE: /usr/local/apache-tomcat-8.5.72
Using CATALINA_HOME: /usr/local/apache-tomcat-8.5.72
Using CATALINA_TMPDIR: /usr/local/apache-tomcat-8.5.72/temp
Using JRE_HOME: /usr/jdk1.8.0_291/jre
Using CLASSPATH: /usr/local/apache-tomcat-8.5.72/bin/bootstrap.jar:/usr/local/apache-tomcat-8.5.72/bin/tomcat-juli.jar
Using CATALINA_OPTS:
Tomcat started.


配置tomcat

  • 防火墙开发8080端口给tomcat
1
2
firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --reload
  • 已经可以访问

    image-20211020162109704

安装jforum

  • 打开地址并下载

  • 将 jforum-2.6.2.war放到tomcat目录的webapps下;

  • 重启tomcat,sh shutdown.sh sh startup.sh

  • 输入 host:8080/jforum-2.6.2 进入安装流程

    image-20211020165041066

    image-20211020165234244

image-20211020165311313

image-20211020171443069

新增批量用户

  • 新增存储过程,批量新增用户,密码都是123456

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    BEGIN
    DECLARE userName VARCHAR (20) ;
    DECLARE userMail VARCHAR (20) ;
    DECLARE i INT DEFAULT 9;#原来是1,要看jforum_users表最新一个用户的id是多少,要比最新那个用户id大就行
    WHILE i<= 400 DO
    set userName = CONCAT ('test1', LPAD ( i, 3, '0' )) ;
    set userMail = CONCAT (userName, '@test.com' ) ;
    #密码123456
    INSERT INTO jforum_users VALUES (i, '1', userName, 'e10adc3949ba59abbe56e057f20f883e', '0', '0',
    null, '2015-05-06 09:33:18', NULL, '0', '', NULL, '', '%d/%M/%Y %H:%i', '0', '0', null, NULL, '0', '1',
    '0', '1', '1', '1', '1', '1', '0', '0', '1', '1', '0', NULL, '0',userMail, null, null, null,
    null, null, null, null, null, null, null, null, null, null, null, NULL);
    INSERT INTO jforum_user_groups VALUES (2,i) ;
    SET i = i+1;
    END WHILE;
    END

image-20211111112111795

需求采集

  • 下面以JForum 论坛为例进行需求采集,首先要了解系统物理架构与逻辑架构。

  • 物理架构:指导进行测试环境建立,测试环境与生产环境的架构趋于一致。

  • 逻辑架构:让我们对系统的逻辑组成有所了解,进行测试时能够清楚地划分问题出现地区域。

系统架构

image-20211019170600141

  • WebServer 负责反向代理,静态请求处理;Tomcat7 负载动态请求处理;Mysql5.6 做双击热备

  • 为了更准确地模拟生产环境负载,在物理架构上尽量保持与生产同步,在机器配置及数量上,可以缩小比例,由测试环境来推算出生产环境的性能。(如何用测试环境准确估算到生产环境,参考TPC-E标准进行评测)

逻辑架构

image-20211019170654795

  • 逻辑架构:逻辑架构展现的是软件系统中元件之间的关系,比如用户界面、数据库、外部系统结构等。下图是应用服务的逻辑结构,列出了系统服务组件、邮件服务、权限管理、业务服务(对于JForum 就是发帖、回帖、浏览帖子)。Web层是通过 JSP 与 Velocity Freemark 来展现的。
  • 通过逻辑架构能迅速了解到系统的主要功能与服务,并且知道其逻辑关系,有助于我们设计测试场景

业务流程

  • 确定系统的主要业务流程,方便写性能测试用例。

image-20211019170922072

需求文档中性能需求说明:

  • 此论坛为一个技术讨论性质的论坛,注册用户规模预计是10万,每日活跃用户数预计为5%,即5000.

  • 用户在论坛中的活动以浏览、发帖及回帖为主,日 PV 预计为 2 万 PV。其中浏览、发帖、回帖比例大约为 7:1:2.

    • PV:用户每访问一个页面统计为一个PV。

     

  • 系统业务增长率为 30%,系统在 3年内不打算进行分库分表处理,需要系统在性能上能够支撑住,也就是测试时需要3年的存量数据。

  • 要求系统能够提供良好的系统体验,比如浏览帖子、发帖、回帖应该控制在3秒内。

  • 为了系统稳定,要求在日常营运时 CPU 使用率<70%,磁盘 Disk ime<70%且无网络瓶颈。

 

image-20211019171133583

硬件指标

  • 系统硬件指标对象是硬件资源,比如CPU、内存、磁盘、网络带宽等。下表列出了主要的性能指标及阈值,这些指标比较抽象,在监控分析时应该进一步细化;比如 CPU的性能指标在 Linux 中分为用户利用率、系统利用率及平均负载等重要指标。

image-20211019171302664

需求分析

  • 需求分析的目的是确定性能测试范围,分析出哪些业务纳入性能测试范围及性能指标是什么?另外要分析用户使用行为、业务分布、分析业务量;估算出 TPS与并发用户数等性能测试执行依据。

圈定测试范围

如何圈定测试范围?

  • (1)确定高频次的业务

  • (2)确定性能影响大的业务

  • (3)确定此功能的可验证性。比如使用支付宝来支付商品费用,如果余额不足,会引导选择使用银行卡来支付。这样支付宝会调用银行的接口来完成银行账户的扣减。银行的接口不提供支持时,需要模拟银行网关这个过程,这就是可验证性分析及解决方案,最终采用 Mock程序来配合测试。

明确性能指标

  • (1)吞吐量(PV、TPS):

     日 PV 是 2 万,3年 30%的增长,日 PV=2*(1+30%)² ≈3.38万

  • (2)响应时间:要求3秒以内

  • (3) 成功率:99%以上

  • (4)稳定波动正常范围

  • (5)其他各项硬件等性能指标。参照硬件指标

分析业务量

  • 测试数据的多少对测试结果会有影响,特别是数据成千万上亿条后,性能影响明显。

  • 性能测试时,除了需要做足一定数量的历史数据,还得关注业务量的增长。需求中年业务增长率 30%,可以理解成年 PV 也会增加 30%。所以测试时要以第3年的业务量为标准来测试,避免错过积累一定数据后性能变差的情况,把问题提前暴露出来。

计算 TPS

  • TPS:表示每秒平均事务数。即吞吐量。

  • 上面分析业务量的数据是以PV来统计的,要计算 TPS ,需要把 PV 转化成 TPS。一个 PV即是对服务器的一次请求,把一个请求放在一个事务中来统计服务器的响应耗时,响应完成即是一次事务完成,这么说一个 PV 即是一个事务(PV 并不能直接等同于 TPS,PV代表了一次客户请求,这次请求可能请求了很多信息,比如图片、样式、JS信息等,发新帖时我们通常只关心发帖的动作耗时,并不关心页面刷新时 JS、样式的耗时,此时就把 PV 等同于 TPS);比如一个功能页面(浏览帖子)一秒会有 10 个 PV,那么此功能的 TPS 即为10。

  • TPS一般要取系统业务高峰期的值,虽然系统不是总处在高峰期,但高峰期 TPS 才能代表系统的实际处理能力。要得到高峰期的 TPS 我们需要分析业务发生时间。

  • UV:一天之内网站独立访客数(以 Cookie 为依据),一天内同一访客多次访问网站只计算 1 个访客(小于等于 PV)。

  • 回到示例项目Jforum,找出日高峰。下表是高峰日 Jforum 论坛的 PV 数据统计(业务量单位为 PV)。

image-20211019171719859

  • 综合看上午十点是访问高峰,PV约为 5208(登录、浏览、回帖、发帖合计),那么这个时段 TPS=5208/3600≈1.45.

  • 这样取平均值是不合适的,一个小时间隔时间太长,采集的业务数据并没有说明在这一个小时中吞吐量是平均的,还需要细分。如果能细分到每分钟的业务量数量,那 TPS 的估算就越准确。

  • 可以采取 80/20 原则来估算,在性能测试中,20%的时间做了 80%的事情。

  • 80/20 原则计算 TPS = 5208*80% / (3600*20%) ≈ 5.8 ,具体如下表

    • 登录的tps=1300*0.8/720=1.4444

image-20211020172516176

  • tps还可以用来计算并发数

并发数计算

  • 三种估算方式:1.tps进行估算(我们采用这种) 2.由在线活动用户数估算 3.根据经验估算
  • TPS=事务数/时间,假设所有的事务都来自不同的用户,那么并发数=事务数=tps时间。
  • vu=tps*(runtime+thinktime)
    • vu表示此业务的虚拟用户数,即并发数
    • runtime是测试程序/脚本运行一次所消耗的时间,包含事务时间+非事务时间
    • thinktime是模拟用户思考或者填写表单消耗的时间;
  • 下图是发帖动作伪代码

image-20211019173149581

  • 根据公式我们计算一下 Vu,上面计算TPS 为5.8

  • 不包括非事务时间(ThinkTime 与程序消耗时间)情况下计算 VU;

    • Vu=TPS*T2=5.8*2=12
  • 包括非事务时间情况下计算 VU。

    • Vu=TPS*(Runtime+ThinkTime)=5.8*(0.2+2+0.2+0.2+0.2+2+0.2+2+2)=53
  • 可以看到两者之间的 Vu 数量相差巨大,如果我们不把 Runtime 与 ThinkTime 加进去,算出来的12个并发用户在测试执行时很有可能无法达到 TPS=5.8 的目标。

  • 业内一般把 Think Time 设为 3 秒,3 秒刚好符合用户在页面的停留平均时间。那么我们巴上面的 Think Time 时间换成3 秒。测试需求中要求响应时间小于3秒,那么我们以3秒为阀值。
    VU=TPS*(Runtime+ThinkTime)=5.8*(T1+TT1+T2+T3+T4+T5+TT2+T6+T7)=5.802+3+3+0.2+0.2+0.2+3+3+0.2)=76。

  • 由于我们计算并发数,取得是系统的tps(登录,浏览,发帖,回帖),实际计算出来的并发是系统业务的总并发数,如登录的并发数量1.44*13=18.72向上取值就算19,需要按比例分配到不同的业务中,

image-20211019174220077

本次文章抄录于《6 全栈性能测试修炼宝典JMeter实战》

单机架构

单机架构是最原始的传统架构,如下图所示,Model V1中Web服务器和App的服务器直接放在一起,随着业务持续增长,Model V2中把Web和App服务器分开管理,随着进一步业务增长需求,DB也很出现性能瓶颈,Web和App服务器频繁读取文件也会造成IO瓶颈,为了不影响现在业务,于是集群方案就产生

image-20211018151234673

集群结构

  • 如图 所示 Model V3 结构 Web&App 服务都可以用多台机器来进行负载分担,DB的瓶颈也可以采用分区、分库、分表的方式来缓解;分库、分区、分表宗旨是减小遍历范围,提高响应速度。
  • 还可以采用读写分离的方式来减轻单台服务器的 IO 负担,相当于增加了机器的处理能力。读写分离比较适合以读操作为主的应用,可以减轻写服务器压力,但是读服务器会有一定的延迟。当一些热点数据过多时,我们还可以对这些热点数据进行缓存(Model V4)。

image-20211018152315051

  • 对于负载均衡层,目前主要是在 TCP\IP 协议的四层与七层进行负载分发,四层负载流行的有 LVS(LVS 集群采用 IP 负载均衡技术和基于内容请求分发技术,目前互联网公司大量使用,如阿里、京东等)、F5(强大的商业交换机,好处是快、但就是贵),七层流行的有 Tengine、 Nginx、Haproxy、Vanish、ATS、Squid 等。目前互联网企业多采用 LVS+Tengine/Nginx的组合来进行负载均衡。
  • Model V3、Model V4 的集群架构基本能够解决多数企业的性能问题,但缺点也比较明显。多个 Web 服务器之间的用户请求状态(Session)需要同步(为保证高可用,如果其中一台宕机,另一台服务器能够正常处理用户请求,专业术语叫 Session 黏滞),这会消耗不少 CPU 资源。另外数据库实现读写分离后,数据同步(数据一致性保证)成为一个性能问题,大量数据的同步 IO 会面临瓶颈。另外业务量大以后,数据的安全保障机制也受到挑战,备份问题凸显,也催生了分布式的发展。

分布式结构

  • 系统分层、系统服务化(SOA 架构、微服务化等)、服务分布式、DB 分布式、缓存分布式及良好的水平扩展能力是当前分布式架构的典型特征:哪一个服务性能不佳直接增加机器即可,性能与机器数量呈线性增长关系,从而解决前面架构遇到的问题。

    image-20211018154844654

DNS&CDN静态加速

  • DNS:智能 DNS,用户请求进入后,域名解析服务器智能判断用户请求的线路,如果是电信用户就解析到电信 IP,联通用户就解析到联通 IP。

  • CDN:用户访问 Web 页面时往往会有很多静态资源(图片、样式、JS 等),而这些资源都是比较耗时的,CDN 服务其实就是把静态页面缓存到不同地区很多台专门的缓存服务器上,然后根据用户线路所在的地区通过 CND 服务商的智能 DNS 自动选择一个最近的缓存服务器让用户访问,以此提高速度,这种方案对静态页面效果非常好,同时它也需要智能 DNS 的帮助才能实现把用户引导到离自己最近的缓存服务器上。

负载均衡器

  • 负载均衡器的作用是把用户请求按一定规则分发到不同的服务器进行处理,在使用负载均衡集群时,分发负载是一件性能要求极高的事情,流行的产品有 LVS、nginx、apache、F5 等。

  • LVS:LVS 集群采用 IP 负载均衡技术和基于内容请求分发技术,也就是能够在 TCP/IP层的第四层进行请求分发。LVS 调度器具有很好的吞吐率,将请求均衡地转移到不同的服务器上执行,且调度器自动屏蔽掉服务器的故障,从而将一组服务器构成一个高性能的、高可用的虚拟服务器。整个服务器集群的结构对客户透明,无需修改客户端和服务器端的程序。为此,在设计时需要考虑系统的透明性、可伸缩性、高可用性和易维护性。关键一点是 LVS开源而且效率高,相比商业负载工具 F5 赢在免费,而且效率达到 F5 的 60%。

  • Tengine:Tengine 是一个强大的高性能反向代理服务器,Tengine 是由淘宝网发起的 Web服务器项目,它在 Nginx 的基础上针对大访问量网站的需求,添加了很多高级功能和特性。目前很多公司采用 LVS+Tengine/Nginx 的负载架构来构建自己的负载均衡部分

Web 服务分布式集群

  • Web:Web 服务层,按照 MVC 的设计理念 Web 服务层主要是进行页面渲染,Session 保持等工作。这些应用部署在诛如 Tomcat、Jetty、Jboss 这些容器上。图 10-13 所示为一个典型的分布式 Web 结构(已经简化),Client 请求通过前端负载均衡器(比如 LVS+Tengine)分发到 Web 层,Web 层通过 ZK(Zookeeper)注册中心找到提供业务处理(App 层中的某一个节点)的节点。Web 层请求传送到 App 层的路由由负载算法(用程序实现的负载路由)来实现通常叫软路由,它能够把请求按一定规则分发到 App 层的各节点上,Dubbo 框架中就内置了这样的软路由。
  • 对于 Web 层来说,请求会话状态(用 Session 来代替)的保持是一个问题,Session 同步是一个容易引起性能的地方,在分布式框架中一般会把 Session 信息独立出来放到缓存设备中,比如用 redis 来存储 Session 信息,当然大量的以亿来计的 Session 信息如果保存在一台或者少量几台 redis 中也会造成风险,首先是需要一个大的内存来存储数据,另外要考虑到数据安全,当服务器挂掉后数据如何恢复?想想一个200G 的 redis 数据集想恢复得花多长时间,本着风险分散原则,还是拆分成多个 redis 节点保险,所以 redis 分布式集群也变得很有必要。不少互联网公司会在 redis 之上加上一个中间层,来构建分布式缓存服务

App 服务分布式集群

  • App:应用服务层,实现主要的业务逻辑。应用服务不仅在单机上要具备更优的性能,在结构上要易于水平扩展,功能服务化且服务无状态。比如我们网购,选择商品准备结算时,如果没有登录会跳出登录框,提交登录请求会调用会员系统进行身份验证,这是一个服务;会员系统调用账务系统查询余额是另一个服务。这些服务部署多个,任意一台处理请求返回结果都一样,这样就具备良好的水平扩展能力。当遇到某一类服务性能吃紧时直接增加机器就可以了。Dubbo 就是经过实践验证的使用广泛的分布式服务框架,具备良好的水平扩展能力

分布式缓存

  • Cache:缓存数据到内存,解决热点数据问题。比如 redis,memcache 等缓存产品。在内存中存储数据时不可忽视的问题是数据的安全性与存储量,当前解决数据安全性的方法主要是数据持久化与数据冗余(主从缓存服务器结构,为了性能会进行读写分离);解决存储量的问题主要是分而治之,进行分布式存储,每一个存储节点我们叫做分片,比如100G的数据我们分5个片区来存储,每个分片就是20G。
  • 图 10-14 所示常见的分布式缓存架构,Cache1 与 Cache n 构成分布式缓存集群,以 redis 为例(比如 Cache1 由 redis 担当),Cache1 是一个分片(物理节点),Cachen是第n个分片(物理节点),redis 以(Key,Value)结构存储数据(有关redis 的知识请自行查阅相关资料)。
  • Web/App 服务先从 Zookeeper 中心取得缓存服务器访问地址(比如 Cache 1 地址),然后向缓存服务器发起请求(读、写、修改)。缓存服务器由 Zookeeper 来提供一致性服务,这样很方便对缓存服务器数据进行冗余(读写分离),保证数据安全,提高访问效率。当缓存数据过多时,可以水平扩展来提高服务能力。
  • 分布式缓存不仅解决热点数据问题,有些企业直接用其作为数据持久化介质,比如秒杀分布式缓存在整个分布式架构中是重要的组成部分。

image-20211018163041453

分布式数据库

  • 传统集中式的数据库结构随着数据的激增,为提供良好的用户体验的成本越来越高。对于海量数据基本是分区、分表、读写分离这些手段,海量数据的访问使得对 CPU、内存、硬盘的要求更高,最后依然是无法突破瓶颈,我们并不能生产出更强的服务器,暂时办不到,也没必要,就像我们搬不动一堆东西时,我们可以分开搬,也可以几个人一起搬。所以我们可以分而治之,用普通的 PC 来做高端服务器的工作。
  • 分布式数据库是一种趋势,用廉价的普通 PC 设备堆叠出具备高可用性、高扩展性的服务集群,正如本章开篇中说到的去IOE 化,摆脱对大型设备的依赖,减少运营成本,提高服务能力。

以上知识抄录于<<全栈性能测试修炼宝典JMeter实战>>

什么是反向代理服务器

  • ‘反向代理服务器’ 有两个概念,一是‘代理服务器’,二是‘反向’

  • ‘代理服务器’比较好理解,例如需要访问某网站,不想或不能直接访问,例如网络的原因、隐私的原因等,我们就连接一个代理服务器,这样对于这个网站来说,访问他的用户是这个代理服务器,而不是我们自己

  • ‘反向’的意思我们没有通过代理服务器访问网站,但网站却在自己服务器前面加了一个代理,我们输入网址发起请求后,请求先到了这个代理服务器,代理服务器再把请求转给网站服务器

    image-20211018163759022

  • 参考这里

中间件总结

Dubbo

  • Dubbo是一个分布式服务框架,是管理中间层的工具,至于你架子上放什么是完全取决于你的,就像一个汽车骨架,你需要配你的轮子引擎。这个框架中要完成调度必须要有一个分布式的注册中心,储存所有服务的元数据,你可以用zk(Zookeeper),也可以用别的,只是大家都用zk

  • Dubbo的将注册中心进行抽象,是得它可以外接不同的存储媒介给注册中心提供服务,有ZooKeeper,Memcached,Redis等。

  • 为什么要用zookeeper作为dubbo的注册中心?能选择其他的吗?

    • Zookeeper的数据模型是由一系列的Znode数据节点组成,和文件系统类似。zookeeper的数据全部存储在内存中,性能高;
    • zookeeper也支持集群,实现了高可用;同时基于zookeeper的特性,也支持事件监听(服务的暴露方发生变化,可以进行推送),所以zookeeper适合作为dubbo的注册中心区使用。redis、Simple也可以作为dubbo的注册中心来使用。
  • 开发步骤

1
2
3
4
5
6
7
1:增加dubbo的配置文件(提供者)
zk的通讯注册地址
dubbo的对外暴露接口的地址
对外暴露并注册的接口(zk)
2:增加获取服务接口的配置文件dubbo(消费者)
配置dubbo调用的接口暴露地址
获取要调用消费的接口bean组件
  • 使用步骤
1
2
1:开启zk的服务,将dubbo的接口注册到服务中
2:启动dubbo的监控中心,监控提供者和消费者的接口调用和注册信息

Dubbo与Kafka对比

  • 都可以以分布式方式处理任务和负载均衡
  • Dubbo处理任务是同步的,可以收到返回结果值。Kafka是异步的,不能返回结果值。
  • Kafka可以存储消息,可以从某个消息重新开始执行。如果任务执行速度较慢,消息可以缓存,不会阻塞

分布式开发应用场景

  • 服务器中间件:Tomcat 6、7、Jboss 7、WebLogic 10、WebSphere 8

  • 分布式服务:Dubbo+Zookeeper+Proxy+Restful

  • 分布式消息中间件:KafKa+Flume+Zookeeper

  • 分布式缓存:Redis 分布式文件:FastDFS

  • 负载均衡:Keepalived+Nginx+Proxy(三重负载)

其他总结

Elasticsearch

  • ElasticSearch是一个基于Lucene的搜索服务器。通过HTTP使用JSON进行数据索引,用于分布式全文检索,解决人们对于搜索的众多要求。

Nginx

  • nginx本是一个web服务器和反向代理服务器,但由于丰富的负载均衡策略,常常被用于客户端可真实的服务器之间,作为负载均衡的实现。用于HTTP、HTTPS、SMTP、POP3和IMAP协议

ActiveMQ

  • activeMQ是一种开源的,面向消息的中间件,用来系统之间进行通信的

说明

  • 按照官网给出的配置后,发现底部和每个文章都不展示统计数据,查询到资料是live2dbusuanzi冲突引起,最终解决方案如下

解决

  • 解决网站底部不展示统计数据,打开\themes\next\layout\_third-party\statistics\busuanzi-counter.swig,将

    1
    2
    3
    4
    5
    <span class="post-meta-item" id="busuanzi_container_site_uv" style="display: none;">
    <span class="post-meta-item" id="busuanzi_container_site_pv" style="display: none;">
    修改
    <span class="post-meta-item" id="busuanzi_container_site_uv" style="display: none;"></span>
    <span class="post-meta-item" id="busuanzi_container_site_pv" style="display: none;"></span>

image-20211014155848022

  • 解决文章标题下不展示统计数据,我看很多人都是修改源busuanzi.pure.mini.js文件,最终我新增了个 style属性就行,打开\themes\next\layout\_macro\post.swig ,新增style属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    {%- if not is_index and theme.busuanzi_count.enable and theme.busuanzi_count.post_views %}
    <style>
    #busuanzi_container_page_pv {display:inline !important;margin-left:10px;}
    </style>
    <span class="post-meta-item" title="{{ __('post.views') }}" id="busuanzi_container_page_pv">

    <span class="post-meta-item-icon">
    <i class="{{ theme.busuanzi_count.post_views_icon }}"></i>
    </span>
    <span class="post-meta-item-text">{{ __('post.views') + __('symbol.colon') }}</span>
    <span id="busuanzi_value_page_pv"></span>
    </span>
    {%- endif %}

    image-20211014155808658