MoneyTree.Resilience 1.0.3

MoneyTree.Resilience 弹性策略

📋 概述

MoneyTree.Resilience 基于 Microsoft.Extensions.Resilience(Polly v8) 封装,提供重试、熔断、超时、限流、资源隔离、降级等弹性策略,内置数据库、缓存、消息队列等常见场景的预配置管道,并集成了健康检查端点。

属性 说明
NuGet 包 MoneyTree.Resilience
外部依赖 MoneyTree.CoreMoneyTree.TelemetryMicrosoft.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

Version Downloads Last updated
1.1.1 1 7/21/2026
1.0.3 1 7/12/2026