PostMan、LoadRunner进行并发压测流程

需求

两个记账接口在同一时间大量处理同一账户账务时,锁表顺序不同导致死锁,在修改完代码后模拟生产记账流程进行测试,需要对两个接口进行并发测试。
在进行压测的时候,需要对流水号进行递增。

PostMan处理流程

1. 新建Collections

在这里插入图片描述

2. 设置全局变量

在这里插入图片描述

3. 新建要测试的接口api

在这里插入图片描述

在这里插入图片描述

4. 在Pre-request Script中设置相关规则

使用JavaScript语言进行脚本编写

在这里插入图片描述

//postman.getGlobalVariable获取定义的全局变量
//postman.setGlobalVariable设置定义的全局变量


// 将流水号加1
var seqno = Number(postman.getGlobalVariable("Seq1240"));
seqno = seqno + 1

postman.setGlobalVariable("Seq1240",seqno);

// 使用日期+交易码+流水号的方式避免流水号重复
var golseqno = String(String(postman.getGlobalVariable("TranDate")) + seqno);
postman.setGlobalVariable("GolSeqNo",golseqno);

5. 处理请求报文

在这里插入图片描述

6. 使用Runner进行测试

在这里插入图片描述
在这里插入图片描述

点击POST链接 查看请求和返回的信息。
在这里插入图片描述

查询数据库查看测试结果
在这里插入图片描述

感觉PostMan的并发都是每组两个接口成功返回后再进行下一次迭代,不能满足测试需求,所以学一下如何使用LoadRunner进行测试。
以下陆续更新LoadRunner学习测试的过程。

LoadRunner处理流程

【性能测试工具完整版教学—LoadRunner篇】
https://www.bilibili.com/video/BV1fY4y1N7oG/?p=33&share_source=copy_web&vd_source=9aea609762c29c24f00ebffa4e482266

视频全长10个小时左右,二倍速观看加整理笔记和进行验证,需要20~30个小时吧

1. 安装本体

在这里插入图片描述

点击开始安装
在这里插入图片描述

选择解压目录
在这里插入图片描述

组件安装
在这里插入图片描述

组件安装完成后,选择安装目录,然后进行软甲安装
在这里插入图片描述

去掉勾选
在这里插入图片描述

安装完成后桌面多了三个快捷方式
在这里插入图片描述

2. 安装语言包

选择语言安装包
在这里插入图片描述

选择LoadRunner安装的路径
在这里插入图片描述

如图所示找到目录及对应的文件
在这里插入图片描述

双击安装文件
在这里插入图片描述

打开选择语言文件夹,选择要安装的语言。本处依次打开如下文件【Chinese-Simplified】→【LoadRunner】→【LR_03457】,点击【LR_03457】将进行安装
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

语言包安装完成

3. 使用VUGEN来编写脚本以及VUGEN软件的简介

首先我们需要知道loadrunner安装完成后,这三个图标分别的作用是什么
在这里插入图片描述

Virtual User Generator 是用来编写和管理测试脚本的。
Controller 是用来创建和控制运行性能测试的场景的。
Analysis 主要是用来对运行结果的分析的分析软件。

3.1 新建解决方案和脚本

在这里插入图片描述

脚本名称:1240
解决方案名称:1240yace
单协议:Web - HTTP/HTML
多协议及可选择多种协议,在编写脚本时可以使用多种协议
在这里插入图片描述

新建完毕后会有红框中对应的几个文件
在这里插入图片描述
其中vuser_init、Action、vuser_end文件都是以.c结尾,额外文件是头文件,包含了需要使用的.h文件,这也表示我们可以使用c语言的语法来编写脚本。

3.2 运行时设置设置

在这里插入图片描述

运行逻辑
在这里插入图片描述
运行逻辑中,随着迭代数的增加,Run 的运行次数会跟着迭代数一起增加(即会多次执行Action),而 vuser_init、vuser_end的运行次数不会增加,并且只会运行一次,我们也可以在Run中再加入Action1、Action2,Run运行多次的时候,对应的Action、Action1、Action2也会运行多次。

节奏
在这里插入图片描述
设置迭代之间的时间间隔,其中Fixed选项也可以选择Random,然后的秒数选择一个区间段,标志在这个区间段内随机触发。

