JMeter 介绍
性能测试整体认知
性能测试的分类
- 负载测试:通过逐步加压的方法,达到既定的性能阈值的目标。阈值的设定应是小于等于某个值,如 cpu 使用率小于等于 80%
- 压力测试:通过逐步加压的方法,使得系统的某些资源达到饱和,甚至失效的状态,简单粗暴的解释就是什么条件能把系统压崩溃
- 并发测试:在同一时间内,多个虚拟用户同时访问同一模块、同一功能,通常的测试方法是设置集合点
- 容量测试:通常是指数据库层面的,目标是获取数据库的最佳容量的能力。又称之为容量预估。具体测试方法为在一定的并发用户,不同的基础数量量下,观察数据库的处理能力,即获取数据库的各项性能指标
- 可靠性测试:又称之为稳定性测试或疲劳测试。是指系统在高压情况下,长时间的运行系统是否稳定。如 cpu 使用率在 80%以上,7*24 小时运行,系统是否稳定。
- 异常测试:又称之为失败测试。是指系统架构方面的测试。如果在负载均衡架构中,要测试宕机、节点挂掉等情况系统的反映
性能测试的工作流程
- 需求分析
- 性能指标制定
- 脚本开发
- 场景设置
- 监控部署
- 测试执行
- 性能分析
- 性能调优
- 测试报告
测试执行-》性能分析-》性能调优,此步骤循环执行,不断调优
常见系统应用分层架构
显示层(view): - web - android - ios - H5
逻辑控制层(controller): - Api
数据存储层(model): - mysql - mongodb - redis - …
性能测试指标定义
事务
从客户端发起的一个或多个请求(这些请求组成一个完整的操作),到客户端接收到从服务器返回的响应
TPS( Transaction Per Second)
每秒钟系统能够处理的事务数
请求响应时间
从客户端发起的一个请求开始,到客户端接收到从服务器返回的响应。整个过程所耗费的时间
事务响应时间
事务可能是一个或多个请求组成的,事务响应时间主要是针对于用户的角度而言,如转账
并发
- 没有严格意义上的并发。并发总有先后,无论差距是 1 毫秒或者是 1 微秒,总有一个时间差。所以并发讲的是一个时间范围内,比如 1 秒内
- 多用户在系统上进行同一操作,比如双十一时,大家都真的同一种商品进行秒杀
- 多用户在系统上进行不同操作,比如双十一时,大家针对不同商品进行秒杀,或者是大家有进行其他不同的操作,比如商品浏览
并发用户数
同一单位时间内对系统发起请求的用户数量
吞吐量
一次性能测试过程中网络上传输的数据量的总和
吞吐率
单位时间内网络上传输的数据量 吞吐率=吞吐量/传输时间
点击率
每秒钟用户向服务器提交的请求数。这个指标是 web 应用程序特有的一个指标,可以想象为每秒钟用户总共在页面上进行多少次点击动作,但是需要注意的是一次鼠标单击的操作后,客户端有可能向服务器发送了多次请求
资源使用率
对不同的系统资源的使用情况,如 cpu 、 内如、io
性能测试的需求分析
分析的目的
- 明确测试指标
- 明确测试场景
当遇到新系统时
- 同行业比较
- 业务预期
当遇到老系统
- 对比以往的用户使用行为以及用户量
性能测试工具
常用工具: - LoadRunner - JMeter
JMeter
JMeter 的组成
测试计划、线程组、断言、定时器、监听器、配置元件、后置处理器、前置处理器、逻辑控制器、Sampler
断言不推荐使用,断言是为了判断准确性。准确性应该尽量放在单元测试做
JMeter 实现多并发
- 线程组:负载发生器,用多线程或多进程的方式来模拟用户的使用行为。JMeter 是以线程的方式来模拟用户的并发访问的。
终端启动:
|
|
JMeter 实现逻辑分支控制
逻辑控制器:用来控制测试脚本的逻辑判断,也可以理解为如何控制脚本的运行。例如:如果控制器,就是当满足什么样的条件后执行哪一步操作。
JMeter 实现配置管理
配置元件:用来提供一些配置相关的信息,如 Http 请求头、cookie 管理,提供参数化数据。还可以进行用户自定义变量等配置,用以定义常量等
JMeter 实现请求预处理
服务器监控性能测试
测试目的
发现服务器的性能瓶颈。配置的不同能够承载的最大任务数不同,能够承载的压力也不同。 ### 测试范围及性能指标 - cpu - 内存 - 磁盘 - 网络 - 版本
测试与生产的环境不同
通过多次压测来计算性能损耗
性能损耗的计算:多次压测后的性能预估
进程与线程
定义与区别: - 进程是具有一定独立功能的程序关于某个数据集合上的运行活动,是系统进行资源分配和调度的一个独立单位 - 线程是进程的一个实体,是 cpu 调度和分派的基本单位,他是比进程更小的能够独立运行的基本单位,线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源。一个线程可以创建和撤销另一个线程 - 一个线程只能属于一个进程,而一个进程可以拥有多个线程 - 线程是进程工作的最小单位 - 一个进程会分配一个地址空间,进程与进程之间不共享地址空间。即不共享内存 - 同一个进程下的不同的多个线程,共享父进程的地址空间 - 线程在执行过程中,需要写作同步。不同进程的线程间要利用消息通信的方法实现同步 - 线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
进程 优点: - 每个进程互相独立,不影响主程序的稳定性,子进程崩溃不影响其他进程 - 通过增加 cpu,就可以扩充性能 - 可以尽量减少线程加锁与解锁的影响,极大的提高了性能 进程 缺点: - 逻辑控制复杂,需要和主程序交互 - 多进程调度开销大
线程 优点: - 程序逻辑和控制方式简单 - 所有线程可以直接共享内存和变量等 - 线程方式消耗的总资源比进程方式少
线程 缺点: - 每个线程与主程序共用地址空间,最大内存地址受限 - 线程之间的同步和加锁不易控制 - 一个线程的崩溃可能影响到整个程序的稳定性
常用命令
|
|
数据驱动
定义:从数据文件中读取测试数据,驱动测试过程的一种测试方法。数据驱动可以理解为更高级的参数化。
特定: - 测试数据与测试代码分离 - 数据控制过程
好处: - 减少测试代码量 - 降低脚本开发和维护的成本 - 便于用例的修改和维护(不用修改代码)
要求: - 较强的代码能力 - 较强的分层架构设计思维 - 对开发框架要有一定的了解
使用场景: - 复杂的业务流程 - 根据业务场景分流 - 符合条件的并发场景 电商业务模型: 登录、注册、浏览电子商品
控制方式: - 参数化 - 逻辑控制器
数据库架构设计
目的:发现数据库相关的所有性能瓶颈
- sql 语句,慢查询等
- 资源使用率
- 数据库架构合理性
- 数据库性能指标
常用架构
一主多从,适用于读比较多的情况 双机热备(keepalived),适用于读写(尤其是写)比较多的情况
主从同步原理
- master 将改变记录到二进制日志(binary log)中
- slave 将 master 的 binary log 拷贝到它的中继日志(relay log)
- slave 重做中继日志中的时间,将改变反映它自己的数据
数据库分库分表
拆分的原因: - 单表或库数据量太大 - 硬件不能升级或无法升级
方案: 业务拆分(数据库拆成不同的数据库,比如 用户、商品、订单等) 垂直拆分(比如商品表中,把床上用品、母婴用品、电子商品拆分出去 ) 水平拆分,一致性哈希算法
MySQL 性能测试
MySQL 重点监控指标
QPS 每秒钟查询数量
|
|
TPS
|
|
线程连接数
|
|
最大连接数
|
|
Query Cache 查询缓存用于缓存 select 查询结果,当下次接收到相同查询请求时,不再执行实际查询处理而直接返回结果,适用于大量查询,很少改变表中数据。 开启方法: 1. 修改 my.cnf 2. 设置 query_cache_size ,最好为 1024 的倍数,参考值 32M 3. 增加一行 query_cache_type=0/1/2。若为 1,将缓存所有的结果,除非 select 语句使用了 SQL_NO_CACHE 禁用查询缓存; 若为 2,则只缓存 select 语句中使用了 SQL_CACHE 指定需要缓存的查询。
Query Cache 命令率
|
|
锁定状态
|
|
主从延时
|
|
慢查询
执行速度超过定义的时间的查询 不同的系统定义不同的慢查询指标 开启方法:
|
|
慢查询日志分析
mysqldumpslow 命令
- -s ,排序(c 访问计数,l 锁定时间,r 返回记录,t 查询时间,al 平均锁定时间,ar 平均返回记录数,at 平均查询时间 )
- -t ,top n ,返回前 n 条数据
- -g ,正则匹配,大小写不敏感
|
|
explain 分析
|
|
返回结果分析 id: - select 识别符,代表语句的执行顺序,一般在 select 嵌套查询时会不同 - id 列数字越大越先执行,如果说数字一样大,那么就从上往下一次执行 - id 列为 null ,表示这是一个结果集,不需要使用它来进行查询
select_type: - simple,表示不需要 union 操作或者不包含子查询的简单 select 查询。有连接查询时,外层的查询为 simple ,且只有一个。 - primary,一个需要 union 操作或者含有子查询的 select ,位于最外层的单位查询的 select_type 即为 primary,且只有一个。 - union,连接的两个 select 查询,第一个查询是 dervied 派生表,除了第一个表外,第二个以后的表 select_type 都是 union。 - dependent union,与 union 一样,出现在 union 或 union all 语句汇总,但是这个查询要受到外部查询的影响。 - union result, 包含 union 的结果集,在 union 和 union all 语句中,因为它不需要参与查询,所以 id 字段为 null。 - subquery,除了 from 字句中包含的子查询外,其他地方出现的子查询都可能是 subquery。 - dependent subquery,与 dependent union 类似,表示这个 subquery 的查询要受到外部表查询的影响 - derived,from 子句中出现的子查询,也叫做派生表,其他数据库中可能叫做内联视图或嵌套 select。
table: 显示的查询表名,如果查询使用了别名,那么这里显示的是别名。如果不设计数据表的操作,那么显示为 null。 如果显示为尖括号括起来的 ,就表示这个是临时表。
type: - 依次从好到差:system, const , eq_ref, ref, fulltext,ref_or_null, unique_subquery, index_subquery, range, index_merge, index, ALL - 除了 all 之外,其他的 type 都可以使用到索引 - 除了 index_merge 之外,其他的 type 只可以用到一个索引
type 各个值的说明: - system: 表中只有一行数据或者是空表,且只能用于
myisam 和 memory 表。如果是 Innodb 引擎,type 列在这个情况通常都是 all
或者 index - const: 使用唯一索引或者主键,返回记录一定是 1 行记录的等值
where 条件时,通常 type 是 const。 其他数据库也叫做唯一索引扫描 -
eq_ref:
出现在要连接过个表的查询计划中,驱动表值返回一行数据,且这行数据是第二个表的主键或者唯一索引,且必须为
not null,唯一索引和主键是多列时,只有所有的列都用作比较时才会出现
eq_ref - ref: 不像 eq_ref
那样要求连接顺序,也没有主键和唯一索引的要求,只要使用相等条件检索时就可能出现,常见于辅助索引的等值查找。或者多列主键、唯一索引中,使用第一个列之外的列作为等值查找也会出现。总之,返回数据不唯一的等值查找就可能出现。 -
fulltext:
全文索引检索。要注意,全文索引的优先级很高,若全文索引和普通索引同时存在时,mysql
不管代价,优先选择使用全文索引 - ref_or_null: 与 ref
方法类似,只是增加了 null 值的比较。实际用的不多。 -
unique_subquery:用于 where 中的 in 形式子查询,子查询返回不重复唯一值 -
index_subquery: 用于 in 形式子查询使用到了辅助索引或者 in
常数列表,子查询可能返回重复值,可以使用索引将子查询去重。 - range:
索引范围扫描,常见于 > < is null between in like
等运算符的查询中。 -
index_merge: 表示查询使用了两个以上的索引,最后取交集或者并集,常见
and, or 的条件使用了不同的索引,官方排序这个在 ref_or_null
之后,但是实际上由于要读取所有索引,性能可能大部分时间不如 range -
index:
索引全表扫描,把索引从头到尾扫一遍,常见于使用索引列就可以处理不需要读取数据文件的查询、可以使用索引排序或者分组的查询。 -
all:全表扫描数据文件,然后在 server 层进行过滤返回符合要求的记录。
possible_keys: 查询可能使用到的索引都会在这里列出来
key: 查询真正使用到的索引。select_type 为 index_merge 时,可能会出现两个以上的索引,其他的只会出现一个
key_len: 用于处理查询的索引长度。
ref: 如果是常数等值查询,这里会显示 const; 如果是连接查询,显示驱动表的关联字段; 如果使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能会显示为 func
rows: 执行计划中估算的扫描行数,不是精确值
Extra: - distinct,在 select 中使用了 distinct 关键字 - no tables used: 不带 from 子句的查询或者 From dual 查询 - using filesort:排序时无法使用到索引时,会出现这个。常见于 order by 和 group by 语句中 - using index:查询时不需要回表查询,直接通过索引就可以获取查询的数据 - using intersect: 表示使用 and 的各个索引的条件时,该信息表示从处理结果获取交集 - using union: 表示使用 or 连接各个使用索引的条件时,该信息表示从处理结果获取并集 - using where: 表示存储引擎返回的记录并不是所有的都满足查询条件,需要在 server 层进行过滤
总结: 首先关注 type 值, ref, rows, Extra 辅助判断
索引
- 主键索引:一种特殊的唯一索引,不允许有空值,在建表时创建
- 唯一索引:索引列的值必须唯一,但允许有空值
- 普通索引:最基本的索引,没有任何限制
- 全文索引:fulltext 是一种只适用于 MyISAM 表的一个索引类型
- 组合索引:也叫多列索引,就是在多列上同时创建索引,使得多列的组合值唯一。创建组合索引的好处是比分别创建多个单列索引的查询速度要快很多。遵循“最左前缀”规则
插入与更新数据时,要重写索引文件 索引创建规范: - 单张表中索引数量不超过 5 个 - 组合索引中的字段数不超过 5 个 - 不使用更新频繁的列作为主键 - 合理创建组合索引(避免冗余) - 不在低基数列上建立索引,例如 性别 - 不在索引列进行数学运算和函数运算,否则会使索引失效 - 不使用 % 前导的查询,例如 like ‘%xxx’ 无法使用索引 - 不使用反向查询。例如 not in / not like ,无法使用索引 - 选择越小的数据类型越好。通常越小的数据类型通常在磁盘、内存、cpu、缓存中 占用的空间很少,处理起来更快 - 在经常需要 order by 、group by 、distinct 的列上加索引(order by 单独出现 不会使用索引,加 where 或 limit 可使用索引) - 在表与表的连接条件上加上索引,可以加快连接查询的速度 - 使用短索引
实时监控
orzdba 集群监控工具: 天兔 lepus
jmeter mysql 性能测试
- JDBC Connection Configuration 配置
- JDBC Request 写 sql 脚本
多协议接口性能测试
目标: - 发现应用程序的性能瓶颈 - 发现数据库的性能瓶颈
范围: - 应用程序各项性能指标 - 数据库各项性能指标
常见接口协议
- HTTP
- HTTPS
- FTP
- TCP
- IP
- UDP
测试用例设计
需要考虑的要素: - 被测系统及版本 - 测试数据 - 测试场景(包含异常场景) - 预期结果 - 预期性能指标
性能测试报告
- 被测系统
- 版本号
- 运行环境、配置
- 测试场景(并发定义)
- 预期性能指标
- 实际结果
- 测试结论
- 若不通过,说明瓶颈
- 若通过,则说明最大性能指标
- 容量规划
扩展组件
略
火爆的大数据
技能树: 存储: HBASE、hive、hdfs 数据传输:flume、kafka 实时计算:storm、spark 语言:java、python、scala
应用场景: 运营支撑:数据仓库、BI 风控支撑:实时计算、数据实时分析 营销支撑:精准营销、实时推荐