1、goreplay流量回放
- 目的
在实际项目中,会有大量的回归测试工作,通常会使用自动化代码的手段来实现回归,但是对于一个庞大的系统来说,通过自动化脚本的方式来实现回归测试,又显得很费时费力。并且如果有定期将线上数据同步到测试环境的需求的话,流量回放就显得很必要了。当然,流量回放并不能替代自动化,对于存在上下文关联的接口,流量回放的处理上就显得很复杂。
- 流量回放
其实流量回放主要是对某个端口的流量进行转发和存储,这边用的是goreplay,mitmproxy也可以做到流量的抓取和回放。
流量回放有三种使用方式:
- 服务->to->服务,即端到端
- 服务->to->文件,即流量存储
- 文件->to->服务,即流量文件回放到服务
- 常用配置示例
- service_to_file.yml
bin:
- "/opt/crawl/project/flow_replay/gor"
input:
- "--input-raw :18080"
- "--input-raw-track-response"
- "--prettify-http"
middle:
-
output:
- "--output-file ./data/requests-%Y-%m-%d-%H.gor"
- "--output-file-size-limit 100kb"
- "--output-file-queue-limit 60" - file_to_service.yml
bin:
- "/opt/crawl/project/flow_replay/gor"
input:
- "--input-file ./data/'requests-2024-03-18-14_7.gor'"
middle:
- "--middleware /opt/crawl/project/flow_replay/middle/main.js"
output:
- "--output-http='http://localhost:18080'"
- "--output-http-track-response"
- "--prettify-http" - 释义
gorplay的配置主要分为三个部分,分别是input、output和middleware
- input:定义需要捕获请求的一些必要条件
# 定义监听端口
--input-raw :18080
# 定义是否要捕获请求响应,只有添加了这个配置,回放时才会触发response事件
--input-raw-track-response
# 定义是否要美化响应,这个配置是作者修复bug新加的配置,必须要有,
# 如果没有会造成乱码
--prettify-http
# 定义存储请求的文件位置
# 可以使用*模糊匹配,批量回放相关文件,如requests-2024-03-18-*.gor
--input-file ./data/'requests-2024-03-18-14_7.gor'
# 定义缓冲区大小,单位为b
--input-raw-buffer-size 10485760 注:不论是从端口读取请求或者从文件读取请求,则必然会触发request事件
- output:定义输出请求的一些必要参数
# 定义存储请求文件的位置、格式及命名
--output-file ./data/requests-%Y-%m-%d-%H.gor
# 追踪流量回放响应,只有存在这个配置,回放成功后才会触发replay事件
--output-http-track-response
# 定义存储请求文件的最大size
--output-file-size-limit 100kb
# 定义单个存储文件中存储请求的数量
--output-file-queue-limit 20
# 同input
--prettify-http
# 定义请求丢弃比例,分别为绝对值和百分比
# 每秒请求超过绝对值的数字,则丢弃
# 只回放百分比的请求数量提升速度
--output-http='http://localhost:18080|10'
--output-http='http://localhost:18080|10%' - 中间件
- 中间件流程示意图