日志
在这里插入图片描述
勾选 启用日志记录,默认为标准日志,如果脚本中带有参数等,建议使用扩展日志,将参数替换和服务器返回数据勾选,这样可以查询到更详细的信息。

思考时间
在这里插入图片描述
我在脚本里没有使用,暂略

其他属性
在这里插入图片描述
我在脚本里没有使用,暂略

其他
在这里插入图片描述
这里面的内容没有进行变更,使用默认设置进行测试即可。

浏览器仿真
在这里插入图片描述
用户代理选择即用户使用的浏览器标识。

速度模拟
在这里插入图片描述
默认使用最大带宽,如果有需要再进行调整。

首选项
在这里插入图片描述
启用图像和文本检查允许Vuser通过执行验证函数web_find或web_image_check来执行验证检查。仅适用于在基于HTML的模式下录制的步骤。启用此选项会增加您的脚本的内存占用。

内容检查、代理服务器、下载筛选器、链配置略。

3.3 参数列表

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

参数列表的名称要与代码中的参数名对应。
使用文件映射参数时,需要看一下列选择顺序个分隔符,以及选择下一行的模式。

设置完成后我们开始进行脚本的编写

3.4 编写脚本

在这里插入图片描述
编写脚本之前我们先来熟悉一下常用的函数

标C的函数

字符串操作函数
strcat、strncat 拼接
strcmp、strncmp 比较
strcpy、strncpy 拷贝
strlen 长度
strlwr、strupr 大小写转换
strset 填充
strstr 查找字符串出现的位置

缓冲区操作函数
memchr 搜索某个字符 
memcmp 比较
memcpy 拷贝
memmove 移动
memset 初始化 一定要记住如果要把一个char a[20]清零,一定是 memset(a,0,20*sizeof(char));

过程控制函数
getenv 获取环境变量
putenv 设置环境变量
system 执行系统命令

内存分配函数
calloc 
free
malloc
realloc 

数学函数
标准输入输出函数
文件操作函数
日期时间函数
数据类型转换函数

LR的一些常见函数


命令行解析函数
lr_get_attrib_double
lr_get_attrib_long
lr_get_attrib_string

数据库操作函数
lr_db_connect
lr_db_disconnect
lr_db_executeSQLStatment
lr_db_dataset_action
lr_db_getvalue

信息函数
lr_end_timer Stops a timer.
lr_get_host_name Returns the name of the host executing the script. 
lr_get_master_host_name Returns the name of the machine running the LoadRunner Controller .
lr_get_vuser_ip Returns the IP address of the current Vuser. Not applicable for products that do not run Vusers.
lr_start_timer Starts a timer.
lr_user_data_point Records a user-defined data sample. 
lr_user_data_point_ex Records a user-defined data sample and enables logging option.
lr_user_data_point_instance Records a user-defined data sample and correlates it to a transaction instance.
lr_user_data_point_instance_ex Records a user-defined data sample and enables logging option.
lr_whoami  

消息函数
lr_debug_message  Sends a debug message to the LoadRunner output window or Application Management agent log file.  
lr_error_message  Sends an error message to the LoadRunner output window or Application Management agent log file.  
lr_get_debug_message  Returns the current message logging settings.  
lr_log_message  Sends a message to the Vuser log file.  
lr_message  Sends a message to the log file and output window.  
lr_output_message  Sends a Vuser message to the log file and output window with location information.  
lr_remove_custom_error_message  Removes a custom text that was set by lr_set_custom_error_message. 
lr_set_debug_message  Sets a message class for output messages.  
lr_set_custom_error_message  Sets a custom text to be output after built-in error messages. 
lr_vuser_status_message  Sends a message to the Vuser status area in the LoadRunner Controller.  

