基于线上请求的性能测试系统CPC

1.背景

测试人员在设计性能测试脚本时,HTTP请求中的参数往往根据个人经验设置,而测试人员水平参差不齐,设计往往具有局限性,不够全面,不能涵盖全线上真实的请求,故得到的性能测试结果不能够真实反映线上真实的情况。

使用线上环境下的HTTP请求检查软件性能的问题,通过Gor记录线上真实的请求,作为性能测试脚本的请求池,用请求池物料进行性能测试,能真实的反映软件系统在线上环境下的性能指标和问题。

2.概念

2-1.架构图

2-2.技术栈

请求池:

Gor:

HTTP 录制工具 https://github.com/buger/gor

Webdis:

A very simple web server providing an HTTP interface to Redis https://github.com/nicolasff/webdis

redis:

持久化缓存

性能测试工具:

nGrinder二次开发:

http://blog.csdn.net/neven7/article/details/50740018

Spring MVC

链路可视化:

watchman(微博APM)

influxDB:

时序化DB https://github.com/influxdata/influxdb

Grafana:

可视化工具 https://github.com/grafana/grafana

3.实现

3-1.请求池

使用Gor录制线上请求,根据线上请求,序列化成Json String, 持久化到redis;性能测试脚本根据key,获取到线上请求数据,进行压测。

为了方便部署请求池,将请求池docker化,使用如下命名,启动docker容器:

docker run -i -t --net=host gor-request-parser /bin/bash

开始录制线上数据:

sh gor_request_parser.sh 8080 60 GET your_api_name NONBASIC ip port

参数介绍:
8080:监听端口
60:监听时间(秒)
GET:HTTP METHOD
your_api_name:过滤其他url,只保留your_api_name请求
NONBASIC:非BASIC认证接口,参数BASIC为BASIC接口
ip port:webdis服务

60s后, 请求数据持久化到redis中

***************************************************
              gor http请求 序列化
  http请求记录中,60 秒后,终止记录
***************************************************
Version: 

***************************************************
       记录结束, http请求序列化到请求池
       @author hugang
***************************************************

redis的key为$date_$hostname_$url

value为Json Array,形如:

3-2.性能测试脚本

性能测试工具使用nGrinder,进行二次开发,请参考:http://blog.csdn.net/neven7/article/details/50740018

性能测试脚本使用redis获取线上请求数据,依赖jedis、fastJson,在脚本lib中导入这2个jar包。

范例:

package org.ngrinder;

import static net.grinder.script.Grinder.grinder
import static org.junit.Assert.*
import static org.hamcrest.Matchers.*
import net.grinder.plugin.http.HTTPRequest
import net.grinder.plugin.http.HTTPPluginControl;
import net.grinder.script.GTest
import net.grinder.script.Grinder
import net.grinder.scriptengine.groovy.junit.GrinderRunner
import net.grinder.scriptengine.groovy.junit.annotation.BeforeProcess
import net.grinder.scriptengine.groovy.junit.annotation.BeforeThread
// import static net.grinder.util.GrinderUtils.* // You can use this if you‘re using nGrinder after 3.2.3
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith

import HTTPClient.HTTPResponse
import HTTPClient.NVPair

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import groovy.json.JsonBuilder
import groovy.json.JsonSlurper

import com.alibaba.fastjson.JSONArray;
import redis.clients.jedis.Jedis;

/**
 * A simple example using the HTTP plugin that shows the retrieval of a
 * single page via HTTP.
 *
 * This script is automatically generated by ngrinder.
 *
 * @author hugang
 */
@RunWith(GrinderRunner)
class TestRunner {
    public static GTest test
    public static HTTPRequest request
    public static File file
    public static JSONArray jsonArray

    @BeforeProcess
    public static void beforeProcess() {
        HTTPPluginControl.getConnectionDefaults().timeout = 6000
        test = new GTest(1, "压测ip")
        request = new HTTPRequest()
        test.record(request);

        // 读取请求池数据
        Jedis jedis = new Jedis("redis ip", redis port);
        // redis key
        String key = "your key";
        String jsonStr = jedis.get(key);

        jsonArray = JSONArray.parseArray(jsonStr);
        // grinder.logger.info(jsonArray.getString(0));
        // grinder.logger.info("before process.");
    }

    @BeforeThread
    public void beforeThread() {
        grinder.statistics.delayReports=true;
    }

    @Test
    public void test(){
        // 随机获取
        int index = (int) (Math.random() * jsonArray.size());
        String httpInfo = jsonArray.getString(index);

        def json = new JsonSlurper().parseText(httpInfo)

        String api = json.api
        Map param = json.param

        def nvs = []
        param.each{
            key, value -> nvs.add(new NVPair(key, value))
        }

        // GET请求,wiki http://grinder.sourceforge.net/g3/script-javadoc/net/grinder/plugin/http/HTTPRequest.html
        // param1: uri, param2: queryData
        // HTTPResponse GET(java.lang.String uri, NVPair[] queryData) Makes an HTTP GET request.
        HTTPResponse result = request.GET("http://压测ip" + api, nvs as NVPair[])
        if (result.statusCode == 301 || result.statusCode == 302) {
            grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", result.statusCode);
        } else {
            assertThat(result.statusCode, is(200));
            // 请求返回的数据
            // println(result.text);
            // 定义一个事务,接口返回数据校验,是否包含
            assertThat(result.text, containsString("\"code\""));
        }
    }
}

3-3. 链路时间分布可视化

链路时间展示,启动web服务指定-javaagent为watchman agent,使用字节码增强,获取某一段时间内代码链路的分布时间。