- 中间件常用Api
init - 初始化
httpPath - 获取请求URL,不包含请求的域名: gor.httpPath(req.http)
httpMethod - 获取请求方法:gor.httpMethod(req.http).
setHttpPath - 更新URL: req.http = gor.setHttpPath(req.http, newPath)
httpPathParam - 获取URL上的参数: gor.httpPathParam(req.http, queryParam)
setHttpPathParam - 设置URL参数: req.http = gor.setHttpPathParam(req.http, queryParam, value)
httpStatus - 响应状态码:gor.httpStatus(rep.http)
httpHeaders - 获取所有请求头: gor.httpHeaders(req.http)
httpHeader - 获取指定请求头: gor.httpHeader(req.http, "Content-Length")
setHttpHeader - 设置请求头, returns modified payload: req.http = gor.setHttpHeader(req.http, "X-Replayed", "1")
httpBody - 获取请求体: gor.httpBody(req.http)
setHttpBody - 设置请求体,需要注意Content-Length的大小: req.http = gor.setHttpBody(req.http, Buffer.from('hello!')).
httpBodyParam - 获取post请求param: gor.httpBodyParam(req.http, param)
setHttpBodyParam - 设置post请求的param: req.http = gor.setHttpBodyParam(req.http, param, value)
httpCookie - 获取cookie: gor.httpCookie(req.http, "SESSSION_ID")
setHttpCookie - 设置cookie, returns modified payload: req.http = gor.setHttpCookie(req.http, "iam", "cuckoo")
deleteHttpCookie - 删除cookie, returns modified payload: req.http = gor.deleteHttpCookie(req.http, "iam") - 事件
事件只存在于中间件中,goreplay接收到某个端口的请求后,会把request和response压缩成gzip,通过data.http字段转发给中间件,这样会触发request事件和response事件,当回放完成后,会触发replay事件
- 中间件代码示例
#!/usr/bin/node
const gor = require("goreplay_middleware");
const NodeRSA = require('node-rsa');
const axios = require('axios')
const {user, baseUrl, publicKey} = require('./defalut')
const https = require('https');
const jsonpath = require('jsonpath');/**
* @description 对公钥进行加密
* @param publicKey
* @param {string} data 需要加密的数据
* @returns {string} 加密后的数据
*/
function encrypt(publicKey, data) {let buffer = Buffer.from(data);let key = new NodeRSA(publicKey);
key.setOptions({encryptionScheme: 'pkcs1'});return key.encrypt(buffer, 'base64', 'base64');
}/**
*
* @param str
* @param color:string, red, green, yellow, blue, and white if the color is the other value
* @return {string}
*/
function addStringColor(str, color) {switch (color) {case "red":
color = "31";break;case "green":
color = "32";break;case "yellow":
color = "33";break;case "blue":
color = "34";break;case "pink":
color = "35";break;default:
color = "37";break;}return "\x1b[" + color + "m" + str + "\x1b[0m";
}/**
* @description send login request and extract sessionId
* @param baseUrl{string} request url
* @returns {string} return sessionId
*/async function getCookie(baseUrl) {const data = {
userName: user["username"],
password: encrypt(publicKey, user["password"])};const url = baseUrl.concat('api/auth/doLogin');try {const response = await axios.post(url, data, {
httpsAgent: new https.Agent({rejectUnauthorized: false}),
headers: {'Content-Type': 'application/json; charset=utf-8'}});return response.headers['set-cookie'][0].match('(?<=JSESSIONID=)[a-f0-9-]+')[0];} catch (error) {
console.error(error);}
}(async () => {let cookie = await getCookie(baseUrl);
gor.init();
gor.on('request', function (request) {//request.http = gor.deleteHttpCookie(request.http, 'JSESSIONID')
request.http = gor.setHttpCookie(request.http, 'JSESSIONID', cookie)
gor.on("replay", request.ID, function (replay) {try {let obj = JSON.parse(gor.httpBody(replay.http).toString('utf8'))if (jsonpath.query(obj, '$..code')[0] === '0000') {
console.error(addStringColor(`√\t${gor.httpMethod(request.http)}\t${gor.httpPath(request.http)}`, 'green'))} else {
console.error(addStringColor(`x\t${gor.httpMethod(request.http)}\t${gor.httpPath(request.http)}\n ${gor.httpBody(replay.http)} `, 'red'))}} catch (e) {
console.error(addStringColor(`\t${gor.httpMethod(request.http)}\t${gor.httpPath(request.http)}\n ${e}`, 'red'))}return replay;})return request})
})() - 效果展示