字符串函数
lr_advance_param  Advances to the next available value in the parameter data file.  
lr_checkpoint  Validates the value of a parameter against an expected value (checkpoint).  
lr_convert_double_to_double  Formats the string representation of a double value using a printf-style format specifier. 
lr_convert_double_to_integer  Converts the string representation of a double value to the string representation of an integer. 
lr_convert_string_encoding  Converts a string to a different encoding.  
lr_decrypt  Decrypts an encoded string.  
lr_eval_string  Returns the string argument after evaluating embedded parameters.  
lr_eval_string_ext  Creates a buffer and assigns it the input string after evaluating embedded parameters.  
lr_eval_string_ext_free  Frees the buffer allocated by lr_eval_string_ext.  
lr_free_parameter  Deletes a dynamic parameter at run-time and frees its buffer.  
lr_next_row  Advances to the next row in the parameter data file.  
lr_param_increment  Increments the value of a LoadRunner parameter.  
lr_param_sprintf  Writes formatted output to a parameter.  
lr_param_unique  Generates a unique string and assigns it to a parameter.  
lr_paramarr_idx  Returns the value of the parameter at a specified location in a parameter array.  
lr_paramarr_len  Returns the number of elements in a parameter array.  
lr_paramarr_random  Returns the value of the parameter at a random location in a parameter array  
lr_save_datetime  Saves the date and time into a parameter.  
lr_save_param_regexp  Finds a string in a buffer using a regular expression and saves capture group matches to a parameter. 
lr_save_int  Saves an integer to a parameter.  
lr_save_searched_string  Searches for an occurrence of a string in a buffer and saves a portion of the buffer after that string to a parameter.  
lr_save_string  Saves a null terminated string as a parameter.  
lr_save_timestamp  Saves the current time in a parameter. 
lr_save_var  Saves a variable length string as a parameter.  
lr_unzip  Uncompresses the information in a parameter and stores the uncompressed information in another parameter. 
lr_zip  Compresses the information in a parameter and stores the compressed information in another parameter. 

事务函数
int lr_start_transaction( const char *transaction_name ); 事务开始
int lr_end_transaction( const char *transaction_name, int status) ; 事务结束

web的一些函数

int web_set_max_html_param_len( const char *length);

web_utl()
请求网页,HTTP的GET请求
查看函数时,点击函数名称按F1则会跳转到函数帮助页面
int web_url( const char *StepName, const char *url, <List of Attributes>, [EXTRARES, <List of Resource Attributes>,] LAST );
例子:
web_url("www.abc.com",
"URL=http://www.abc.com/",
"TargetFrame=", 
"TargetBrowser=Mercury Technologies",
"Resource=0",
"RecContentType=text/html",
"Snapshot=t1.inf",
"Mode=HTML",
LAST );
LAST 参数列表结尾的标记

int web_custom_request( const char *RequestName, <List of Attributes>, [EXTRARES, <List of Resource Attributes>,] LAST);
In the following recorded script, the user began recording from http://lazarus/html/forms/file.html. When the user submitted his request, VuGen inserted a web_add_header function, followed by a web_custom_request function.
web_url("file.html", "URL=http://lazarus/html/forms/file.html","TargetFrame=_TOP", LAST );
例子:
web_add_header("Content–Type",
"multipart/form–data; boundary=–––––––––––––––––––––––––––292742461228954");
web_custom_request("post_query.exe", "Method=POST",
"URL=http://lazarus/cgi–bin/post_query.exe",
"Body=–––––––––––––––––––––––––––––292742461228954\r\nContent–Disp"
"osition: form–data; name=\"entry\"\r\n\r\nText\r\n––––––––––"
"–––––––––––––––––––292742461228954\r\nContent–Disposition: f"
"–––––––––––292742461228954––\r\n",
"TargetFrame=",
LAST );

vuser_init.c

char recv_data[3000];
char data1[40000];

vuser_init()
{
	return 0;
}

Action.c

/*****************************************************************
脚本编写信息描述:1240-一借一贷记账
项目名称:核心业务系统
版 本 号:V1.0
交易路径:LR -> 核心
编码语言:C
参数数据: 
开发协议:HTTP/HTML
作    者:UntifA
时    间:2024年1月11日08:43:01
历史修改记录:

*****************************************************************/

#include "lr_replace_string.h"

