├── .gitignore ├── README.md ├── application ├── cert_files │ ├── server.crt │ └── server.key ├── orderservice.py ├── response.xml └── templates │ └── index.html ├── automation ├── auto_stress_test.sh ├── auto_stress_test_jenkins.sh ├── order_auto.jmx ├── order_auto_jenkins.jmx └── users.csv ├── image └── PKQ.jpg ├── jars └── mysql-connector-java-8.0.15.jar ├── jmx ├── Class_BaiduNews_1117.jmx ├── PreClassJaveReq_1124.jmx ├── PreClassMenu.jmx ├── PreClassMenu_1117.jmx ├── PreClassPrepare_BaiduNews.jmx ├── UploadFile.jmx ├── grafana_test.jmx ├── jsr233_proc.jmx ├── orderservice.jmx ├── orderusers.csv ├── processors.jmx ├── test.jmx ├── timer.jmx ├── users.csv └── xml_data.jmx ├── shell ├── jmeter_dashboard.json ├── startGrafana.sh └── startInfluxdb.sh ├── sql └── order.sql └── unicode2utf8 └── unicode2utf8.js /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.iml 3 | .DS_Store 4 | target/ 5 | *.swp 6 | *.swo 7 | *.txt12 8 | *.log 9 | logs/ 10 | /target 11 | .project 12 | .vagrant 13 | .classpath 14 | .settings 15 | *.key 16 | ~*.doc 17 | *.pdb 18 | dependency-reduced-pom.xml 19 | ~$*.pptx 20 | myTestSpring/notify-subscription.log.* 21 | *.log.* 22 | *.txt 23 | automation/PreClassMenu_auto_*.jmx 24 | automation/test_*.jtl 25 | application/upload/*.* 26 | automation/web_* 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 压力测试项目,练习用 2 | 包含: JMeter压测脚本,模拟被测试的接口应用,自动化压测样例代码 3 | 4 | 1. jmeter演示知识点: 5 | - Get请求编写 6 | - Get请求的传参 7 | - 获取返回值 8 | - Post请求编写 9 | - Post请求传参数 10 | - 获取返回值 11 | - JSON解析 12 | - 正则匹配 13 | - 动态参数传递 14 | - 公共参数配置 15 | - CSV导入参数配置 16 | 17 | 2. 模拟接口服务的启动方法 18 | 路径:iJmeter/application 19 | python3 ${path}/orderservice.py 20 | 21 | 3. 自动化压测 22 | - 代码位置: automation/auto_stress_test.sh 23 | - 运行之前需要在本机配置环境变量 jmeter_path,将其指向jmeter安装的根目录 24 | export jmeter_path=/jmeter_root_path/ 25 | - 自动化压测会在运行时依次、自动执行并发压测,并发数 10 20 30 40 50, 每组压测60秒 26 | - 运行代码的时候请先确保当前路径处于automation目录下,然后运行 ./auto_stress_test.sh 27 | -------------------------------------------------------------------------------- /application/cert_files/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICTzCCAbgCCQDeWLuqGqflXDANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQGEwJj 3 | bjELMAkGA1UECAwCYmoxCzAJBgNVBAcMAmN5MQswCQYDVQQKDAJwdDELMAkGA1UE 4 | CwwCaG0xCzAJBgNVBAMMAnFxMRwwGgYJKoZIhvcNAQkBFg1xcUBwaW50ZWMuY29t 5 | MB4XDTIwMDkwNDA4NTkwOFoXDTIxMDkwNDA4NTkwOFowbDELMAkGA1UEBhMCY24x 6 | CzAJBgNVBAgMAmJqMQswCQYDVQQHDAJjeTELMAkGA1UECgwCcHQxCzAJBgNVBAsM 7 | AmhtMQswCQYDVQQDDAJxcTEcMBoGCSqGSIb3DQEJARYNcXFAcGludGVjLmNvbTCB 8 | nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1IX6zAeMKlz2p5BcpVxe/f41iWmK 9 | /ZRrpAPva9s+ZgY6F33AShonZFOulOYrcfmxXoeN/IGY0tAhnQrgYo3RsBh6KLRu 10 | lVYD6JKu1NAw5Pb5haFpcn0hMUFc16LnNcry4QL1nJhSxBGefu4x5zJYCtRCXr4H 11 | iv7FeB56EkbY5H8CAwEAATANBgkqhkiG9w0BAQUFAAOBgQDAyF4QFEpZ3riOxU/C 12 | l/0PVCxOhTiw0MMY0SpWkc4Qa5iBz3W2+XVhzZLnkwbOZZCh831cTTWPhijbi6r3 13 | OSW6Aa6FF4dLWtzpEQodteLzHI4g/m/gYtAyRci83woaP93aThl4bxl62JinUpny 14 | BUWQ3EnwFrgYOuA/vZkqJFgmLA== 15 | -----END CERTIFICATE----- 16 | -------------------------------------------------------------------------------- /application/cert_files/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: DES-EDE3-CBC,3663BEA7A3537664 4 | 5 | CHxu1v2jRzkQdw+LlLC5rhPcUB3eS1Pp94VjQQhjN5a5F8/nvvLWQ1gcG44qweF4 6 | ZxJwa3Ckgh/cpnyN2tSkxoP0Oge4VYxus3kLESidvpiFKCSgKwr8CpubDR79HgWY 7 | UYI6fXV0/6if1/Csezg27wcnByLAT8TuqGIl9mU7ILWpM/XNOJJhbytmUcCh56ST 8 | 24trbhE3fweVj4e63z/ddgKqPTTS6wRe1FZOiMkQ7+GCUG7mN+F9tLwFVUQyt8EF 9 | gDfHUOdt/ZoorciO+507VXV2PF5ahmhyTx2n7hSQsmIoqOL4o6E+OVgup9+BfkLR 10 | naFbYa7nUMRGYMPGsTxBWHg0bKQcuh397YAh2lmYn0nKcZQedM5OlN1IhtSosmun 11 | OQB7keEgk8QyrhBmuTdcrYgTNB+1kokDcsjopoI4rMJk/0sM4WgJhFT1PBv8pVVR 12 | ncFZkQZgAOFbhgEWdyYsRnHGt3FWSKEZ8YwWTV0f9sWWY43YsUGGqbgxDyuRECNu 13 | /SLj27aewaJAsfTfT2wkDOKZwg2nKVQ3dCBSg5LiwG4v0HMBtjbE497cr8Gf7xBF 14 | HZcdLFmQzmPTFa28IDtXi0ngklduRpbcrnEAF2LfaEF2GEEvXxhBIQvByTsfPtXD 15 | ZZ2sZbST57TyIB7tlMrZ55xBc9ycNxrEL9dyFGr4ZIhsPlKaminiapQUk2O8H1rO 16 | LYIynAXV/Zk19p0bXo+DqrY34dh/XFQSPKwP3hgVj+uPie/+8hQFMDnMUrBNwo6B 17 | YlGq1ie9+7I9epyq6I7IxWDB6hG11nD+7abBRbyTVio= 18 | -----END RSA PRIVATE KEY----- 19 | -------------------------------------------------------------------------------- /application/orderservice.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | import time 4 | 5 | from flask import Flask, request, make_response, jsonify, render_template 6 | from werkzeug.utils import secure_filename 7 | # from skywalking import agent, config 8 | 9 | app = Flask(__name__) 10 | user_token_dic = { 11 | 'user01': '3b6754f00bb0063071c5b71ce2b56b4ed0ce56a63493e785bea85b74c41ce200' 12 | , 'user02': 'dcdc7286f6822dc5a4b54d2ce53f40ae0e562d7fc06d64b8dd332f7d528c7c67' 13 | , 'user03': '04c4fba92b3451b16daedbbc7dd4cec84b8a88333f3da60626c6abbfdc829a02' 14 | , 'user04': '3c3a7fa64c34e2530b708ec9bdeedd49e0098bfd3239b1cd58985feeb38531b8' 15 | , 'user05': 'abb9d47918055902a8a6f3f8e86cd962d37d49647e9b51bdd7f7d67ff95f9864' 16 | , 'user06': '6b2b8f34dd4ad1812a76a7037ed23d9ebc0189070320fa32dc610a79852419c7' 17 | , 'user07': 'aac287a1eeb39d1983aaa732a7a5f33a64918adb1e88da6b344d2090eaed7239' 18 | , 'user08': '3d0c7ff2ad3063bc0e93befeef895def90290114ee590ca09b60f8e4476aca27' 19 | , 'user09': 'a0a9941e29cebdd732a2a57411f14d45e14bc3061d66c2e1c30eca421ed0b02d' 20 | , 'user10': '34467677a88fc7966807c26ced0972cc775be9e6983d4bfbd2a0981a4350dcfd' 21 | } 22 | menu_json = { 23 | "code": "200", 24 | "breakfast": [ 25 | { 26 | "menu_nunber": "01", 27 | "menu_price": 5.50, 28 | "menu_name": "小笼包" 29 | }, 30 | { 31 | "menu_nunber": "02", 32 | "menu_price": 3.00, 33 | "menu_name": "八宝粥" 34 | }, 35 | { 36 | "menu_nunber": "03", 37 | "menu_price": 1.50, 38 | "menu_name": "油条" 39 | }, 40 | { 41 | "menu_nunber": "04", 42 | "menu_price": 1.00, 43 | "menu_name": "茶叶蛋" 44 | }, 45 | { 46 | "menu_nunber": "05", 47 | "menu_price": 1.50, 48 | "menu_name": "豆包" 49 | }, 50 | { 51 | "menu_nunber": "06", 52 | "menu_price": 2.00, 53 | "menu_name": "烧饼" 54 | } 55 | ], 56 | "lunch": [ 57 | { 58 | "menu_nunber": "07", 59 | "menu_price": 17.00, 60 | "menu_name": "宫保鸡丁" 61 | }, 62 | { 63 | "menu_nunber": "08", 64 | "menu_price": 25.00, 65 | "menu_name": "锅包肉" 66 | }, 67 | { 68 | "menu_nunber": "09", 69 | "menu_price": 35.00, 70 | "menu_name": "糖醋排骨" 71 | }, 72 | { 73 | "menu_nunber": "10", 74 | "menu_price": 30.00, 75 | "menu_name": "蒜台炒肉片" 76 | }, 77 | { 78 | "menu_nunber": "11", 79 | "menu_price": 25.50, 80 | "menu_name": "酸辣土豆丝" 81 | }, 82 | { 83 | "menu_nunber": "12", 84 | "menu_price": 32.00, 85 | "menu_name": "红烧茄子" 86 | } 87 | ], 88 | "dinner": [ 89 | { 90 | "menu_nunber": "13", 91 | "menu_price": 21.00, 92 | "menu_name": "辣椒炒肉" 93 | }, 94 | { 95 | "menu_nunber": "14", 96 | "menu_price": 15.00, 97 | "menu_name": "豌豆肉片汤" 98 | }, 99 | { 100 | "menu_nunber": "15", 101 | "menu_price": 26.00, 102 | "menu_name": "原味五花肉卷" 103 | }, 104 | { 105 | "menu_nunber": "16", 106 | "menu_price": 20.00, 107 | "menu_name": "醋溜白菜" 108 | }, 109 | { 110 | "menu_nunber": "17", 111 | "menu_price": 25.50, 112 | "menu_name": "地三鲜" 113 | }, 114 | { 115 | "menu_nunber": "18", 116 | "menu_price": 39.00, 117 | "menu_name": "红烧排骨" 118 | } 119 | ] 120 | } 121 | 122 | server_internal_error_data = { 123 | "code": "500", 124 | "message": "Server internal error." 125 | } 126 | 127 | UPLOAD_FOLDER = 'upload' 128 | app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER 129 | basedir = os.path.abspath(os.path.dirname(__file__)) 130 | ALLOWED_EXTENSIONS = set(['txt', 'png', 'jpg', 'xls', 'JPG', 'PNG', 'xlsx', 'gif', 'GIF', 'doc', 'docx', 'ppt', 'pptx']) 131 | 132 | enable_agent = True if os.getenv('enable_agent', 'false') == 'true' else False 133 | if enable_agent: 134 | print('Start skywalking agent for monitoring.') 135 | config.init( 136 | agent_collector_backend_services="localhost:11800", 137 | agent_name="python-order-service", 138 | agent_instance_name="python-order-service-instance" 139 | ) 140 | agent.start() 141 | 142 | 143 | @app.route("/api/v1/user/login", methods=['POST']) 144 | def login(): 145 | """登录接口,输入参数格式: 146 | { 147 | "authRequest": { 148 | "userName": "[username]", 149 | "password": "[password]" 150 | } 151 | } 152 | 153 | :return 154 | Success : http code 200 155 | { 156 | "code": "200", 157 | "message": "login success", 158 | "access_token": "3b6754f00bb0063071c5b71ce2b56b4ed0ce56a63493e785bea85b74c41ce200" 159 | } 160 | 161 | Fail : http code 401 162 | { 163 | "code": "401", 164 | "message": "login fail" 165 | } 166 | """ 167 | try: 168 | raw_data = request.get_data(as_text=True) 169 | data = json.loads(raw_data) 170 | username = data.get("authRequest").get("userName") 171 | password = data.get("authRequest").get("password") 172 | 173 | if username not in user_token_dic.keys() or password != 'pwd': 174 | print('Username or password error!') 175 | login_fail_resp_data = { 176 | "code": "401", 177 | "message": "login fail" 178 | } 179 | return make_response(jsonify(login_fail_resp_data), '401') 180 | 181 | login_succ_resp_data = { 182 | "code": "200", 183 | "message": "login success", 184 | "access_token": user_token_dic.get(username) 185 | } 186 | 187 | return make_response(jsonify(login_succ_resp_data), '200') 188 | except Exception as ex: 189 | print(ex.msg) 190 | return make_response(jsonify(server_internal_error_data), '500') 191 | 192 | 193 | @app.route('/api/v1/menu/list', methods=['GET']) 194 | def list(): 195 | """菜单浏览接口 196 | 197 | :return: 菜单列表 198 | """ 199 | access_token = request.headers.get("accesstoken") 200 | 201 | if access_token is None: 202 | login_fail_resp_data = { 203 | "code": "401", 204 | "message": "Please login first." 205 | } 206 | return make_response(jsonify(login_fail_resp_data), '401') 207 | 208 | if access_token not in user_token_dic.values(): 209 | print('access_token error, please re-login.') 210 | login_fail_resp_data = { 211 | "code": "401", 212 | "message": "Unknown user info, please re-login." 213 | } 214 | return make_response(jsonify(login_fail_resp_data), '401') 215 | 216 | category = request.args.get("type") 217 | 218 | if category is not None: 219 | return make_response(jsonify(menu_json.get(category)), 200) 220 | 221 | return make_response(jsonify(menu_json), 200) 222 | 223 | 224 | @app.route("/api/v1/menu/confirm", methods=['POST']) 225 | def confirm(): 226 | """下单接口,输入参数格式: 227 | header = {'accesstoken' : ''} 228 | data: 229 | { 230 | "order_list": [ 231 | { 232 | "menu_nunber" : "01", 233 | "number" : 1 234 | }, 235 | { 236 | "menu_nunber" : "03", 237 | "number" : 2 238 | }, 239 | { 240 | "menu_nunber" : "04", 241 | "number" : 1 242 | }, 243 | { 244 | "menu_nunber" : "05", 245 | "number" : 3 246 | } 247 | ] 248 | } 249 | 250 | :return 251 | Success : http code 200 252 | { 253 | "code": "200", 254 | "message": "Order success.", 255 | "total": 7 256 | } 257 | 258 | not login : http code 401 259 | { 260 | "code": "401", 261 | "message": "Please login first." 262 | } 263 | """ 264 | try: 265 | access_token = request.headers.get("accesstoken") 266 | if access_token is None: 267 | login_fail_resp_data = { 268 | "code": "401", 269 | "message": "Please login first." 270 | } 271 | return make_response(jsonify(login_fail_resp_data), '401') 272 | 273 | raw_data = request.get_data(as_text=True) 274 | order_list = json.loads(raw_data).get("order_list") 275 | total = 0 276 | for order in order_list: 277 | total = total + order.get("number") 278 | time.sleep(0.6) 279 | 280 | order_success_resp_data = { 281 | "code": "200", 282 | "message": "Order success.", 283 | "total": total 284 | } 285 | return make_response(jsonify(order_success_resp_data), '200') 286 | except Exception: 287 | return make_response(jsonify(server_internal_error_data), '500') 288 | 289 | 290 | @app.route("/api/v1/user/logout", methods=['DELETE']) 291 | def logout(): 292 | """用户注销接口,输入参数格式: 293 | header = {'accesstoken' : ''} 294 | """ 295 | try: 296 | access_token = request.headers.get("accesstoken") 297 | 298 | if access_token not in user_token_dic.values(): 299 | print('access_token error, logout failed.') 300 | login_fail_resp_data = { 301 | "code": "401", 302 | "message": "Unknown user info, logout fail." 303 | } 304 | return make_response(jsonify(login_fail_resp_data), '401') 305 | 306 | login_succ_resp_data = { 307 | "code": "200", 308 | "message": "logout success" 309 | } 310 | 311 | return make_response(jsonify(login_succ_resp_data), '200') 312 | except Exception: 313 | return make_response(jsonify(server_internal_error_data), '500') 314 | 315 | 316 | # suffix validation 317 | def allowed_file(filename): 318 | return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS 319 | 320 | 321 | # upload file testing page 322 | @app.route('/', methods=['GET'], strict_slashes=False) 323 | def indexpage(): 324 | return render_template('index.html') 325 | 326 | 327 | # upload file 328 | @app.route('/uploadfile', methods=['POST'], strict_slashes=False) 329 | def api_upload(): 330 | file_dir = os.path.join(basedir, app.config['UPLOAD_FOLDER']) 331 | if not os.path.exists(file_dir): 332 | os.makedirs(file_dir) 333 | f = request.files['file'] # get the file name 334 | 335 | if f and allowed_file(f.filename): # Verify the file type 336 | fname = secure_filename(f.filename) 337 | ext = fname.rsplit('.', 1)[1] 338 | unix_time = time.time() 339 | new_filename = str(unix_time) + '.' + ext 340 | f.save(os.path.join(file_dir, new_filename)) 341 | print(f'{f.filename} upload success!') 342 | return jsonify({'code': 200, 'result': 'success', 'msg': f'file {f.filename} upload success'}) 343 | else: 344 | print(f'{f.filename} upload failed!') 345 | return jsonify( 346 | {'code': 500, 'result': 'failed', 'msg': f'file {f.filename} upload fail, please check the file type'}) 347 | 348 | 349 | if __name__ == "__main__": 350 | app.run(port=9091, debug=True, host='0.0.0.0') 351 | 352 | # Demo for https, password = 1234 353 | # app.run('0.0.0.0', debug=True, port=9091, ssl_context=(f'{os.path.abspath(os.curdir)}/cert_files/server.crt' 354 | # , f'{os.path.abspath(os.curdir)}/cert_files/server.key')) 355 | -------------------------------------------------------------------------------- /application/response.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /application/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 上传文件 3 |

上传文件

4 |
5 |

6 |

7 |

-------------------------------------------------------------------------------- /automation/auto_stress_test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # 压测脚本中设定的压测时间应为20秒 4 | export jmx_filename="order_auto.jmx" 5 | 6 | # 需要在系统变量中定义jmeter根目录的位置,如下 7 | # export jmeter_path="/your jmeter path/" 8 | 9 | echo "自动化压测开始" 10 | 11 | # 压测并发数列表 12 | thread_number_array=(10 20 30) 13 | for num in "${thread_number_array[@]}" 14 | do 15 | echo "压测并发数 ${num}" 16 | # 定义jtl结果文件名与压测报告路径 17 | export jtl_filename="test_${num}.jtl" 18 | export web_report_path_name="web_${num}" 19 | 20 | rm -f ${jtl_filename} 21 | rm -rf ${web_report_path_name} 22 | 23 | # JMeter 静默压测 + 生成html压测报告 24 | ${jmeter_path}/bin/jmeter -n -t ${jmx_filename} -l ${jtl_filename} -Jthread=${num} -e -o ${web_report_path_name} 25 | echo "结束压测并发数 ${num}" 26 | done 27 | echo "自动化压测全部结束" 28 | 29 | -------------------------------------------------------------------------------- /automation/auto_stress_test_jenkins.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # 压测脚本中设定的压测时间从Jenkins任务参数中传入,参数名称 duration 4 | # 生成的压测报告入口文件为 ./index.html 5 | export jmx_filename="order_auto_jenkins.jmx" 6 | 7 | # 需要在系统变量中定义jmeter根目录的位置,如下 8 | # export jmeter_path="/your jmeter path/" 9 | 10 | echo "自动化压测开始" 11 | 12 | rm -f index.html 13 | echo "" > index.html 14 | 15 | 16 | rm -f *.jtl 17 | rm -rf web_* 18 | # 压测并发数列表 19 | thread_number_array=($thread_number_list) 20 | for num in "${thread_number_array[@]}" 21 | do 22 | echo "压测并发数 ${num}" 23 | # 定义jtl结果文件名与压测报告路径 24 | export jtl_filename="test_${num}.jtl" 25 | export web_report_path_name="web_${num}" 26 | 27 | # JMeter 静默压测 + 生成html压测报告 28 | ${jmeter_path}/bin/jmeter -n -t ${jmx_filename} -l ${jtl_filename} -Jthread=${num} -Jduration=${duration} -e -o ${web_report_path_name} 29 | echo "结束压测并发数 ${num}" 30 | echo "${web_report_path_name}

" >> index.html 31 | done 32 | echo "自动化压测全部结束" 33 | 34 | -------------------------------------------------------------------------------- /automation/order_auto.jmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | false 7 | true 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | continue 17 | 18 | false 19 | -1 20 | 21 | ${__P(thread,20)} 22 | 1 23 | true 24 | 20 25 | 26 | false 27 | 28 | 29 | 30 | false 31 | 32 | saveConfig 33 | 34 | 35 | true 36 | true 37 | true 38 | 39 | true 40 | true 41 | true 42 | true 43 | false 44 | true 45 | true 46 | false 47 | false 48 | false 49 | true 50 | false 51 | false 52 | false 53 | true 54 | 0 55 | true 56 | true 57 | true 58 | true 59 | true 60 | true 61 | 62 | 63 | 64 | 65 | 66 | 67 | false 68 | 69 | saveConfig 70 | 71 | 72 | true 73 | true 74 | true 75 | 76 | true 77 | true 78 | true 79 | true 80 | false 81 | true 82 | true 83 | false 84 | false 85 | false 86 | true 87 | false 88 | false 89 | false 90 | true 91 | 0 92 | true 93 | true 94 | true 95 | true 96 | true 97 | true 98 | 99 | 100 | 101 | 102 | 103 | 104 | , 105 | UTF-8 106 | ./users.csv 107 | true 108 | true 109 | true 110 | shareMode.all 111 | false 112 | no,username,password 113 | 114 | 115 | 116 | 117 | 118 | host 119 | localhost 120 | = 121 | 122 | 123 | port 124 | 9091 125 | = 126 | 127 | 128 | protocol 129 | http 130 | = 131 | 132 | 133 | wait 134 | 100 135 | = 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | accesstoken 144 | ${accesstoken} 145 | 146 | 147 | Content-Type 148 | application/json 149 | 150 | 151 | 152 | 153 | 154 | true 155 | 156 | saveConfig 157 | 158 | 159 | true 160 | true 161 | true 162 | 163 | true 164 | true 165 | true 166 | true 167 | false 168 | true 169 | true 170 | true 171 | false 172 | true 173 | true 174 | false 175 | true 176 | false 177 | true 178 | 0 179 | true 180 | true 181 | true 182 | true 183 | true 184 | true 185 | 186 | 187 | ./error_log.xml 188 | 189 | 190 | 191 | false 192 | true 193 | 194 | 195 | 196 | true 197 | 198 | 199 | 200 | false 201 | { 202 | "authRequest": { 203 | "userName": "${username}", 204 | "password": "${password}" 205 | } 206 | } 207 | = 208 | 209 | 210 | 211 | ${host} 212 | ${port} 213 | ${protocol} 214 | 215 | api/v1/user/login 216 | POST 217 | true 218 | false 219 | true 220 | false 221 | 222 | 1000 223 | 224 | 225 | 226 | 227 | accesstoken 228 | $.access_token 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | ${host} 238 | ${port} 239 | ${protocol} 240 | 241 | /api/v1/menu/list 242 | GET 243 | true 244 | false 245 | true 246 | false 247 | 248 | 249 | 250 | 251 | 252 | 253 | ${wait} 254 | 255 | 256 | 257 | 258 | 259 | false 260 | String s2 = new String(prev.getResponseData(), "UTF-8"); 261 | //---------------一下步骤为转码过程--------------- 262 | char aChar; 263 | int len = s2.length(); 264 | StringBuffer outBuffer = new StringBuffer(len); 265 | for (int x = 0; x < len;) 266 | { 267 | aChar = s2.charAt(x++); 268 | if (aChar == '\\') { 269 | aChar = s2.charAt(x++); 270 | if (aChar == 'u') { 271 | int 272 | value = 0; 273 | for (int i = 0; 274 | i < 4; 275 | i++ 276 | ) 277 | { 278 | aChar = s2.charAt(x++); 279 | switch (aChar) { 280 | case'0': 281 | case'1': 282 | case'2': 283 | case'3': 284 | case'4': 285 | case'5': 286 | case'6': 287 | case'7': 288 | case'8': 289 | case'9': 290 | value = (value << 4) + aChar - '0'; 291 | break; 292 | case'a': 293 | case'b': 294 | case'c': 295 | case'd': 296 | case'e': 297 | case'f': 298 | value = (value << 4) + 10 + aChar - 'a'; 299 | break; 300 | case'A': 301 | case'B': 302 | case'C': 303 | case'D': 304 | case'E': 305 | case'F': 306 | value = (value << 4) + 10 + aChar - 'A'; 307 | break; 308 | default: 309 | throw new IllegalArgumentException( 310 | "Malformed   \\uxxxx  encoding."); 311 | } 312 | } 313 | outBuffer.append((char) 314 | value 315 | ) 316 | ; 317 | } else { 318 | if (aChar == 't') 319 | aChar = '\t'; 320 | else if (aChar == 'r') 321 | aChar = '\r'; 322 | else if (aChar == 'n') 323 | aChar = '\n'; 324 | else if (aChar == 'f') 325 | aChar = '\f'; 326 | outBuffer.append(aChar); 327 | } 328 | } else 329 | outBuffer.append(aChar); 330 | } 331 | //-----------------以上内容为转码过程--------------------------- 332 | //将转成中文的响应结果在查看结果树中显示 333 | 334 | prev.setResponseData(outBuffer.toString()); 335 | 336 | 337 | 338 | 339 | true 340 | 341 | 342 | 343 | false 344 | { 345 | "order_list": [ 346 | { 347 | "menu_nunber" : "01", 348 | "number" : 2 349 | }, 350 | { 351 | "menu_nunber" : "03", 352 | "number" : 2 353 | }, 354 | { 355 | "menu_nunber" : "04", 356 | "number" : 2 357 | }, 358 | { 359 | "menu_nunber" : "05", 360 | "number" : 3 361 | } 362 | ] 363 | } 364 | = 365 | 366 | 367 | 368 | ${host} 369 | ${port} 370 | ${protocol} 371 | 372 | /api/v1/menu/confirm 373 | POST 374 | true 375 | false 376 | true 377 | false 378 | 379 | 380 | 381 | 382 | 383 | 384 | ${wait} 385 | 386 | 387 | 388 | $.message 389 | Order success. 390 | true 391 | false 392 | false 393 | true 394 | 395 | 396 | 397 | $.total 398 | 9 399 | true 400 | false 401 | false 402 | true 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | ${host} 411 | ${port} 412 | ${protocol} 413 | 414 | /api/v1/user/logout 415 | DELETE 416 | true 417 | false 418 | true 419 | false 420 | 421 | 422 | 423 | 424 | 425 | 426 | ${wait} 427 | 428 | 429 | 430 | 431 | 432 | true 433 | true 434 | true 435 | 436 | 437 | 438 | 439 | 440 | 441 | influxdbMetricsSender 442 | org.apache.jmeter.visualizers.backend.influxdb.HttpMetricsSender 443 | = 444 | 445 | 446 | influxdbUrl 447 | http://localhost:8086/write?db=jmeter 448 | = 449 | 450 | 451 | application 452 | OrderService 453 | = 454 | 455 | 456 | measurement 457 | jmeter 458 | = 459 | 460 | 461 | summaryOnly 462 | false 463 | = 464 | 465 | 466 | samplersRegex 467 | .* 468 | = 469 | 470 | 471 | percentiles 472 | 90;95;99 473 | = 474 | 475 | 476 | testTitle 477 | OrderService 478 | = 479 | 480 | 481 | eventTags 482 | 483 | = 484 | 485 | 486 | 487 | org.apache.jmeter.visualizers.backend.influxdb.InfluxdbBackendListenerClient 488 | 489 | 490 | 491 | 492 | 493 | 494 | -------------------------------------------------------------------------------- /automation/order_auto_jenkins.jmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | false 7 | true 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | continue 17 | 18 | false 19 | -1 20 | 21 | ${__P(thread, 20)} 22 | 1 23 | true 24 | ${__P(duration, 20)} 25 | 26 | false 27 | 28 | 29 | 30 | false 31 | 32 | saveConfig 33 | 34 | 35 | true 36 | true 37 | true 38 | 39 | true 40 | true 41 | true 42 | true 43 | false 44 | true 45 | true 46 | false 47 | false 48 | false 49 | true 50 | false 51 | false 52 | false 53 | true 54 | 0 55 | true 56 | true 57 | true 58 | true 59 | true 60 | true 61 | 62 | 63 | 64 | 65 | 66 | 67 | false 68 | 69 | saveConfig 70 | 71 | 72 | true 73 | true 74 | true 75 | 76 | true 77 | true 78 | true 79 | true 80 | false 81 | true 82 | true 83 | false 84 | false 85 | false 86 | true 87 | false 88 | false 89 | false 90 | true 91 | 0 92 | true 93 | true 94 | true 95 | true 96 | true 97 | true 98 | 99 | 100 | 101 | 102 | 103 | 104 | , 105 | UTF-8 106 | /Users/jizhiqian/workspace/studio/iJmeter/jmx/users.csv 107 | true 108 | true 109 | true 110 | shareMode.all 111 | false 112 | no,username,password 113 | 114 | 115 | 116 | 117 | 118 | host 119 | localhost 120 | = 121 | 122 | 123 | port 124 | 9091 125 | = 126 | 127 | 128 | protocol 129 | http 130 | = 131 | 132 | 133 | wait 134 | 100 135 | = 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | accesstoken 144 | ${access_token} 145 | 146 | 147 | Content-Type 148 | application/json 149 | 150 | 151 | 152 | 153 | 154 | true 155 | 156 | 157 | 158 | false 159 | { 160 | "authRequest": { 161 | "userName": "${username}", 162 | "password": "${password}" 163 | } 164 | } 165 | = 166 | 167 | 168 | 169 | ${host} 170 | ${port} 171 | ${protocol} 172 | 173 | api/v1/user/login 174 | POST 175 | true 176 | false 177 | true 178 | false 179 | 180 | 181 | 182 | 183 | 184 | 185 | access_token 186 | $.access_token 187 | 0 188 | 189 | 190 | 191 | $.message 192 | login success 193 | true 194 | false 195 | false 196 | true 197 | 198 | 199 | 200 | ${wait} 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | ${host} 209 | ${port} 210 | ${protocol} 211 | 212 | /api/v1/menu/list 213 | GET 214 | true 215 | false 216 | true 217 | false 218 | 219 | 220 | 221 | 222 | 223 | 224 | ${wait} 225 | 226 | 227 | 228 | 229 | true 230 | 231 | 232 | 233 | false 234 | { 235 | "order_list": [ 236 | { 237 | "menu_nunber" : "01", 238 | "number" : 2 239 | }, 240 | { 241 | "menu_nunber" : "03", 242 | "number" : 2 243 | }, 244 | { 245 | "menu_nunber" : "04", 246 | "number" : 2 247 | }, 248 | { 249 | "menu_nunber" : "05", 250 | "number" : 3 251 | } 252 | ] 253 | } 254 | = 255 | 256 | 257 | 258 | ${host} 259 | ${port} 260 | ${protocol} 261 | 262 | /api/v1/menu/confirm 263 | POST 264 | true 265 | false 266 | true 267 | false 268 | 269 | 270 | 271 | 272 | 273 | 274 | ${wait} 275 | 276 | 277 | 278 | $.message 279 | Order success. 280 | true 281 | false 282 | false 283 | true 284 | 285 | 286 | 287 | $.total 288 | 9 289 | true 290 | false 291 | false 292 | true 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | ${host} 301 | ${port} 302 | ${protocol} 303 | 304 | /api/v1/user/logout 305 | DELETE 306 | true 307 | false 308 | true 309 | false 310 | 311 | 312 | 313 | 314 | 315 | 316 | ${wait} 317 | 318 | 319 | 320 | 321 | false 322 | true 323 | false 324 | 325 | 326 | 327 | 328 | 329 | 330 | influxdbMetricsSender 331 | org.apache.jmeter.visualizers.backend.influxdb.HttpMetricsSender 332 | = 333 | 334 | 335 | influxdbUrl 336 | http://localhost:8086/write?db=jmeter 337 | = 338 | 339 | 340 | application 341 | order 342 | = 343 | 344 | 345 | measurement 346 | jmeter 347 | = 348 | 349 | 350 | summaryOnly 351 | true 352 | = 353 | 354 | 355 | samplersRegex 356 | .* 357 | = 358 | 359 | 360 | percentiles 361 | 90;95;99 362 | = 363 | 364 | 365 | testTitle 366 | Order Testing 367 | = 368 | 369 | 370 | eventTags 371 | 372 | = 373 | 374 | 375 | 376 | org.apache.jmeter.visualizers.backend.influxdb.InfluxdbBackendListenerClient 377 | 378 | 379 | 380 | 381 | 382 | 383 | influxdbMetricsSender 384 | org.apache.jmeter.visualizers.backend.influxdb.HttpMetricsSender 385 | = 386 | 387 | 388 | influxdbUrl 389 | http://localhost:8086/write?db=jmeter 390 | = 391 | 392 | 393 | application 394 | Order Service 395 | = 396 | 397 | 398 | measurement 399 | jmeter 400 | = 401 | 402 | 403 | summaryOnly 404 | false 405 | = 406 | 407 | 408 | samplersRegex 409 | .* 410 | = 411 | 412 | 413 | percentiles 414 | 90;95;99 415 | = 416 | 417 | 418 | testTitle 419 | Order Service 420 | = 421 | 422 | 423 | eventTags 424 | 425 | = 426 | 427 | 428 | 429 | org.apache.jmeter.visualizers.backend.influxdb.InfluxdbBackendListenerClient 430 | 431 | 432 | 433 | 434 | 435 | 436 | -------------------------------------------------------------------------------- /automation/users.csv: -------------------------------------------------------------------------------- 1 | No.,username,password 2 | 1,user01,pwd 3 | 2,user02,pwd 4 | 3,user03,pwd 5 | 4,user04,pwd 6 | 5,user05,pwd 7 | 6,user06,pwd 8 | 7,user07,pwd 9 | 8,user08,pwd 10 | 9,user09,pwd 11 | 10,user10,pwd -------------------------------------------------------------------------------- /image/PKQ.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/princeqjzh/iJmeter/d7e7b79ffebb62562b552182ea63ac6be6ed3c38/image/PKQ.jpg -------------------------------------------------------------------------------- /jars/mysql-connector-java-8.0.15.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/princeqjzh/iJmeter/d7e7b79ffebb62562b552182ea63ac6be6ed3c38/jars/mysql-connector-java-8.0.15.jar -------------------------------------------------------------------------------- /jmx/PreClassJaveReq_1124.jmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | false 7 | true 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | continue 17 | 18 | false 19 | 1 20 | 21 | 100 22 | 1 23 | false 24 | 10 25 | 26 | 27 | 28 | 29 | false 30 | 31 | saveConfig 32 | 33 | 34 | true 35 | true 36 | true 37 | 38 | true 39 | true 40 | true 41 | true 42 | false 43 | true 44 | true 45 | false 46 | false 47 | false 48 | true 49 | false 50 | false 51 | false 52 | true 53 | 0 54 | true 55 | true 56 | true 57 | true 58 | true 59 | true 60 | 61 | 62 | 63 | 64 | 65 | 66 | false 67 | 68 | saveConfig 69 | 70 | 71 | true 72 | true 73 | true 74 | 75 | true 76 | true 77 | true 78 | true 79 | false 80 | true 81 | true 82 | false 83 | false 84 | false 85 | true 86 | false 87 | false 88 | false 89 | true 90 | 0 91 | true 92 | true 93 | true 94 | true 95 | true 96 | true 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | hostname 107 | localhost 108 | = 109 | 110 | 111 | 112 | com.test.stress.JHttpRequestSample 113 | 114 | 115 | 116 | false 117 | true 118 | false 119 | 120 | 121 | 122 | 123 | 124 | port 125 | 9091 126 | = 127 | 128 | 129 | protocol 130 | http 131 | = 132 | 133 | 134 | 135 | 136 | 137 | , 138 | 139 | /Users/jizhiqian/workspace/studio/iJmeter/jmx/users.csv 140 | true 141 | false 142 | true 143 | shareMode.all 144 | false 145 | no,username,password 146 | 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /jmx/PreClassMenu_1117.jmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | false 7 | true 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | continue 17 | 18 | false 19 | -1 20 | 21 | 5 22 | 1 23 | true 24 | 60 25 | 26 | 27 | 28 | 29 | false 30 | 31 | saveConfig 32 | 33 | 34 | true 35 | true 36 | true 37 | 38 | true 39 | true 40 | true 41 | true 42 | false 43 | true 44 | true 45 | false 46 | false 47 | false 48 | true 49 | false 50 | false 51 | false 52 | true 53 | 0 54 | true 55 | true 56 | true 57 | true 58 | true 59 | true 60 | 61 | 62 | 63 | 64 | 65 | 66 | , 67 | UTF-8 68 | /Users/jizhiqian/workspace/studio/iJmeter/jmx/users.csv 69 | true 70 | true 71 | true 72 | shareMode.all 73 | false 74 | no,username,password 75 | 76 | 77 | 78 | 79 | 80 | host 81 | localhost 82 | = 83 | 84 | 85 | port 86 | 9091 87 | = 88 | 89 | 90 | protocol 91 | http 92 | = 93 | 94 | 95 | 96 | 97 | 98 | false 99 | 100 | saveConfig 101 | 102 | 103 | true 104 | true 105 | true 106 | 107 | true 108 | true 109 | true 110 | true 111 | false 112 | true 113 | true 114 | false 115 | false 116 | false 117 | true 118 | false 119 | false 120 | false 121 | true 122 | 0 123 | true 124 | true 125 | true 126 | true 127 | true 128 | true 129 | 130 | 131 | 132 | 133 | 134 | 135 | true 136 | 137 | 138 | 139 | false 140 | { 141 | "authRequest": { 142 | "userName": "${username}", 143 | "password": "${password}" 144 | } 145 | } 146 | = 147 | 148 | 149 | 150 | ${host} 151 | ${port} 152 | ${protocol} 153 | 154 | api/v1/user/login 155 | POST 156 | true 157 | false 158 | true 159 | false 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | Content-Type 169 | application/json 170 | 171 | 172 | 173 | 174 | 175 | access_token 176 | $.access_token 177 | 0 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | ${host} 186 | ${port} 187 | ${protocol} 188 | 189 | /api/v1/menu/list 190 | GET 191 | true 192 | false 193 | true 194 | false 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | access_token 204 | ${access_token} 205 | 206 | 207 | 208 | 209 | 210 | 211 | true 212 | 213 | 214 | 215 | false 216 | { 217 | "order_list": [ 218 | { 219 | "menu_nunber" : "01", 220 | "number" : 1 221 | }, 222 | { 223 | "menu_nunber" : "03", 224 | "number" : 2 225 | }, 226 | { 227 | "menu_nunber" : "04", 228 | "number" : 1 229 | }, 230 | { 231 | "menu_nunber" : "05", 232 | "number" : 3 233 | } 234 | ] 235 | } 236 | = 237 | 238 | 239 | 240 | ${host} 241 | ${port} 242 | ${protocol} 243 | 244 | /api/v1/menu/confirm 245 | POST 246 | true 247 | false 248 | true 249 | false 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | access_token 259 | ${access_token} 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | ${host} 270 | ${port} 271 | ${protocol} 272 | 273 | /api/v1/user/logout 274 | DELETE 275 | true 276 | false 277 | true 278 | false 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | access_token 288 | ${access_token} 289 | 290 | 291 | 292 | 293 | 294 | 295 | false 296 | true 297 | false 298 | 299 | 300 | 301 | 302 | 303 | 304 | influxdbMetricsSender 305 | org.apache.jmeter.visualizers.backend.influxdb.HttpMetricsSender 306 | = 307 | 308 | 309 | influxdbUrl 310 | http://localhost:8086/write?db=jmeter 311 | = 312 | 313 | 314 | application 315 | Order 316 | = 317 | 318 | 319 | measurement 320 | jmeter 321 | = 322 | 323 | 324 | summaryOnly 325 | true 326 | = 327 | 328 | 329 | samplersRegex 330 | .* 331 | = 332 | 333 | 334 | percentiles 335 | 90;95;99 336 | = 337 | 338 | 339 | testTitle 340 | JMeter Test 341 | = 342 | 343 | 344 | eventTags 345 | 346 | = 347 | 348 | 349 | 350 | org.apache.jmeter.visualizers.backend.influxdb.InfluxdbBackendListenerClient 351 | 352 | 353 | 354 | 355 | 356 | 357 | -------------------------------------------------------------------------------- /jmx/UploadFile.jmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | false 7 | true 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | continue 17 | 18 | false 19 | 1 20 | 21 | 1 22 | 1 23 | false 24 | 10 25 | 26 | true 27 | 28 | 29 | 30 | false 31 | 32 | saveConfig 33 | 34 | 35 | true 36 | true 37 | true 38 | 39 | true 40 | true 41 | true 42 | true 43 | false 44 | true 45 | true 46 | false 47 | false 48 | false 49 | true 50 | false 51 | false 52 | false 53 | true 54 | 0 55 | true 56 | true 57 | true 58 | true 59 | true 60 | true 61 | 62 | 63 | 64 | 65 | 66 | 67 | false 68 | 69 | saveConfig 70 | 71 | 72 | true 73 | true 74 | true 75 | 76 | true 77 | true 78 | true 79 | true 80 | false 81 | true 82 | true 83 | false 84 | false 85 | false 86 | true 87 | false 88 | false 89 | false 90 | true 91 | 0 92 | true 93 | true 94 | true 95 | true 96 | true 97 | true 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | ../image/PKQ.jpg 108 | file 109 | multipart/form-data 110 | 111 | 112 | 113 | 114 | 115 | 116 | localhost 117 | 9091 118 | http 119 | 120 | /uploadfile 121 | POST 122 | true 123 | false 124 | true 125 | false 126 | 127 | 128 | 129 | 130 | 131 | 132 | $.code 133 | 200 134 | true 135 | false 136 | false 137 | true 138 | 139 | 140 | 141 | $.result 142 | success 143 | true 144 | false 145 | false 146 | true 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | stage.velobank.com 155 | 156 | https 157 | 158 | /content/dam/velobank-old-032020/Video-1-How-to-fund-your-Velo-account-through-international-wire.mp4 159 | GET 160 | true 161 | false 162 | true 163 | false 164 | 165 | 166 | 167 | 168 | 169 | 170 | import java.io.*; 171 | 172 | byte[] result = prev.getResponseData(); 173 | String file_name = "E://download//keywords-${counter}.txt"; 174 | File file = new File(file_name); 175 | FileOutputStream out = new FileOutputStream(file); 176 | out.write(result); 177 | out.close(); 178 | 179 | 180 | 181 | false 182 | 183 | 184 | 185 | false 186 | true 187 | false 188 | 189 | 190 | 191 | 192 | 193 | 194 | -------------------------------------------------------------------------------- /jmx/grafana_test.jmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | false 7 | true 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | continue 17 | 18 | false 19 | -1 20 | 21 | 1 22 | 1 23 | false 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | influxdbMetricsSender 33 | org.apache.jmeter.visualizers.backend.influxdb.HttpMetricsSender 34 | = 35 | 36 | 37 | influxdbUrl 38 | http://localhost:8086/write?db=jmeter 39 | = 40 | 41 | 42 | application 43 | application name 44 | = 45 | 46 | 47 | measurement 48 | jmeter 49 | = 50 | 51 | 52 | summaryOnly 53 | true 54 | = 55 | 56 | 57 | samplersRegex 58 | .* 59 | = 60 | 61 | 62 | percentiles 63 | 90;95;99 64 | = 65 | 66 | 67 | testTitle 68 | Test name 69 | = 70 | 71 | 72 | eventTags 73 | 74 | = 75 | 76 | 77 | 78 | org.apache.jmeter.visualizers.backend.influxdb.InfluxdbBackendListenerClient 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /jmx/jsr233_proc.jmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | false 7 | true 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | continue 17 | 18 | false 19 | 1 20 | 21 | 1 22 | 1 23 | false 24 | 25 | 26 | true 27 | 28 | 29 | 30 | false 31 | 32 | saveConfig 33 | 34 | 35 | true 36 | true 37 | true 38 | 39 | true 40 | true 41 | true 42 | true 43 | false 44 | true 45 | true 46 | false 47 | false 48 | false 49 | true 50 | false 51 | false 52 | false 53 | true 54 | 0 55 | true 56 | true 57 | true 58 | true 59 | true 60 | true 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | www.weather.com.cn 71 | 72 | 73 | 74 | /data/cityinfo/101280601.html 75 | GET 76 | true 77 | false 78 | true 79 | false 80 | 81 | 82 | 83 | 84 | 85 | 86 | groovy 87 | 88 | 89 | true 90 | import groovy.json.JsonSlurper; 91 | 92 | def jsonSlurper = new JsonSlurper(); 93 | def response = jsonSlurper.parseText(prev.getResponseDataAsString()); 94 | def city=response.weatherinfo.city.toString(); 95 | 96 | log.info("JSR233 city = " + city); 97 | vars.put("city",city); //输出变量city 98 | 99 | 100 | 101 | 102 | false 103 | true 104 | false 105 | 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /jmx/orderservice.jmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | false 7 | true 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | continue 17 | 18 | false 19 | -1 20 | 21 | 10 22 | 1 23 | true 24 | 20 25 | 26 | false 27 | 28 | 29 | 30 | false 31 | 32 | saveConfig 33 | 34 | 35 | true 36 | true 37 | true 38 | 39 | true 40 | true 41 | true 42 | true 43 | false 44 | true 45 | true 46 | false 47 | false 48 | false 49 | true 50 | false 51 | false 52 | false 53 | true 54 | 0 55 | true 56 | true 57 | true 58 | true 59 | true 60 | true 61 | 62 | 63 | 64 | 65 | 66 | 67 | , 68 | UTF-8 69 | ./orderusers.csv 70 | true 71 | true 72 | true 73 | shareMode.all 74 | false 75 | no,username,password 76 | 77 | 78 | 79 | false 80 | 81 | saveConfig 82 | 83 | 84 | true 85 | true 86 | true 87 | 88 | true 89 | true 90 | true 91 | true 92 | false 93 | true 94 | true 95 | false 96 | false 97 | false 98 | true 99 | false 100 | false 101 | false 102 | true 103 | 0 104 | true 105 | true 106 | true 107 | true 108 | true 109 | true 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | host 119 | localhost 120 | = 121 | 122 | 123 | port 124 | 9091 125 | = 126 | 127 | 128 | protocol 129 | http 130 | = 131 | 132 | 133 | wait 134 | 10 135 | = 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | accesstoken 144 | ${access_token} 145 | 146 | 147 | Content-Type 148 | application/json 149 | 150 | 151 | 152 | 153 | 154 | false 155 | true 156 | false 157 | 158 | 159 | 160 | false 161 | false 162 | 163 | 164 | 165 | true 166 | 167 | 168 | 169 | false 170 | { 171 | "authRequest": { 172 | "userName": "${username}", 173 | "password": "${password}" 174 | } 175 | } 176 | = 177 | 178 | 179 | 180 | ${host} 181 | ${port} 182 | ${protocol} 183 | 184 | api/v1/user/login 185 | POST 186 | true 187 | false 188 | true 189 | false 190 | 191 | 192 | 193 | 194 | 195 | 196 | access_token 197 | $.access_token 198 | 0 199 | 200 | 201 | 202 | $.message 203 | login success 204 | true 205 | false 206 | false 207 | true 208 | 209 | 210 | 211 | ${wait} 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | ${host} 220 | ${port} 221 | ${protocol} 222 | 223 | /api/v1/menu/list 224 | GET 225 | true 226 | false 227 | true 228 | false 229 | 230 | 231 | 232 | 233 | 234 | 235 | ${wait} 236 | 237 | 238 | 239 | false 240 | 241 | 242 | String s2 = new String(prev.getResponseData(), "UTF-8"); 243 | //---------------一下步骤为转码过程--------------- 244 | char aChar; 245 | int len = s2.length(); 246 | StringBuffer outBuffer = new StringBuffer(len); 247 | for (int x = 0; x < len;) 248 | { 249 | aChar = s2.charAt(x++); 250 | if (aChar == '\\') { 251 | aChar = s2.charAt(x++); 252 | if (aChar == 'u') { 253 | int 254 | value = 0; 255 | for (int i = 0; 256 | i < 4; 257 | i++ 258 | ) 259 | { 260 | aChar = s2.charAt(x++); 261 | switch (aChar) { 262 | case'0': 263 | case'1': 264 | case'2': 265 | case'3': 266 | case'4': 267 | case'5': 268 | case'6': 269 | case'7': 270 | case'8': 271 | case'9': 272 | value = (value << 4) + aChar - '0'; 273 | break; 274 | case'a': 275 | case'b': 276 | case'c': 277 | case'd': 278 | case'e': 279 | case'f': 280 | value = (value << 4) + 10 + aChar - 'a'; 281 | break; 282 | case'A': 283 | case'B': 284 | case'C': 285 | case'D': 286 | case'E': 287 | case'F': 288 | value = (value << 4) + 10 + aChar - 'A'; 289 | break; 290 | default: 291 | throw new IllegalArgumentException( 292 | "Malformed   \\uxxxx  encoding."); 293 | } 294 | } 295 | outBuffer.append((char) 296 | value 297 | ) 298 | ; 299 | } else { 300 | if (aChar == 't') 301 | aChar = '\t'; 302 | else if (aChar == 'r') 303 | aChar = '\r'; 304 | else if (aChar == 'n') 305 | aChar = '\n'; 306 | else if (aChar == 'f') 307 | aChar = '\f'; 308 | outBuffer.append(aChar); 309 | } 310 | } else 311 | outBuffer.append(aChar); 312 | } 313 | //-----------------以上内容为转码过程--------------------------- 314 | //将转成中文的响应结果在查看结果树中显示 315 | 316 | prev.setResponseData(outBuffer.toString()); 317 | 318 | 319 | 320 | 321 | true 322 | 323 | 324 | 325 | false 326 | { 327 | "order_list": [ 328 | { 329 | "menu_nunber" : "01", 330 | "number" : 2 331 | }, 332 | { 333 | "menu_nunber" : "03", 334 | "number" : 2 335 | }, 336 | { 337 | "menu_nunber" : "04", 338 | "number" : 2 339 | }, 340 | { 341 | "menu_nunber" : "05", 342 | "number" : 3 343 | } 344 | ] 345 | } 346 | = 347 | 348 | 349 | 350 | ${host} 351 | ${port} 352 | ${protocol} 353 | 354 | /api/v1/menu/confirm 355 | POST 356 | true 357 | false 358 | true 359 | false 360 | 361 | 362 | 363 | 364 | 365 | 366 | ${wait} 367 | 368 | 369 | 370 | $.message 371 | Order success. 372 | true 373 | false 374 | false 375 | true 376 | 377 | 378 | 379 | $.total 380 | 9 381 | true 382 | false 383 | false 384 | true 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | ${host} 393 | ${port} 394 | ${protocol} 395 | 396 | /api/v1/user/logout 397 | DELETE 398 | true 399 | false 400 | true 401 | false 402 | 403 | 404 | 405 | 406 | 407 | 408 | ${wait} 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | influxdbMetricsSender 418 | org.apache.jmeter.visualizers.backend.influxdb.HttpMetricsSender 419 | = 420 | 421 | 422 | influxdbUrl 423 | http://localhost:8086/write?db=jmeter 424 | = 425 | 426 | 427 | application 428 | Order Service 429 | = 430 | 431 | 432 | measurement 433 | jmeter 434 | = 435 | 436 | 437 | summaryOnly 438 | false 439 | = 440 | 441 | 442 | samplersRegex 443 | .* 444 | = 445 | 446 | 447 | percentiles 448 | 90;95;99 449 | = 450 | 451 | 452 | testTitle 453 | Order Service 454 | = 455 | 456 | 457 | eventTags 458 | 459 | = 460 | 461 | 462 | 463 | org.apache.jmeter.visualizers.backend.influxdb.InfluxdbBackendListenerClient 464 | 465 | 466 | 467 | 468 | 469 | 470 | -------------------------------------------------------------------------------- /jmx/orderusers.csv: -------------------------------------------------------------------------------- 1 | No.,username,password 2 | 1,user01,pwd 3 | 2,user02,pwd 4 | 3,user03,pwd 5 | 4,user04,pwd 6 | 5,user05,pwd 7 | 6,user06,pwd 8 | 7,user07,pwd 9 | 8,user08,pwd 10 | 9,user09,pwd 11 | 10,user10,pwd -------------------------------------------------------------------------------- /jmx/processors.jmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | false 7 | true 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | continue 17 | 18 | false 19 | 1 20 | 21 | 1 22 | 1 23 | false 24 | 25 | 26 | true 27 | 28 | 29 | 30 | false 31 | 32 | saveConfig 33 | 34 | 35 | true 36 | true 37 | true 38 | 39 | true 40 | true 41 | true 42 | true 43 | false 44 | true 45 | true 46 | false 47 | false 48 | false 49 | true 50 | false 51 | false 52 | false 53 | true 54 | 0 55 | true 56 | true 57 | true 58 | true 59 | true 60 | true 61 | 62 | 63 | 64 | 65 | 66 | 67 | 2 68 | 69 | 70 | 71 | 72 | 73 | 74 | false 75 | ${timestamp} 76 | = 77 | true 78 | time 79 | 80 | 81 | 82 | www.baidu.com 83 | 84 | 85 | 86 | 87 | GET 88 | true 89 | false 90 | true 91 | false 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | false 101 | long timestamp = System.currentTimeMillis(); 102 | vars.put("timestamp", timestamp + ""); 103 | 104 | 105 | 106 | false 107 | 108 | 109 | import com.studio.test.utils.*; 110 | 111 | String idcardno = Tools.createIdcard(); 112 | vars.put("idcardno", idcardno); 113 | 114 | 115 | 116 | false 117 | 1111 222 3333 118 | 119 | 120 | log.info("aaaaa=====" + bsh.args[2]); 121 | 122 | 123 | 124 | 125 | false 126 | true 127 | false 128 | 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /jmx/test.jmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | false 7 | true 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | continue 17 | 18 | false 19 | 1 20 | 21 | 1 22 | 1 23 | false 24 | 25 | 26 | true 27 | 28 | 29 | 30 | 31 | 32 | false 33 | 34 | saveConfig 35 | 36 | 37 | true 38 | true 39 | true 40 | 41 | true 42 | true 43 | true 44 | true 45 | false 46 | true 47 | true 48 | false 49 | false 50 | false 51 | true 52 | false 53 | false 54 | false 55 | true 56 | 0 57 | true 58 | true 59 | true 60 | true 61 | true 62 | true 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | rValue 72 | ${__Random(0,99,)} 73 | = 74 | 75 | 76 | date 77 | ${__RandomDate(,,2021-10-10,,)} 78 | = 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | false 87 | long timestamp = System.currentTimeMillis(); 88 | vars.put("timestamp", timestamp + ""); 89 | 90 | 91 | 92 | 1 93 | 94 | 95 | 96 | true 97 | ${__Random(1,4,id)} 98 | 99 | 100 | 101 | 102 | 103 | 104 | www.baidu.com 105 | 106 | 107 | 108 | 109 | GET 110 | true 111 | false 112 | true 113 | false 114 | 115 | 116 | 117 | 118 | 119 | 120 | 10 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | www.baidu.com 129 | 130 | 131 | 132 | 133 | GET 134 | true 135 | false 136 | true 137 | false 138 | 139 | 140 | 141 | 142 | 143 | 144 | 1000 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | www.baidu.com 153 | 154 | 155 | 156 | 157 | GET 158 | true 159 | false 160 | true 161 | false 162 | 163 | 164 | 165 | 166 | 167 | 168 | 1000 169 | 170 | 171 | 172 | 173 | 174 | false 175 | true 176 | false 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /jmx/timer.jmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | false 7 | true 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | continue 17 | 18 | false 19 | -1 20 | 21 | 10 22 | 1 23 | true 24 | 60 25 | 26 | true 27 | 28 | 29 | 30 | false 31 | 32 | saveConfig 33 | 34 | 35 | true 36 | true 37 | true 38 | 39 | true 40 | true 41 | true 42 | true 43 | false 44 | true 45 | true 46 | false 47 | false 48 | false 49 | true 50 | false 51 | false 52 | false 53 | true 54 | 0 55 | true 56 | true 57 | true 58 | true 59 | true 60 | true 61 | 62 | 63 | 64 | 65 | 66 | 67 | false 68 | 69 | saveConfig 70 | 71 | 72 | true 73 | true 74 | true 75 | 76 | true 77 | true 78 | true 79 | true 80 | false 81 | true 82 | true 83 | false 84 | false 85 | false 86 | true 87 | false 88 | false 89 | false 90 | true 91 | 0 92 | true 93 | true 94 | true 95 | true 96 | true 97 | true 98 | 99 | 100 | 101 | 102 | 103 | 104 | false 105 | 106 | saveConfig 107 | 108 | 109 | true 110 | true 111 | true 112 | 113 | true 114 | true 115 | true 116 | true 117 | false 118 | true 119 | true 120 | false 121 | false 122 | false 123 | true 124 | false 125 | false 126 | false 127 | true 128 | 0 129 | true 130 | true 131 | true 132 | true 133 | true 134 | true 135 | 136 | 137 | 138 | 139 | 140 | 141 | false 142 | false 143 | 144 | 145 | 146 | 1 147 | 148 | throughput 149 | 60.0 150 | 0.0 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | www.baidu.com 159 | 160 | 161 | 162 | 163 | GET 164 | true 165 | false 166 | true 167 | false 168 | 169 | 170 | 171 | 172 | 173 | 174 | 300 175 | 100 176 | 177 | 178 | 179 | false 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | www.baidu.com 193 | 194 | 195 | 196 | 197 | GET 198 | true 199 | false 200 | true 201 | false 202 | 203 | 204 | 205 | 206 | 207 | 208 | 3000 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | www.baidu.com 217 | 218 | 219 | 220 | 221 | GET 222 | true 223 | false 224 | true 225 | false 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | -------------------------------------------------------------------------------- /jmx/users.csv: -------------------------------------------------------------------------------- 1 | No.,username,password 2 | 1,user01,pwd 3 | 2,user02,pwd 4 | 3,user03,pwd 5 | 4,user04,pwd 6 | 5,user05,pwd 7 | 6,user06,pwd 8 | 7,user07,pwd 9 | 8,user08,pwd 10 | 9,user09,pwd 11 | 10,user10,pwd -------------------------------------------------------------------------------- /jmx/xml_data.jmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | false 7 | true 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | continue 17 | 18 | false 19 | 1 20 | 21 | 1 22 | 1 23 | false 24 | 25 | 26 | true 27 | 28 | 29 | 30 | false 31 | 32 | saveConfig 33 | 34 | 35 | true 36 | true 37 | true 38 | 39 | true 40 | true 41 | true 42 | true 43 | false 44 | true 45 | true 46 | false 47 | false 48 | false 49 | true 50 | false 51 | false 52 | false 53 | true 54 | 0 55 | true 56 | true 57 | true 58 | true 59 | true 60 | true 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | localhost 71 | 8000 72 | 73 | 74 | response.xml 75 | GET 76 | true 77 | false 78 | true 79 | false 80 | 81 | 82 | 83 | 84 | 85 | 86 | false 87 | value 88 | <field name="orderId" value="(.+?)"/> 89 | $1$ 90 | notfound 91 | 0 92 | 93 | 94 | 95 | notfound 96 | orderId 97 | 1 98 | //field[@name="orderId"]/@value 99 | false 100 | false 101 | false 102 | 103 | 104 | 105 | 106 | false 107 | true 108 | false 109 | 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /shell/startGrafana.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | docker stop jmeterGraf 4 | docker rm jmeterGraf 5 | docker run -d -p 3000:3000 --name=jmeterGraf grafana/grafana -------------------------------------------------------------------------------- /shell/startInfluxdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | docker stop jmeterdb 4 | docker rm jmeterdb 5 | docker run -d -p 8086:8086 -p 8083:8083 --name=jmeterdb influxdb -------------------------------------------------------------------------------- /sql/order.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE IF NOT EXISTS `jmeter_class`; 2 | USE `jmeter_class`; 3 | 4 | DROP TABLE IF EXISTS `user`; 5 | CREATE TABLE `user` ( 6 | `uid` int(11) NOT NULL AUTO_INCREMENT, 7 | `username` varchar(100) DEFAULT NULL, 8 | `password` varchar(100) DEFAULT NULL, 9 | PRIMARY KEY (`uid`) 10 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 11 | 12 | -- LOCK TABLES `user` WRITE; 13 | -- INSERT INTO `user` VALUES (1,'user1', '123456'),(2,'user1', '123456'),(3,'user1', '123456'),(4,'user1', '123456'),(5,'user1', '123456'),(6,'user1', '123456'); 14 | -- UNLOCK TABLES; 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /unicode2utf8/unicode2utf8.js: -------------------------------------------------------------------------------- 1 | String s2 = new String(prev.getResponseData(), "UTF-8"); 2 | //---------------一下步骤为转码过程--------------- 3 | char aChar; 4 | int len = s2.length(); 5 | StringBuffer outBuffer = new StringBuffer(len); 6 | for (int x = 0; x < len;) 7 | { 8 | aChar = s2.charAt(x++); 9 | if (aChar == '\\') { 10 | aChar = s2.charAt(x++); 11 | if (aChar == 'u') { 12 | int 13 | value = 0; 14 | for (int i = 0; 15 | i < 4; 16 | i++ 17 | ) 18 | { 19 | aChar = s2.charAt(x++); 20 | switch (aChar) { 21 | case'0': 22 | case'1': 23 | case'2': 24 | case'3': 25 | case'4': 26 | case'5': 27 | case'6': 28 | case'7': 29 | case'8': 30 | case'9': 31 | value = (value << 4) + aChar - '0'; 32 | break; 33 | case'a': 34 | case'b': 35 | case'c': 36 | case'd': 37 | case'e': 38 | case'f': 39 | value = (value << 4) + 10 + aChar - 'a'; 40 | break; 41 | case'A': 42 | case'B': 43 | case'C': 44 | case'D': 45 | case'E': 46 | case'F': 47 | value = (value << 4) + 10 + aChar - 'A'; 48 | break; 49 | default: 50 | throw new IllegalArgumentException( 51 | "Malformed   \\uxxxx  encoding."); 52 | } 53 | } 54 | outBuffer.append((char) 55 | value 56 | ) 57 | ; 58 | } else { 59 | if (aChar == 't') 60 | aChar = '\t'; 61 | else if (aChar == 'r') 62 | aChar = '\r'; 63 | else if (aChar == 'n') 64 | aChar = '\n'; 65 | else if (aChar == 'f') 66 | aChar = '\f'; 67 | outBuffer.append(aChar); 68 | } 69 | } else 70 | outBuffer.append(aChar); 71 | } 72 | //-----------------以上内容为转码过程--------------------------- 73 | //将转成中文的响应结果在查看结果树中显示 74 | 75 | prev.setResponseData(outBuffer.toString()); --------------------------------------------------------------------------------