请参考:http://blog.csdn.net/neven7/article/details/50980726

时间: 2024-09-29 14:28:15

基于线上请求的性能测试系统CPC的相关文章

一次线上用于某某中心系统线上所需环境搭建部署weblogic12C过程

source /etc/profile groupadd bea mkdir /data useradd -d /data/weblogic -g bea weblogic echo '[email protected]#$%'|passwd --stdin weblogic JAVA_HOME=/data/weblogic/jdk-7u55-linux-x64 CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar PATH=$JA

订单导出的预发和线上的自动化对比工具

问题与背景 订单导出需要将交易数据通过报表的形式导出并提供下载給商家,供商家发货.对账等.由于交易的场景非常多,承接多个业务(微商城.零售单店.零售连锁版.餐饮),订单类型很多,新老报表的字段覆盖交易.支付.会员.优惠.发货.退款.特定业务等,合计多达120个.每次代码变更(尤其是比较大的改动),如果想要手工验证指定时间段内的绝大多数场景下绝大多数订单类型的所有字段都没有问题,在前端页面点击下载报表,然后手工对比,将是非常大的工作量.因此,迫切需要一个自动化的对比工具,对比变更分支与线上分支的导

线上问题排查的四类方法

最正统的方法 日志 这是排查问题的最常用的方法,需要预估自己每日日志量和需要存储的日志时间.申请磁盘空间时一般会留35%的冗余以备突发流量. 一般需要打日志的有:每个对外提供方法的入口和出口,调用第三方的调用前和调用后.打印内容主要包括入参和出参.https://github.com/xiexiaojing/concise-logger 我在简明日志规范里定义:几种常用的类里用切面的形式注入日志. 监控 传统的方法如果JVM出现gc等问题需要先打开gc日志,这会牺牲一些效率.但是现在业界已经普遍

性能测试之线上引流测试--让性能测试更真实更丰富

为什么要做引流测试 目前为止大部分的测试是在测试环境下,通过模拟用户的行为来对系统进行验证,包括功能以及性能.在这个过程中,你可能会遇到以下问题: 用户访问行为比较复杂,模拟很难和用户行为一致,模拟不够真实; 线下模拟场景有限,会出现业务覆盖不全的情况.引流测试就是为了解决以上问题,通过把线上的真实流量复制到线下环境,解决测试环境模拟不够真实,或覆盖不够全面的问题. 引流的做法 目前不少公司对引流测试进行了实践,主要有以下4种引流方式: 以上几种办法各有利弊,有的是需要自己开发相应的工具来支持.

线上LVS负载均衡请求不转发案例简单解决分析一例

线上某架构组织结构基本如下: 基本架构描述: 前端采用的是lvs+keepalived做负载均衡和高可用,用来转发客户的请求给后端的业务服务器,也就是那4组nginx+tomcat业务服务器.说的更直白一些,那几台nginx+tomcat可以简答理解为lvs的客户端. 故障描述: 其中lvs转发到58.2.12.20这台服务器的时候, ActiveConn的值还有一些,InActConn几乎是没有数值的.为了这个问题纠结了好几天迟迟未能解决,由于刚到公司也不能不解决这些问题哦. 解决思路: 1)

系统上线那点事 - 记一次线上系统故障

该项目是一个微信转盘游戏抽奖营销项目.因为运营营销时间要求紧迫.开发測试部署上线用了10天不到,有些准备工作并没有到位,如: 1.因为总体开发在上线前2天才完毕,測试了解这个项目需求是在开发的第二周,并没有充足的时间进行完好的功能,UI机型适配,系统压力測试. 2.技术上因为合作方的公众号密钥并不适合直接给出,所以由对方封装微信接口获取所需功能,对方封装的微信接口给出比較迟,在预定開始时间前三天: 微信的网页接口授权回调域名仅仅有一个.这个回调域名还有其它应用在使用,不能直接简单的改为我们部署应

第二代支付系统及电票线上清算相关知识

二代支付系统 国家处理中心(NPC):NPC是人民银行连接支付系统所有城市节点和特许参与者的中枢节点,负责接收.转发各CCPC和接收.处理特许参与者的支付指令,以及资金清算的一组硬件和软件系统的总称.参加支付系统的直接参与者必须在人民银行国家处理中心开设清算账户. 城市处理中心(CCPC):CCPC是人民银行支付系统的城市节点,连接NPC和各直接参与者,负责在NPC和直接参与者之间接收和转发支付指令的一组硬件和软件系统的总称. 人民银行二代支付系统  CNAPS(China National A

线上系统架构设计 之 【数据库篇-主主从】

双主一从架构,从服务器在本地,用于备份和研发测试.两台线上服务器进行数据库相互同步,保证数据一致性,采用xtrabackup备份数据库+脚本每天1点异地备份到从服务器. 一.对线上的一台主服务器数据进行备份,并恢复到另外两台服务器上. innobackupex --defaults-file=/wqdata/mysql/my.cnf --user=bkuser --password='123456' /wqdata/mofidbbak/fullbackup/    备份 scp -P 8022

【阿里云产品公测】OTS使用之简单线上产品实践基于PythonSDK

阿里云用户:morenocjm 实践是检验真理的唯一标准,学习技术需要通过实践过程中的不断尝试,才能够快速掌握要领.OTS是构建在阿里云飞天分布式系统之上的NoSQL数据库服务,提供海量结构化数据的存储和实时访问.刚好想用手上的一台ECS做点什么,既然如此,那就通过搭建简单线上产品(alijot.com 快速记)的过程,学习下NoSQL数据库OTS吧. ------------------------------------------------------------------------