Action()
{
	/*	定义char data[40000] 会报错 Too many local variables 
		原因其实是因为Action能分配的内存不多,所以若要直接使用占用内存大的变量,则建议将其定义成全局变量,或者是在Action里面使用malloc函数来进行分配
	*/
	
	char *data = (char *)malloc(40000); // 报文内容
	char *recv_data = (char *)malloc(40000); // 相应报文内容
	char *recv_message = (char *)malloc(40000); // 返回信息
	
	char Trace_ID[50] = {0}; // 全局流水
	
	char prcscd[100]; // transcation_id
	
	// 字符集编码转码结果
	int rc = 0;
	


	/*
		lr_eval_string()
		函数的主要作用:返回脚本中的一个参数当前的值(从参数中取得对应的值,并且转换为一个字符串)。
		格式:lr_eval_string("{参数名}");
		例如:lr_eval_string("{parm}");
		返回值类型:char
		由于返回值类型是char类型,所以可以直接使用lr_output_message(lr_eval_string("{parm}"))函数输出到日志中。
		如:lr_output_message(lr_eval_string("{parm}"));
		
		lr_save_string 
		函数主要是将程序中的常量或变量保存为lr中的参数
		char *tmp="hello";
		lr_save_string("192.168.10.35","ip"); //将常量保存为参数ip
		lr_save_string(tmp,"miao");     //将变量tmp保存为参数miao
		
	*/
	strcpy( Trace_ID,lr_eval_string("UntifA{date}{time}{rand}") );
	
	lr_output_message("查看一下流水号-----------> Trace_ID [%s]\n ", Trace_ID);
	
	lr_save_string(Trace_ID,"gloseqno");
	
	lr_output_message("查看一下流水号-----------> {gloseqno} [%s]\n ", lr_eval_string("{gloseqno}"));
	
	
	// 组装请求报文:
	strcpy(data,lr_eval_string("{																						"
		"\"Body\":{"
		"\"AppHead\":{"
		"\"jiaoyigy\":\"{jiaoyigy}\","
		"\"jiaoyirq\":\"{date}\","
		"\"jiaoyijg\":\"{jiaoyijg}\","
	"},"
        "\"zrzhhumc\": \"{zrzhhumc}\","
        "\"zczhhumc\": \"{zczhhumc}\""
	"},"
    "\"Head\":{"
		"\"ReqTm\":\"{time}\","
		"\"ReqSeqNo\":\"{gloseqno}\","
		"\"GloSeqNo\":\"{gloseqno}\","
		"\"ScnNo\":\"01\""
	"}"
"}"));
	
	lr_output_message("查看一下报文-----------> data [%s]\n ", data);
	
	lr_convert_string_encoding(data, LR_ENC_SYSTEM_LOCALE, LR_ENC_UTF8, "request_data");
	
	// 替换报文内容结尾的^@符号,即ASCII码中的0
	lr_replace_string("request_data","%x00","");
	
//	lr_save_string(data,"request_data");
	
	lr_output_message("查看一下报文-----------> request_data [%s]\n ", lr_eval_string("{request_data}"));
	
	// 报文进行转码
	//	rc = lr_convert_string_encoding(data, LR_ENC_SYSTEM_LOCALE, LR_ENC_UTF8, "stringInUnicode");
	//	if(rc < 0)
	//	
	//	{
	//		
	//	} else {
	//		lr_output_message("stringInUnicode ------> %s \n", lr_eval_string("{stringInUnicode}"));
	//	}
	
	
	//报文最大长度
    web_set_max_html_param_len("4096");
	
    // 组装报文头
	web_add_header("Content-Type","application/json");
	web_add_header("appKey","admin");
	web_add_header("appSecret","sunline");

	
	
	/*
		注册将与正则表达式匹配的动态数据保存到参数的请求。
		int web_reg_save_param_regexp(“ParamName= <输出参数名称>”,“RegExp = regular_expression”,[<属性列表>,] [<SEARCH FILTERS>,] LAST);
		参数说明:
		ParamName:要创建的参数的名称。
		RegExp:PERL兼容的正则表达式,包括一个用于从响应或响应中提取的带括号的子字符串。请参阅正则表达式。
		List of Attributes:有关每个属性的详细信息,请参阅保存参数注册函数的属性。
		属性值字符串(例如,“NotFound = warning”)不区分大小写。
		SEARCH FILTERS:搜索过滤器,指定缓冲区的部分以搜索字符串。请参阅搜索过滤器以保存参数注册函数。
		LAST:指示参数列表结束的标记。
	*/
//	web_reg_save_param_regexp(
//		"ParamName=recv_data",
//		"RegExp=",
//		"NotFound=warning",
//		"Group=0",
//		SEARCH_FILTERS,
//		"Scope=ALL",
//		"IgnoreRedirections=No",
//		LAST);

// 正则表达式没用成功,改用web_reg_save_param_ex函数功能	
//	web_reg_save_param_regexp("ParamName=recv_data","RegExp=\\(*)\\","Group=0","Notfound=warning",LAST);
//	web_reg_save_param_regexp("ParamName=recv_message","RegExp=RspMsg\":\"","Group=0","Notfound=warning",LAST);
//	web_reg_save_param_regexp("ParamName=recv_code","RegExp=RspCd\":\"","Group=0","Notfound=warning",LAST);
	
	// 获取返回报文
	web_reg_save_param_ex(
		"ParamName=recv_data",
		"LB=",
		"RB=",
		SEARCH_FILTERS,
		LAST);
	
	
	// 获取返回信息
	web_reg_save_param_ex(
		"ParamName=recv_message",
		"LB=RspMsg\":\"",
		"RB=\"",
		SEARCH_FILTERS,
		LAST);
	
	// 获取响应码
	web_reg_save_param_ex(
		"ParamName=recv_code",
		"LB=RspCd\":\"",
		"RB=\"",
		SEARCH_FILTERS,
		LAST);

	// 设置集合点
	lr_rendezvous("1240yjyd_jihe");
	
	strcpy(prcscd, "1240_yjyd");
	// 开启事务
	lr_start_transaction(prcscd);
	
	web_custom_request("untifa",
	                   "URL=http://xxx.xxx.xxx.xxx:xxxx/1240",
	                   "Method=POST",
	                   "body={request_data}",
	                   LAST);
	                   
	

	strcpy( recv_data,lr_eval_string("{recv_data}") );
	strcpy( recv_message,lr_eval_string("{recv_message}") );
	lr_convert_string_encoding(recv_data, LR_ENC_UTF8,LR_ENC_SYSTEM_LOCALE, "recv_data_conv");
	lr_convert_string_encoding(recv_message, LR_ENC_UTF8,LR_ENC_SYSTEM_LOCALE, "recv_message_conv");
	
	lr_output_message("响应报文:\n %s", lr_eval_string("{recv_data_conv}"));
	
	if(strcmp(lr_eval_string("{recv_code}"),"CBS0000000000000")== 0){
		// 结束事务
		lr_end_transaction(prcscd,LR_PASS);
	} else {
		// 结束事务
		lr_end_transaction(prcscd,LR_FAIL);
		lr_error_message("返回的响应码:%s",lr_eval_string("{recv_code}"));
		lr_error_message("返回的错误信息是:%s",lr_eval_string("{recv_message_conv}"));
	}
	
	return 0;
}
*/

