MoneyTree.Resilience 1.0.3
MoneyTree.Resilience 弹性策略
📋 概述
MoneyTree.Resilience 基于 Microsoft.Extensions.Resilience(Polly v8) 封装,提供重试、熔断、超时、限流、资源隔离、降级等弹性策略,内置数据库、缓存、消息队列等常见场景的预配置管道,并集成了健康检查端点。
| 属性 | 说明 |
|---|---|
| NuGet 包 | MoneyTree.Resilience |
| 外部依赖 | MoneyTree.Core、MoneyTree.Telemetry、Microsoft.Extensions.Resilience |
| 定位 | 基于 Polly v8 的弹性策略封装 |
🏗️ 项目文件结构
MoneyTree.Resilience/
├── MoneyTree.Resilience.csproj
├── GlobalUsings.cs
├── Core/
│ ├── ResilienceOptions.cs # 弹性策略配置选项
│ └── ResiliencePipelineFactory.cs # 弹性管道工厂
├── HealthChecks/
│ ├── HealthCheckDelegates.cs # 四个具名委托类型定义
│ ├── DatabaseHealthCheck.cs # 数据库健康检查
│ ├── RedisHealthCheck.cs # Redis 健康检查
│ ├── MessageQueueHealthCheck.cs # 消息队列健康检查
│ └── ConfigurationCenterHealthCheck.cs # 配置中心健康检查
├── Middleware/
│ └── ResilienceMiddleware.cs # 弹性中间件
└── Extensions/
├── ResilienceBuilder.cs # 流畅配置构造器
└── ResilienceExtensions.cs # DI 注册扩展
🛡️ 弹性策略一览
| 策略 | 说明 | 典型场景 |
|---|---|---|
| Retry | 失败自动重试,指数退避 | 瞬时故障(网络抖动、临时超载) |
| CircuitBreaker | 连续失败熔断,冷却后半开 | 下游服务不可用 |
| Timeout | 超时直接取消 | 资源保护,防止长时间等待 |
| RateLimiter | 限制并发请求数 | 保护下游服务不被压垮 |
| Bulkhead | 资源隔离 | 防止级联故障 |
| Fallback | 故障降级 | 提升可用性,返回备用数据 |
🚀 快速开始
基础配置
// Program.cs
using MoneyTree.Resilience.Extensions;
var builder = WebApplication.CreateBuilder(args);
// 使用默认配置
builder.Services.AddMoneyTreeResilience();
// 或自定义配置
builder.Services.AddMoneyTreeResilience(r =>
{
r.WithRetry(count: 3, baseDelaySeconds: 1)
.WithTimeout(seconds: 30)
.WithCircuitBreaker(
failureThreshold: 0.5,
samplingDurationSeconds: 30,
breakDurationSeconds: 60);
});
var app = builder.Build();
// 使用弹性中间件
app.UseMoneyTreeResilience();
app.Run();
📖 使用示例
在服务中使用弹性管道
框架预置了多种场景的专用管道:
using MoneyTree.Resilience.Core;
public class OrderService
{
private readonly ResiliencePipelineFactory _pipelineFactory;
public OrderService(ResiliencePipelineFactory pipelineFactory)
{
_pipelineFactory = pipelineFactory;
}
// 数据库操作使用数据库专用管道(重试 + 熔断 + 超时)
public async Task<Order?> GetOrderAsync(string id)
{
var pipeline = _pipelineFactory.CreateDatabase();
return await pipeline.ExecuteAsync(
async token =>
{
// 数据库查询逻辑
await Task.Delay(100, token);
return new Order { Id = id };
},
CancellationToken.None);
}
// 缓存操作使用缓存专用管道(超时保护)
public async Task<T?> GetFromCacheAsync<T>(string key) where T : class
{
var pipeline = _pipelineFactory.CreateCache();
return await pipeline.ExecuteAsync(
async token =>
{
// Redis 缓存查询逻辑
await Task.Delay(10, token);
return default(T);
},
CancellationToken.None);
}
// 消息队列操作使用消息管道(更多重试次数)
public async Task PublishMessageAsync<T>(T message)
{
var pipeline = _pipelineFactory.CreateMessaging();
await pipeline.ExecuteAsync(
async token =>
{
// 消息队列发布逻辑
await Task.Delay(50, token);
},
CancellationToken.None);
}
}
预配置管道说明
| 管道 | 默认策略 | 适用场景 |
|---|---|---|
CreateDatabase() |
重试 3 次 + 超时 30s + 熔断 | SQL 数据库操作 |
CreateCache() |
超时 5s | Redis/缓存操作 |
CreateMessaging() |
重试 5 次 + 指数退避 | 消息队列 |
CreateDefault() |
重试 1 次 + 超时 10s | 通用场景 |
GetOrCreate(name) |
自定义命名策略 | 特殊需求 |
HttpClient 弹性策略
为特定的 HttpClient 添加弹性策略:
builder.Services.AddHttpClient("PaymentService", client =>
{
client.BaseAddress = new Uri("https://payment.example.com");
client.Timeout = TimeSpan.FromSeconds(15);
})
.AddResilienceHandler("payment-pipeline");
// 自定义管道名称
builder.Services.AddHttpClient("InventoryService", client =>
{
client.BaseAddress = new Uri("https://inventory.example.com");
})
.AddResilienceHandler("inventory-pipeline");
🏥 健康检查
内置健康检查端点
app.MapHealthChecks("/health", new HealthCheckOptions
{
ResponseWriter = async (context, report) =>
{
context.Response.ContentType = "application/json";
var result = new
{
status = report.Status.ToString(),
checks = report.Entries.Select(e => new
{
name = e.Key,
status = e.Value.Status.ToString(),
description = e.Value.Description
}),
totalDuration = report.TotalDuration.TotalMilliseconds
};
await context.Response.WriteAsJsonAsync(result);
}
});
内置健康检查项
| 检查项 | 说明 | 激活委托类型 |
|---|---|---|
DatabaseHealthCheck |
检查数据库连接状态 | DatabaseHealthCheckDelegate |
RedisHealthCheck |
检查 Redis 连接状态 | RedisHealthCheckDelegate |
MessageQueueHealthCheck |
检查消息队列连接状态 | MessageQueueHealthCheckDelegate |
ConfigurationCenterHealthCheck |
检查配置中心连接状态 | ConfigurationCenterHealthCheckDelegate |
健康检查渐进式激活
四个健康检查默认返回 Healthy("未配置"),不影响 /health 端点状态。
通过 DI 注入对应的具名委托即可激活实际检测逻辑,各检查独立激活、互不干扰:
// 激活数据库健康检查
builder.Services.AddSingleton<DatabaseHealthCheckDelegate>(sp =>
{
var db = sp.GetRequiredService<AppDbContext>();
return async ct => await db.Database.CanConnectAsync(ct);
});
// 激活 Redis 健康检查(独立于数据库检查)
builder.Services.AddSingleton<RedisHealthCheckDelegate>(sp =>
{
var multiplexer = sp.GetRequiredService<IConnectionMultiplexer>();
return async ct => (await multiplexer.GetDatabase().PingAsync(ct)) != default;
});
// 激活消息队列健康检查
builder.Services.AddSingleton<MessageQueueHealthCheckDelegate>(sp =>
{
var connection = sp.GetRequiredService<IConnection>();
return async ct => connection.IsOpen;
});
// 激活配置中心健康检查
builder.Services.AddSingleton<ConfigurationCenterHealthCheckDelegate>(sp =>
{
var factory = sp.GetRequiredService<IHttpClientFactory>();
return async ct =>
{
var client = factory.CreateClient("HealthCheck");
var response = await client.GetAsync("/health", ct);
return response.IsSuccessStatusCode;
};
});
设计要点: 每个检查使用独立的具名委托类型(
XXXHealthCheckDelegate), 而非共用的Func<CancellationToken, Task<bool>>,确保 DI 容器能独立解析各检查的委托, 避免类型碰撞导致的多检查共享同一逻辑的问题。
🏁 完整微服务配置示例
整合配置中心、服务发现、弹性策略、遥测的完整启动配置:
using System.Reflection;
using MoneyTree.ServiceDiscovery.Extensions;
using MoneyTree.Resilience.Extensions;
using MoneyTree.Telemetry.Extensions;
var builder = WebApplication.CreateBuilder(args);
// 配置中心
builder.Services.AddMoneyTreeConfigurationCenter(c =>
{
c.WithServerAddress("https://config.mycompany.com")
.WithAppId("order-service");
});
// 服务注册发现
builder.Services.AddMoneyTreeServiceDiscovery(sd =>
{
sd.WithServiceName("OrderService")
.UseConsul("http://consul:8500")
.WithHealthCheck("/health");
});
// 弹性策略
builder.Services.AddMoneyTreeResilience(r =>
{
r.WithRetry(3, 1)
.WithTimeout(30)
.WithCircuitBreaker();
});
// 遥测
builder.Services.AddMoneyTreeTelemetry(t =>
{
t.WithServiceName("OrderService")
.UseOpenTelemetryCollector();
});
// 属性注入
builder.Services.AddMoneyTreeAutoInjection(options =>
options.ScanFromAssembly(Assembly.GetExecutingAssembly()));
var app = builder.Build();
app.UseMoneyTreeDefaults();
app.UseMoneyTreeResilience();
app.Run();
🔧 手动获取弹性管道
在应用任意位置手动获取和使用弹性管道:
public class HealthCheckService
{
private readonly ResiliencePipelineFactory _factory;
public HealthCheckService(ResiliencePipelineFactory factory)
{
_factory = factory;
}
public async Task<bool> CheckAllDependenciesAsync()
{
var pipeline = _factory.GetOrCreate("default");
return await pipeline.ExecuteAsync(async token =>
{
// 执行健康检查逻辑
await Task.Delay(50, token);
return true;
},
CancellationToken.None);
}
}
Showing the top 20 packages that depend on MoneyTree.Resilience.
| Packages | Downloads |
|---|---|
|
MoneyTree.ServiceDefaults
MoneyTree Framework 服务默认配置。快速落地项目的默认入口,集成弹性策略 + 健康检查 + 可选遥测/服务发现。
|
1 |
.NET 10.0
- MoneyTree.Core (>= 1.0.3)
- Microsoft.AspNetCore.Http.Abstractions (>= 2.3.11)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 10.0.9)
- Microsoft.Extensions.Http.Resilience (>= 10.7.0)
- Microsoft.Extensions.Resilience (>= 10.7.0)
- Polly.Core (>= 8.7.0)
- Polly.Extensions (>= 8.7.0)