相关文章:
1、goreplay流量回放
目的 在实际项目中,会有大量的回归测试工作,通常会使用自动化代码的手段来实现回归,但是对于一个庞大的系统来说,通过自动化脚本的方式来实现回归测试,又显得很费时费力。并且如果有定期将线上数据同步到测试环境的需求…...
Transformer的前世今生 day06(Self-Attention和RNN、LSTM的区别)
Self-Attention和RNN、LSTM的区别 RNN的缺点:无法做长序列,当输入很长时,最后面的输出很难参考前面的输入,即长序列会缺失上文信息,如下: 可能一段话超过50个字,输出效果就会很差了 LSTM通过忘…...
UDP send 出现大量“Resource temporarily unavailable”
背景 最近排查用户现场环境,查看日志出现大量的“send: Resource temporarily unavailable”错误,UDP设置NO_BLOCK模式,send又发生在进程上下文,并且还设置了SO_SNDBUF 为8M,在此情况下为什么还会出现发送队列满的情况…...
怎么拆解台式电脑风扇CPU风扇的拆卸步骤-怎么挑
今天我就跟大家分享一下如何选购电脑风扇的知识。 我也会解释一下机箱散热风扇一般用多少转。 如果它恰好解决了您现在面临的问题,请不要忘记关注本站并立即开始! 文章目录列表:大家一般机箱散热风扇都用多少转? 机箱散热风扇选择…...
Windows安装Odoo结合内网穿透实现公网访问本地企业管理系统
文章目录 前言1. 下载安装Odoo:2. 实现公网访问Odoo本地系统:3. 固定域名访问Odoo本地系统 前言 Odoo是全球流行的开源企业管理套件,是一个一站式全功能ERP及电商平台。 开源性质:Odoo是一个开源的ERP软件,这意味着企…...
Portainer的替代Dockge?又一个Docker Compose管理器?
Dockge:让Docker Compose管理触手可及,一图胜千言,轻松构建与管控您的容器服务栈!- 精选真开源,释放新价值。 概览 Docker,这一开放源代码的创新平台,旨在实现应用程序部署、扩展与运维的自动化…...
Midjourney AI绘图工具介绍及使用
介绍 Midjourney是一款目前被誉为最强的AI绘图工具。只要输入想到的文字,就能通过人工智能产出相对应的图片。 官网只是宣传和登录入口,提供个人主页、订阅管理等功能,Midjourney实际的绘画功能,是在另外一个叫discord的产品中实…...
clang-query 的编译安装与使用示例
1,clang query 概述 作用: 检查一个程序源码的抽象语法树,测试 AST 匹配器; 帮助检查哪些 AST 节点与指定的 AST 匹配器相匹配; 2,clang-query 安装 准备: git clone --recursive https://git…...
echarts数据下钻如何配置
官方范例:https://echarts.apache.org/examples/zh/editor.html?cbar-multi-drilldown 看了一眼范例直接晕了,你这,一堆数据直接写死,这怎么用啊! 一般来说,实现步骤是: 1)后台&a…...
git 提交空目录
git 提交空目录 1. git 无法感应空目录2. git 提交空目录References 1. git 无法感应空目录 Git FAQ https://archive.kernel.org/oldwiki/git.wiki.kernel.org/index.php/GitFaq.html Currently the design of the Git index (staging area) only permits files to be liste…...
【优化方案】Java 将字符串中的星号替换为0-9中的数字,并返回所有可能的替换结果
需求 将输入的字符串中的星号替换为0-9中的数字,并返回所有可能的替换结果,允许存在多个*号。 分析: 在每个星号位置,我们需要进行 0-9 的循环遍历,因此每个星号位置都有 10 种可能性。如果字符数组中有k个星号&#x…...
C语言复习-链表
链表: 特点: 通过 next 指针 把内存上不连续 的几段数据 联系起来 set nu -- 打印行号 概念: 一种数据结构 -- 数据存放的思想 比如 -- 数组 -- 内存连续的一段空间,存放相同类型的一堆数据 缺点 -- 增删元素很 难 -- 不灵活 --> 引入链表 next指针的初步认识…...
Redis面试题-缓存雪崩、缓存穿透、缓存击穿问题
1 穿透: 两边都不存在(皇帝的新装) (黑名单) (布隆过滤器) 2 击穿:一个热点的key失效了,这时大量的并发请求直接到达数据库. (提前预热) 3 雪崩:…...
【Node.js】npx
概述 npx 可以使用户在不安装全局包的情况下,运行已安装在本地项目中的包或者远程仓库中的包。 高版本npm会自带npx命令。 它可以直接运行 node_modules/.bin 下的 exe 可执行文件。而不像之前,我们需要在 scripts 里面配置,然后 npm run …...
hive授予指定用户特定权限及beeline使用
背景:因业务需要,需要使用beeline对hive数据进行查询,但是又不希望该用户可以查询所有的数据,希望有一个新用户bb给他指定的库表权限。 解决方案: 1.赋权语句,使用hive管理员用户在终端输入hive进入命令控…...
Vmware虚拟机无法用root直连说明
Vmware虚拟机无法用root直连说明 背景目的SSH服务介绍无法连接检查配置 背景 今天在VM上新装了一套Centos-stream-9系统,网络适配器的连接方式采用的是桥接,安装好虚拟机后,在本地用ssh工具进行远程连接,ip、用户、密码均是成功的…...
Visio中存在问题的解决方法
公式缩放 mathtype公式在visio缩放之后,出现了变形。 解决方法:每次输入公式都通过 插入->对象->mathType Equation 新建一个公式。可以避免 注:网上有的说在word中使用mathtype编写公式,之后复制到visio中。 插入波形 选择…...
taro之Swiper的使用
图样: 往往我们需要轮播图去显示我们想要的图片之类的 这是工作的代码 <View classNametop-title><SwiperclassNamebanner-swiperinterval{3000}circularautoplay>{homeBannerList.map((item) > {return (<SwiperItem key{item.id}><View…...
正大国际:金融行业发展趋势
2024金融科技趋势研究报告 大模型生态揭秘!金融行业迎来变革,中控成生态核心,大模型在金融行业的应用 随着大模型的不断发展,越来越多的金融机构开始尝试在一些业务场景中引入大模型和生成式A能力,预计2024年,领先的金…...
vue中实现超出一行 展开和收起的功能
html中: <divclass="txttype"ref="txttype"style="margin-bottom: 6px":class="hidetext == true ? hidetext : "><div style="width: 96%"><el-tagtype="info"style="margin-right: 10px&…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...
Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
通过MicroSip配置自己的freeswitch服务器进行调试记录
之前用docker安装的freeswitch的,启动是正常的, 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...
DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态
前言 在人工智能技术飞速发展的今天,深度学习与大模型技术已成为推动行业变革的核心驱动力,而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心,系统性地呈现了两部深度技术著作的精华:…...
向量几何的二元性:叉乘模长与内积投影的深层联系
在数学与物理的空间世界中,向量运算构成了理解几何结构的基石。叉乘(外积)与点积(内积)作为向量代数的两大支柱,表面上呈现出截然不同的几何意义与代数形式,却在深层次上揭示了向量间相互作用的…...
java 局域网 rtsp 取流 WebSocket 推送到前端显示 低延迟
众所周知 摄像头取流推流显示前端延迟大 传统方法是服务器取摄像头的rtsp流 然后客户端连服务器 中转多了,延迟一定不小。 假设相机没有专网 公网 1相机自带推流 直接推送到云服务器 然后客户端拉去 2相机只有rtsp ,边缘服务器拉流推送到云服务器 …...
2025-06-08-深度学习网络介绍(语义分割,实例分割,目标检测)
深度学习网络介绍(语义分割,实例分割,目标检测) 前言 在开始这篇文章之前,我们得首先弄明白,什么是图像分割? 我们知道一个图像只不过是许多像素的集合。图像分割分类是对图像中属于特定类别的像素进行分类的过程,即像素级别的…...
智能问数Text2SQL Vanna windows场景验证
架构 Vanna 是一个开源 Python RAG(检索增强生成)框架,用于 SQL 生成和相关功能。 机制 Vanna 的工作过程分为两个简单步骤 - 在您的数据上训练 RAG“模型”,然后提出问题,这些问题将返回 SQL 查询,这些查…...