vuser_end

vuser_end()
{
	return 0;
}

globalsh.h

#ifndef _GLOBALS_H
#define _GLOBALS_H

//--------------------------------------------------------------------
// Include Files
#include "lrun.h"
#include "web_api.h"
#include "lrw_custom_body.h"

//--------------------------------------------------------------------
// Global Variables

#endif // _GLOBALS_H

lr_replace_string.h

// ----------------------------------------------------------------------------
//
// 方法描述:
//    在一个字符串中查找并替换一个字符串。
//
// 参数说明:
//    src - 源字符串
//    from - 源字符串中需要被替换的字符串
//    to - 用于替换的字符串
//
// 返回说明:
//		返回一个指向动态内存的包含被"to"替换成"from"后的字符串。
//
// 注释:
//		不要直接使用这个脚本,除非你是一个懂得C语言和字符串处理的高级用户。
//		如想使用,请使用下方的lr_replace_string行数即可。
//
// ----------------------------------------------------------------------------
char *replaceString(const char *src, const char *from, const char *to){
  char *value;
  char *dst;
  char *match;
  int size;
  int fromlen;
  int tolen;

  // 分别获取源字符串,需要被替换的字符串,用于替换的字符串的长度。
  size = strlen(src) + 1;
  fromlen = strlen(from);
  tolen = strlen(to);

  // 分配第一块足够大小的原始字符串空间。
  value = (char *)malloc(size);

  //由于需要返回"value",所以这里需要做一个副本。
  dst = value;

  // 开始之前,判断内存分配是否成功。
  if ( value != NULL ){
    // 一直循环直到没有找到匹配项。
    for ( ;; ){
      // 搜索from在src中第一次出现时的字符串。
      match = (char *) strstr(src, from);
      if ( match != NULL ){
        // 找出有多少个字符需要复制到'match'中。
        size_t count = match - src;

        // 由于需要重新分配内存,因此需要定义一个安全的临时变量。
        char *temp;

        // 计算被字符串被替换后总的字符串长度。
        size += tolen - fromlen;

        // 为新字符串重新分配内存。
        // temp = realloc(value, size);
        temp = (char *)realloc(value, size);

        if ( temp == NULL ){
          // 如果内存分配失败,那么就释放之前分配的内存并返回NULL。
          free(value);
          return NULL;
        }

        // 如果内存分配成功,但是我们最终会返回'value',因此需要将它指向
        // 现在内存地址。并且不要忘记指向正确的目的地地址。
        dst = temp + (dst - value);
        value = temp;

        // 从src拷贝count个字符到dest。
        memmove(dst, src, count);
        src += count;
        dst += count;

        // 从to拷贝tolen个字符到dst。
        memmove(dst, to, tolen);
        src += fromlen;
        dst += tolen;
      }else{	// 如果没有匹配的字符串
        strcpy(dst, src);		// 复制该字符串中剩余的部分(包括终止空字符)。
        break;
      }
    }
  }
  return value;
}

