Goreplay来做流量回放
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Goreplay来做流量回放相关的知识,希望对你有一定的参考价值。
最近做项目,用到goreplay来做流量回放,什么是goreplay?
GoReplay is an open-source network monitoring tool which can record your live traffic, and use it for shadowing, load testing, monitoring and detailed analysis.
本质上就是通过监控网络,录制http请求信息(对应用无入侵),然后再把请求重新播放出来。
这是官方给出来运行原理图。
关于goreplay的使用方式,命令用法官方文档给的很全面了,不作赘述,本篇文章关注的是除杂(过滤)。官方本来是支持过滤filtering的,但过滤的范围有限,目前只有Allow url regexp,Disallow url regexp,Filter based on regexp of header,Filter based on HTTP method,也就是对url,header,method三个方向作了过滤,我的需求是对body过滤,不包括在范围内(也有可能我没找到对应文档)
官方找不到对应办法,只能“曲线救国”了,因为goreplay录制的内容是文本性质,所以可以对录制内容下手,把自己认定的杂质除掉,然后再播放,这样就达到效果了。
录制:
我是在windows下demo的,所以下载goreplay的winodwst版本【https://github.com/buger/goreplay/releases/download/v1.3.2/gor-1.3.2_windows.zip】,同时还需要安装WinPcap配合【https://www.winpcap.org/install/bin/WinPcap_4_1_3.exe】,这样就可以通过命令进行录制了:
gor --input-raw :5000 --output-file request.gor
被录制的服务是一个api,实现如下
[HttpPost("/order")]
public IActionResult Post([FromBody] Order order)
{
_logger.LogInformation(System.Text.Json.JsonSerializer.Serialize(order));
order.Status = 200;
return new JsonResult(order);
}
public class Order
{
public string Code { get; set; }
public decimal Amount { get; set; }
public int Status { get; set; }
}
gorreplay录制的内容格式如下:
1 c9051388c0a8000437c39d7f 1629555358511143000 0
POST /pay HTTP/1.1
Content-Type: application/json
User-Agent: PostmanRuntime/7.28.3
Accept: */*
Postman-Token: 3a49aba0-2e9b-4f1d-8fc8-01fb8b15d620
Host: 192.168.0.7:5000
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 92
{
"code":"3a13abfe-d9cb-4e11-ba90-738e93d2cb07",
"amount":908.59,
"status":552
}
????????????
1 c9051388c0a8000437c39d7f 1629555358813757000 0
POST /pay HTTP/1.1
Content-Type: application/json
User-Agent: PostmanRuntime/7.28.3
Accept: */*
Postman-Token: 3a49aba0-2e9b-4f1d-8fc8-01fb8b15d620
Host: 192.168.0.7:5000
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 92
{
"code":"3a13abfe-d9cb-4e11-ba90-738e93d2cb07",
"amount":908.59,
"status":552
}
????????????
除杂
文中的json就是我请求的body,就要依据这个json中的一些数据来除杂,所以就得写段代码解决这个事情。
其实原理很简单,因为我知道我请求的都是json,所以就是从录制的文件中,按段切割,很明细就是三只猴子????????????为分割点,把内容中的json查询出来,然后运用上规则引擎达到过滤作用,把符合条件的数据留下,不符合条件的数据就除杂,最后保存成一个新文件,供流量回放时使用。
规则引擎
桂素伟,公众号:桂迹一个简单的规则引擎例子
步骤确定了,下面是代码:
using RulesEngine;
using RulesEngine.Models;
using RulesEngine.Extensions;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json;
using System.Dynamic;
var path = @"C:\\MyFile\\Source\\Repos\\Asp.NetCoreExperiment\\Asp.NetCoreExperiment\\GoReplay\\GoReplayDemo01\\request_0.gor";
var expression = "input1.amount >= 900.00";
await ImpurityRemoval(path, expression);
/// <summary>
/// 除杂方法,会重新生成一个带有日期时间的新.gor文件
/// </summary>
static async Task ImpurityRemoval(string path, string expression)
{
using var readFile = new StreamReader(path, Encoding.UTF8);
using var writeFile = new StreamWriter(@$"{path.Replace(Path.GetFileName(path), Path.GetFileNameWithoutExtension(path) + "_" + DateTime.Now.ToString("yyyyMMddHHmmss") + Path.GetExtension(path))}", true, Encoding.UTF8);
var split = "????????????";
string? line;
var request = new StringBuilder();
while ((line = await readFile.ReadLineAsync()) != null)
{
if (line != split)
{
request.Append(line + "\\n");
}
else
{
request.Append(line + "\\n");
var list = GetJson(request.ToString());
foreach (var item in list)
{
var converter = new ExpandoObjectConverter();
var entity = JsonConvert.DeserializeObject<ExpandoObject>(item, converter);
if (await Filter(entity, expression))
{
await writeFile.WriteAsync(request.ToString());
}
}
request.Clear();
}
}
}
/// <summary>
/// 获取json,这里没有完全测试
/// </summary>
static List<string> GetJson(string jsonString)
{
var pattern = @"\\{(.|\\s)*\\}";
var list = new List<string>();
var matches = Regex.Matches(jsonString, pattern, RegexOptions.IgnoreCase);
foreach (Match m in matches)
{
list.Add(m.Value);
}
return list;
}
/// <summary>
/// 用规则引擎匹配过滤规则
/// </summary>
static async Task<bool> Filter(dynamic? entity, string expression)
{
var workRules = new WorkflowRules();
workRules.WorkflowName = "ImpurityRemoval";
workRules.Rules = new List<Rule>
{
new Rule
{
RuleName="ImpurityRemoval01",
SuccessEvent= "10",
RuleExpressionType= RuleExpressionType.LambdaExpression,
Expression= expression,
}
};
var rulesEngine = new RulesEngine.RulesEngine(new WorkflowRules[] { workRules });
List<RuleResultTree> resultList = await rulesEngine.ExecuteAllRulesAsync("ImpurityRemoval", entity);
var result = false;
resultList.OnSuccess((eventName) =>
{
result = true;
});
return result;
}
回放
gor --input-file=request_0_20210821234723.gor --output-http="http://localhost:5000"
注意事项:
在录制的时候本机请求不进行录制,需要外部访问api
在除杂过程中,重新生成gor文件时,换行一定要UNIX(LF),不要是Windows(CRLF),说人话就是生成文件的换行用\\n,不要\\r\\n,否则回放时goreplay不起作用
以上是关于Goreplay来做流量回放的主要内容,如果未能解决你的问题,请参考以下文章
流量回放工具之GoReplay input_file 源码分析
流量回放工具之GoReplay input_file 源码分析
流量回放工具之GoReplay input_file 源码分析