nbomber基础负载测试需定义scenario(含name和至少一个step),step用try/catch+response.fail()处理异常超时,通过loadsimulator配置并发与持续时间,避免共享httpclient。

如何用 NBomber 在 C# 中定义一个基础负载测试场景
直接用 NBomber 写负载测试,核心是构造 Scenario 并传给 Runner。它不依赖外部 DSL 或配置文件,所有逻辑都在 C# 代码里,适合集成进 CI 或按需动态生成压测路径。
关键步骤:
-
Scenario必须指定一个name和至少一个Step(即被压测的函数) - 每个
Step接收Context参数,返回Response(成功/失败 + 可选耗时、数据) - 用
Runner.RegisterScenarios()注册后调用Run()才真正执行
示例:模拟 HTTP GET 请求
var httpStep = Step.Create("get_homepage", async context =>
{
var client = new HttpClient();
var response = await client.GetAsync("https://example.com");
return response.IsSuccessStatusCode
? Response.Ok()
: Response.Fail($"HTTP {response.StatusCode}");
});
Step 中如何处理异常和超时而不让整个场景中断
NBomber 默认把未捕获异常视为失败响应,但不会终止整个测试进程——这是设计使然,也是你必须主动兜底的原因。常见误区是直接 throw 异常却不包装成 Response.Fail(),导致日志难追踪、成功率统计失真。
正确做法:
- 所有 I/O 操作加
try/catch,用Response.Fail(message)显式返回失败 - 用
HttpClient.Timeout或CancellationToken控制单次请求上限,避免 step 卡死拖慢整体 RPS - 不要在
Step里做阻塞调用(如Task.Wait()、.Result),会吃光线程池
错误写法:throw new TimeoutException(); → 日志只显示 "unhandled exception",无上下文;正确写法:return Response.Fail("timeout");
如何配置并发数、持续时间和阶梯式加压
NBomber 的负载策略由 LoadSimulator 控制,不是靠循环或 Sleep 实现。你得明确选择一种模式并传入参数,否则默认是 1 用户持续 1 秒——基本没意义。
常用组合:
-
LoadSimulator.InjectPerSec(rate: 100):每秒注入 100 个请求,恒定速率,适合稳态压力测试 -
LoadSimulator.InjectPerSec(rate: 100, during: TimeSpan.FromMinutes(5)):持续 5 分钟 -
LoadSimulator.InjectAtOnce(concurrentUsers: 50):瞬间起 50 个并发,适合秒杀类场景 - 阶梯加压需组合多个
Scenario或用InjectPerSec分段调用 Runner(NBomber 本身不内置“逐步 ramp-up”语法)
注意:concurrentUsers 不等于线程数,NBomber 基于 Task 调度,实际并发受 ThreadPool 和异步 IO 限制。
为什么本地跑通了,CI 环境却报 SocketException 或连接拒绝
这不是 NBomber 的问题,而是 .NET 默认连接池和 DNS 缓存行为在容器或高并发下暴露出来。典型现象是前几十秒正常,之后大量 Connection refused 或 Too many open files。
关键修复点:
- 禁用
HttpClient共享实例的 DNS 缓存:new SocketsHttpHandler { PooledConnectionLifetime = TimeSpan.FromMinutes(1) } - 为每个
Step创建独立HttpClient实例(或复用带生命周期管理的 handler),避免共享连接池打满 - Linux 容器中检查
ulimit -n,NBomber 高并发时可能突破默认 1024 文件描述符限制 - 避免在
Step外部 new HttpClient 并长期持有——这是最常被忽略的资源泄漏点
真实踩坑点:用 static readonly HttpClient 是反模式,尤其在长时间运行的压测中,DNS 变更无法感知,连接复用失效,最终表现为随机失败。