// ----------------------------------------------------------------------------
//
// 方法描述:
//		在一个LoadRunner字符串中查找并替换一个字符串。
//
// 参数说明:
//    lrparam    - LoadRunner源字符串参数名称
//    findstr    - LoadRunner源字符串中需要被替换的字符串
//    replacestr - LoadRunner用于替换的字符串
//
// 返回说明:
//		返回一个整数: 1表示成功,0表示失败。
//
// 示例说明:
//    lr_save_string( "welcome to china!", "LR_Parameter");
//    lr_replace_string( "LR_Parameter", "o", "-h-" );
//    lr_output_message( "%s", lr_eval_string("{LR_Parameter}") );
//
// ----------------------------------------------------------------------------
int lr_replace_string( const char *lrparam, char *findstr, char *replacestr ){
  int res = 0;
  char *result_str;
  char lrp[1024];

  // 格式化LoadRunner参数名称
  sprintf( lrp, "{%s}", lrparam);

  // 查找并替换字符串
  result_str = replaceString( lr_eval_string(lrp), findstr, replacestr );

  // 结果处理
  if (result_str != NULL ){
    lr_save_string( result_str, lrparam );
    free( result_str );
    res = 1;
  }
  return res;
}


// ----------------------------------------------------------------------------
//
//  LoadRunner中调用DEMO
//
//  #include "lr_replace_string.h"
//
//  Action()
//  {
// 		//FilterID是loarunner的参数化数据
//		lr_save_string(lr_eval_string("{FilterID}"),"Filter_ID");
// 		lr_replace_string("Filter_ID","#","%23");
//		lr_output_message("%s", lr_eval_string("{Filter_ID}"));
//
// 		return 0;
//	}
//
// ----------------------------------------------------------------------------

编译、执行查看测试结果,测试通过。
在这里插入图片描述

4. 使用Controller创建、控制运行性能测试

使用Controller时,需要了解的一些定义

手动场景,按照自定义配置进行测试。
面向目标场景,按照需要达到什么目标去配置进行测试。

LoadRunner 脚本,即使用VUGEN来编写的脚本
系统或单元测试 dll文件、jar包等可以用来执行的

Machines(Load Generators)
进行加压的机器

Vusers
虚拟用户

Scheduling
如何加载运行

Monitors
过程监控测试

Goal-oriented
目标场景

Manual
手动场景

工作流程、工作原理
在这里插入图片描述
在这里插入图片描述

新建场景
在这里插入图片描述
在这里插入图片描述
功能依次为:启动、虚拟用户、添加测试组、删除测试组、运行设置、详细信息、查看脚本、虚拟服务
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

计划方式根据场景和组不同,全局计划也跟着改变,可以自行测试一下,很好理解。
不同组可以设置不同的任务,实现不同脚本不同的并发数。

设置好Controller后,保存文件,文件的后缀为.lrs。

运行压测场景,由于流水号随机号设置了0~100 导致有重复的流水号,所以有失败事务,后续需要改成唯一值或者将随机数的范围扩大。
在这里插入图片描述

5. 使用Analysis进行运行结果分析

通常由Controller跳转进行Analysis软件的打开

这种方式打开不加载运行结果
在这里插入图片描述

在这里插入图片描述

勾选自动加载分析后,Controller运行完毕后会自动打开分析软件。
如果没有勾选,点击下图图标可以打开分析软件
在这里插入图片描述

打开软件,查看压测结果
在这里插入图片描述
在这里插入图片描述

查看数据库压测结果,是否还有死锁交易
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/316208.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

jmap使用

jmap 是 Java 虚拟机 (JVM) 中的一个命令行工具&#xff0c;用于生成堆转储。这个工具对于诊断内存问题、分析内存占用情况等非常有用。 jmap 官方文档 bash: jmap: command not found 命令找不到 # jmap -dump <pid>jmap -dump 137886 安装一下java-devel yum -y in…

6.2 声音编辑工具GoldWave5简介(6)

3&#xff0e;选择【选项】|【控制器属性】命名或单击“控制器”面板上的“设置控制器属性”按钮&#xff0c;打开“控制器属性”对话框&#xff0c;将“音量”选项卡中的“麦克风”选项打上勾&#xff0c;使GoldWave只能录制来自麦克风的声音。如果要录制电脑内部的声音&#…

ASP.NET进销存系统源码

ASP.NET进销存系统源码 功能介绍&#xff1a; 财务 销售清单&#xff0c;填写销售单&#xff0c;客户管理&#xff0c;添加客户资料 销售 销售清单&#xff0c;填写销售单&#xff0c;客户管理&#xff0c;添加客户资料 仓库 仓库结存&#xff0c;仓库盘点&#xff0c;盘点结…

SpringBoot集成RabbitMq,RabbitMq消费与生产,消费失败重发机制,发送签收确认机制

RabbitMq消费与生产&#xff0c;消费失败重发机制&#xff0c;发送确认机制&#xff0c;消息发送结果回执 1. RabbitMq集成spring bootRabbitMq集成依赖RabbitMq配置RabbitMq生产者&#xff0c;队列&#xff0c;交换通道配置&#xff0c;消费者示例 2. RabbitMq消息确认机制消息…

PHP项目添加分布式锁,这里是ThinkPHP8框架实现分布式锁

背景&#xff1a;公司旧项目&#xff0c;最初访问量不多&#xff0c;单机部署的。后来&#xff0c;访问量上来了&#xff0c;有阵子很卡&#xff0c;公司决定横向扩展&#xff0c;后端代码部署了三台服务器。部署调整后&#xff0c;有用户反馈&#xff0c;一个订单支付了三次。…

C/S架构,集成三维影像后处理功能,自主版权的一套医院PACS系统源码

一、PACS简介 PACS&#xff08;PictureArchivingandCommunicationsSystem&#xff09;即图像存储与传输系统&#xff0c;是应用于医院的数字医疗设备如CT、MR&#xff08;磁共振&#xff09;、US&#xff08;超声成像&#xff09;、X光机、DSA&#xff08;数字减影&#xff09…

基于卡尔曼滤波的声源跟踪方法研究

基于卡尔曼滤波的声源跟踪方法研究 摘 要一、研究意义二、研究内容三、算法介绍3.1基于到达时间差的定位算法3.1.1算法原理介绍3.1.2仿真实验设计与分析 3.2扩展卡尔曼滤波算法3.2.1算法的基本原理3.2.2仿真实验及分析 3.3无迹卡尔曼滤波算法3.3.1算法的基本原理3.3.2仿真实验及…

VGAN实现视网膜图像血管分割(基于pytorch)

背景介绍 VGAN&#xff08;Retinal Vessel Segmentation in Fundoscopic Images with Generative Adversarial Networks&#xff09;出自2018年的一篇论文&#xff0c;尝试使用生成性对抗网络实现视网膜血管分割的任务,原论文地址&#xff1a;https://arxiv.org/abs/1706.0931…

用通俗易懂的方式讲解:十分钟读懂 Stable Diffusion 运行原理

AIGC 热潮正猛烈地席卷开来&#xff0c;可以说 Stable Diffusion 开源发布把 AI 图像生成提高了全新高度&#xff0c;特别是 ControlNet 和 T2I-Adapter 控制模块的提出进一步提高生成可控性&#xff0c;也在逐渐改变一部分行业的生产模式。惊艳其出色表现&#xff0c;也不禁好…

大语言模型下载,huggingface和modelscope加速

huggingface 下载模型 如果服务器翻墙了&#xff0c;不用租机器 如果服务器没翻墙&#xff0c;可以建议使用下面的方式 可以租一台**autodl**不用显卡的机器&#xff0c;一小时只有1毛钱&#xff0c;启动学术加速&#xff0c;然后下载&#xff0c;下载完之后&#xff0c;用scp…

Java重修第五天—面向对象2

通过学习本篇文章可以掌握如下知识 static&#xff1b;设计单例&#xff1b;继承。 之前文章我们已经对面向对象进行了入门学习&#xff0c;这篇文章我们就开始深入了解面向对象设计。 static 我们定义了一个 Student类&#xff0c;增加姓名属性&#xff1a;name &#xff1…

Spring Task 任务调度工具

大家好我是苏麟 , 今天聊聊Spring Task 任务调度工具 Spring Task Spring Task 是Spring框架提供的任务调度工具&#xff0c;可以按照约定的时间自动执行某个代码逻辑。 定位&#xff1a;定时任务框架 作用&#xff1a;定时自动执行某段Java代码 什么是定时任务 ? 通过时…

009-Zynq基操之如何去玩转PL向PS的中断(对新手友好,走过路过千万不要错过)

文章目录 前言一、PL-PS的中断是啥&#xff1f;二、PL-PS端中断详细步骤1.ZYNQ核配置2.PS端中断函数配置3.需要拓展多个中断函数 总结 前言 本设计跟我的ZYNQ实战合集专栏中的脉冲触发电路有关系&#xff0c;也正好趁这个机会讲述一下PL-PS的中断系统&#xff0c;如何去触发中…

为什么不直接public,多此一举用get、set,一文给你说明白

文章目录 1. 封装性&#xff08;Encapsulation&#xff09;2. 验证与逻辑处理3. 计算属性&#xff08;Computed Properties&#xff09;4. **跟踪变化&#xff08;Change Tracking&#xff09;5. 懒加载与延迟初始化&#xff08;Lazy Initialization&#xff09;6. 兼容性与未来…

【Leetcode】2182. 构造限制重复的字符串

文章目录 题目思路代码 题目 2182. 构造限制重复的字符串 问题&#xff1a;给你一个字符串 s 和一个整数 repeatLimit &#xff0c;用 s 中的字符构造一个新字符串 repeatLimitedString &#xff0c;使任何字母 连续 出现的次数都不超过 repeatLimit 次。你不必使用 s 中的全…

高效便捷的远程管理利器——Royal TSX for Mac软件介绍

Royal TSX for Mac是一款功能强大、操作便捷的远程管理软件。无论是远程桌面、SSH、VNC、Telnet还是FTP&#xff0c;用户都可以通过Royal TSX轻松地远程连接和管理各种服务器、计算机和网络设备。 Royal TSX for Mac提供了直观的界面和丰富的功能&#xff0c;让用户能够快速便…

新版云进销存ERP销售库存仓库员工管理系统源码

新版云进销存ERP销售库存仓库员工管理系统源码 系统介绍&#xff1a;2022版本,带合同报价单打印&#xff0c;修复子账号不显示新加客户的BUG&#xff0c;还有其他方面的优化。 简单方便。 功能强大&#xff0c;系统采用phpMYSQL开发&#xff0c;B/S架构&#xff0c;方便随地使用…

红队打靶练习:HOLYNIX: V1

目录 信息收集 1、arp 2、netdiscover 3、nmap 4、nikto whatweb 目录探测 1、gobuster 2、dirsearch 3、dirb 4、feroxbuster WEB sqlmap 1、爆库 2、爆表 3、爆列 4、爆字段 后台登录 1、文件上传 2、文件包含 3、越权漏洞 反弹shell 提权 总结 信息…

SpringSecurity入门demo(二)表单认证

上一篇博客集成 Spring Security&#xff0c;使用其默认生效的 HTTP 基本认证保护 URL 资源&#xff0c;下面使用表单认证来保护 URL 资源。 一、默认表单认证&#xff1a; 代码改动&#xff1a;自定义WebSecurityConfig配置类 package com.security.demo.config; import or…

最新AI绘画Midjourney绘画提示词Prompt大全

一、Midjourney绘画工具 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭…