Healnet.Infrastructure 2.0.3

There is a newer version of this package available.
See the version list below for details.
dotnet add package Healnet.Infrastructure --version 2.0.3
                    
NuGet\Install-Package Healnet.Infrastructure -Version 2.0.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Healnet.Infrastructure" Version="2.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Healnet.Infrastructure" Version="2.0.3" />
                    
Directory.Packages.props
<PackageReference Include="Healnet.Infrastructure" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Healnet.Infrastructure --version 2.0.3
                    
#r "nuget: Healnet.Infrastructure, 2.0.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Healnet.Infrastructure@2.0.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Healnet.Infrastructure&version=2.0.3
                    
Install as a Cake Addin
#tool nuget:?package=Healnet.Infrastructure&version=2.0.3
                    
Install as a Cake Tool

Healnet.Infrastructure 基础设施模块

版本: v1.7.2 | 模块: Healnet.Infrastructure | 依赖: Healnet.Core

概述

Healnet.Infrastructure 是 Healnet 微服务框架的基础设施层,对 24+ 个 中间件/基础设施组件进行了统一封装,提供一致的 DI 注册方式与配置约定,业务系统通过简单的 AddXxx 扩展方法即可集成。

v1.7.2 修复:

  • 🐛 消除所有编译警告 - 修复 52 个编译警告(NU1603、NU1902/03/04、MSB3539、CS0618)
  • 🐛 更新包版本 - 所有 NuGet 包更新为具体版本号,避免版本降级警告
  • 🐛 修复输出路径设置 - 使用 Directory.Build.props 统一设置输出路径,消除 MSB3539 警告

v1.7.2 修复:

  • 🐛 修复 GrpcOperationFilter 空引用 bug - 确保 operation.Tagsoperation.Extensions 不为 null

v1.7.0 新增功能:

  • Consul 便捷调用 - IConsulHttpClient 自动服务发现 + 负载均衡,UseConsul 一行代码注册服务
  • YARP 配置文件驱动 - AddYarpConsulDiscovery(IConfiguration) 从 appsettings.json 读取服务映射
  • YARP 弹性策略 - AddYarpResilience() 集成 Polly 重试/熔断/限流
  • Swagger gRPC 支持 - gRPC JSON Transcoding,自动将 gRPC 方法映射为 REST HTTP 端点

快速导航

类别 模块 注册方法 配置节点 生命周期
认证安全 Authentication AddJwtAuth(...) Healnet:Jwt Scoped/Singleton
认证安全 Security AddSecurityHeaders(...) / AddCorsPolicy(...) Healnet:Security / Healnet:Cors Singleton
数据存储 SqlSugar AddSqlSugar(...) Healnet:SqlSugar Singleton
数据存储 MongoDB 手动注册 IMongoClient + IMongoDbContext 自定义 Singleton
数据存储 ClickHouse AddClickHouse(...) Healnet:ClickHouse Scoped
数据存储 ElasticSearch AddElasticSearch(...) Healnet:ElasticSearch Singleton
缓存锁 Redis AddRedis(...) Healnet:Redis Singleton
消息队列 RabbitMQ 手动注册 IConnection + IRabbitMQService 自定义 Singleton
服务发现 Consul AddConsul(...) Healnet:Consul Singleton
HTTP 客户端 Http AddHttpClientService(...) Healnet:HttpClient:{name} Scoped
API 网关 YARP AddYarpConfigBuilder() / AddYarpConsulDiscovery(...) 代码配置 Transient/Singleton
RPC gRPC AddGrpcService(...) Healnet:gRPC Singleton
可观测性 Logging UseHealnetSerilog() / AddSerilog(...) Healnet:Serilog Singleton
可观测性 OpenTelemetry AddHealnetOpenTelemetry(...) 代码配置 Singleton
可观测性 HealthChecks AddHealnetHealthChecks(...) + MapHealnetHealthChecks() 代码配置 Transient
可观测性 Middleware UseExceptionHandling() / UseRequestLogging() / UseCorrelationId() 代码配置 Transient
容错 Resilience AddResilience(...) 代码配置 Singleton
容错 AOP 拦截器 AddAspectCoreWithInterceptors() 代码配置 Scoped
API 文档 Swagger AddSwagger(...) + UseSwaggerWithUI() Healnet:Swagger Singleton
对象存储 OSS AddAliyunOssFileService(...) Healnet:FileStorage Singleton
AI 集成 AI AddAIServices(...) Healnet:AI Scoped
工作单元 UnitOfWork AddUnitOfWork() Scoped

通用入口

对于只需要常用基础服务的场景,提供了快捷注册入口:

// Program.cs
builder.Services.AddHealnetInfrastructure(options =>
{
    options.HttpClientName = "default";
    options.ConsulAddress = "http://consul.healnet.net:8500";
});

// 或仅基础通用服务(Serilog + SnowflakeId)
builder.Services.AddHealnetCommonServices();

模块详细说明

1. JWT 认证 (Healnet.Infrastructure.Authentication)

JwtOptions 配置项

属性 类型 默认值 说明
SecretKey string "" JWT 签名密钥(必须 ≥ 32 字符)
Issuer string Healnet Token 签发者
Audience string Healnet.Api Token 受众
AccessTokenExpireMinutes int 60 Access Token 过期时间(分钟)
RefreshTokenExpireDays int 7 Refresh Token 过期时间(天)
ValidateIssuer bool true 是否验证签发者
ValidateAudience bool true 是否验证受众
ValidateLifetime bool true 是否验证有效期
ValidateIssuerSigningKey bool true 是否验证签名密钥

注册方式:

// 方式一:配置委托
builder.Services.AddJwtAuth(options =>
{
    options.SecretKey = "your-32-char-minimum-secret-key!!";
    options.Issuer = "Healnet";
    options.Audience = "Healnet.Api";
    options.AccessTokenExpireMinutes = 60;
    options.RefreshTokenExpireDays = 7;
});

// 方式二:配置文件
builder.Services.AddJwtAuth(builder.Configuration);

// 中间件(必须)
app.UseAuthentication();
app.UseAuthorization();

配置示例 (appsettings.json):

{
  "Healnet": {
    "Jwt": {
      "SecretKey": "your-secret-key-at-least-32-characters-long!!",
      "Issuer": "Healnet",
      "Audience": "Healnet.Api",
      "AccessTokenExpireMinutes": 60,
      "RefreshTokenExpireDays": 7,
      "ValidateIssuer": true,
      "ValidateAudience": true,
      "ValidateLifetime": true,
      "ValidateIssuerSigningKey": true
    }
  }
}

注入服务:

接口 实现 生命周期 用途
JwtHelper JwtHelper Scoped Token 生成及验证
ITokenService TokenService Scoped Token 管理(生成/刷新/撤销)

JwtHelper API:

public class JwtHelper
{
    string GenerateToken(IEnumerable<Claim> claims);  // 生成 JWT Token
    ClaimsPrincipal? ValidateToken(string token);     // 验证 Token
    string? GetClaimValue(string token, string claimType);  // 获取声明值
    long? GetUserId(string token);                    // 获取用户 ID
    string? GetEmail(string token);                   // 获取邮箱
    bool IsTokenValid(string token);                  // Token 是否有效
}

⚠️ SecretKey 必须 ≥ 32 字符,注册时自动校验,不满足会抛出 ArgumentException


2. 安全头与 CORS (Healnet.Infrastructure.Security)

SecurityOptions 配置项

属性 类型 默认值 说明
EnableHsts bool true 是否启用 HSTS(HTTP 严格传输安全)
HstsMaxAgeDays int 365 HSTS 最大有效期(天)
EnableCsp bool false 是否启用 CSP(内容安全策略)
ContentSecurityPolicy string default-src 'self'; CSP 策略内容
EnableXssProtection bool true 是否启用 XSS 保护
EnableFrameOptions bool true 是否启用 Frame 选项
FrameOptionsValue string DENY Frame 选项值(DENY/SAMEORIGIN)
EnableXContentTypeOptions bool true 是否启用 X-Content-Type-Options
ReferrerPolicy string strict-origin-when-cross-origin Referrer-Policy 响应头值
PermissionsPolicy string? null Permissions-Policy 响应头值
CustomHeaders Dictionary<string, string> [] 自定义响应头

CorsOptions 配置项

属性 类型 默认值 说明
AllowedOrigins List<string> [] 允许的源
AllowedMethods List<string> ["GET", "POST", "PUT", "DELETE"] 允许的 HTTP 方法
AllowedHeaders List<string> ["Authorization", "Content-Type"] 允许的请求头
AllowCredentials bool false 是否允许凭证
PreflightMaxAgeMinutes int 10 预检请求缓存时间(分钟)

安全头注册:

// 默认安全头(XSS、Frame、HSTS、CSP 等)
builder.Services.AddSecurityHeaders();
app.UseSecurityHeaders();

// 自定义
builder.Services.AddSecurityHeaders(options =>
{
    options.EnableHsts = true;
    options.EnableCsp = true;
    options.ContentSecurityPolicy = "default-src 'self'; script-src 'self' 'unsafe-inline';";
});

// 从配置读取
builder.Services.AddSecurityHeaders(builder.Configuration);
app.UseSecurityHeaders();

配置示例:

{
  "Healnet": {
    "Security": {
      "EnableHsts": false,
      "EnableXssProtection": true,
      "EnableFrameOptions": true,
      "FrameOptionsValue": "DENY",
      "EnableCsp": false,
      "EnableXContentTypeOptions": true,
      "ReferrerPolicy": "strict-origin-when-cross-origin"
    },
    "Cors": {
      "AllowedOrigins": ["http://localhost:3000"],
      "AllowCredentials": true,
      "AllowedMethods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
      "AllowedHeaders": ["Content-Type", "Authorization", "X-Requested-With"]
    }
  }
}

⚠️ 注意

  1. UseSecurityHeaders() 必须在 UseCors() 之前调用
  2. 开发环境建议禁用 HSTS(EnableHsts = false
  3. 如果 AllowCredentials = true,则 AllowedOrigins 不能包含 *

CORS 注册:

// 从配置读取
builder.Services.AddCorsPolicy(builder.Configuration, "DefaultPolicy");
app.UseCorsPolicy("DefaultPolicy");

// 手动配置
builder.Services.AddCorsPolicy("MyPolicy", policy =>
{
    policy.WithOrigins("https://app.example.com")
          .AllowCredentials()
          .WithMethods("GET", "POST");
});

3. SqlSugar ORM (Healnet.Infrastructure.SqlSugar)

注册方式:

// 方式一:连接字符串(默认 MySQL)
builder.Services.AddSqlSugar("Server=192.168.114.213;Database=KP_BRM;Uid=sa;Pwd=xxx;");

// 方式二:配置委托
builder.Services.AddSqlSugar(options =>
{
    options.ConnectionString = "Server=...";
    options.DbType = DbType.SqlServer;
    options.IsAutoCloseConnection = true;
    options.InitKeyType = InitKeyType.Attribute;
});

// 方式三:配置文件
builder.Services.AddSqlSugar(builder.Configuration);

配置示例:

{
  "Healnet": {
    "SqlSugar": {
      "ConnectionString": "Server=192.168.114.213;Database=KP_BRM;Uid=sa;Pwd=xxx;",
      "DbType": "SqlServer",
      "IsAutoCloseConnection": true,
      "InitKeyType": "Attribute"
    }
  }
}

注入服务:

接口 实现 生命周期 用途
ISqlSugarClient SqlSugarClient Singleton ORM 操作(SQL 日志/错误自动上报)

注册实体仓储:

// 单个实体
builder.Services.AddSqlSugarRepository<User>();

// 批量注册
builder.Services.AddSqlSugarRepositories(typeof(User), typeof(Order), typeof(Product));

// 使用
public class UserService
{
    private readonly ISqlSugarRepository<User> _repo;
    public UserService(ISqlSugarRepository<User> repo) => _repo = repo;
}

ISqlSugarRepository<T> 方法:

Task<T> GetByIdAsync(object id);
Task<List<T>> GetAllAsync();
Task<List<T>> GetListAsync(Expression<Func<T, bool>> where);
Task<T> GetSingleAsync(Expression<Func<T, bool>> where);
Task<int> InsertAsync(T entity);
Task<int> InsertRangeAsync(List<T> entities);
Task<int> UpdateAsync(T entity);
Task<int> UpdateRangeAsync(List<T> entities);
Task<int> DeleteByIdAsync(object id);
Task<int> DeleteAsync(Expression<Func<T, bool>> where);
Task<int> CountAsync(Expression<Func<T, bool>> where);
Task<List<T>> PageAsync(int page, int size, Expression<Func<T, bool>> where, ...);

4. MongoDB (Healnet.Infrastructure.MongoDB)

MongoDB 模块采用手动 DI 注册方式,提供灵活的多租户上下文。

注册方式:

// 注册 MongoClient
builder.Services.AddSingleton<IMongoClient>(sp =>
    new MongoClient("mongodb://localhost:27017"));

// 注册配置
builder.Services.AddSingleton(new MongoDbContextOptions
{
    DefaultDatabase = "HealnetDB",
    EnableAudit = true,
    TenantDatabases = new List<TenantDatabase>
    {
        new() { TenantId = "tenant1", DatabaseName = "HealnetDB_Tenant1" }
    }
});

// 注册上下文
builder.Services.AddSingleton<IMongoDbContext, MongoDbContext>();

// 注册审计处理
builder.Services.AddSingleton<IAuditHandler, AuditHandler>();

注入服务:

接口 实现 用途
IMongoDbContext MongoDbContext 数据库上下文,支持多租户、集合获取
IAuditHandler AuditHandler 审计字段自动设置(CreatedAt/CreatedBy/UpdatedAt/UpdatedBy)

使用示例:

public class UserRepository
{
    private readonly IMongoDbContext _context;

    public UserRepository(IMongoDbContext context) => _context = context;

    public async Task<User> GetById(string id)
    {
        var collection = _context.GetCollection<User>();
        return await collection.Find(u => u.Id == id).FirstOrDefaultAsync();
    }

    public async Task Insert(User user)
    {
        // 审计处理由 AuditHandler 在 MongoDbContext 层自动完成
        var collection = _context.GetCollection<User>();
        await collection.InsertOneAsync(user);
    }
}

6. ElasticSearch (Healnet.Infrastructure.ElasticSearch)

注册方式:

// 配置委托
builder.Services.AddElasticSearch(options =>
{
    options.Uri = "http://192.168.114.206:9200";
    options.DefaultIndex = "healnet-logs";
    options.Username = "elastic";
    options.Password = "password";
});

// 配置文件
builder.Services.AddElasticSearch(builder.Configuration);

配置示例:

{
  "Healnet": {
    "ElasticSearch": {
      "Uri": "http://192.168.114.206:9200",
      "DefaultIndex": "healnet-logs",
      "Username": "elastic",
      "Password": "password",
      "EnableSniffing": false,
      "TimeoutSeconds": 30,
      "ConnectionLimit": 10
    }
  }
}

注入服务:

接口 实现 用途
IElasticClient ElasticClient (NEST) ElasticSearch 低级客户端
IElasticSearchService ElasticSearchService 全文搜索、聚合查询封装

7. Redis 缓存与分布式锁 (Healnet.Infrastructure.Redis)

RedisOptions 配置项

属性 类型 默认值 说明
Configuration string localhost:6379 Redis 连接字符串
KeyPrefix string Healnet: 缓存键前缀(从配置读取)
ConnectTimeout int 5000 连接超时(毫秒)
SyncTimeout int 5000 同步超时(毫秒)
AbortOnConnectFail bool false 连接失败时是否中止
DefaultDatabase int 0 默认数据库编号

注册方式:

// 配置委托
builder.Services.AddRedis(options =>
{
    options.Configuration = "192.168.114.233:6379,defaultDatabase=0";
    options.KeyPrefix = "Healnet:Identity:";
    options.ConnectTimeout = 5000;
    options.SyncTimeout = 5000;
    options.AbortOnConnectFail = false;
    options.DefaultDatabase = 0;
});

// 配置文件
builder.Services.AddRedis(builder.Configuration);

配置示例:

{
  "Healnet": {
    "Redis": {
      "Configuration": "192.168.114.233:6379,defaultDatabase=0",
      "KeyPrefix": "Healnet:Identity:",
      "ConnectTimeout": 5000,
      "SyncTimeout": 5000,
      "AbortOnConnectFail": false,
      "DefaultDatabase": 0
    }
  }
}

⚠️ 注意

  1. InstanceNamePoolSize 字段在代码里未使用,建议从配置中删除
  2. 如果没有密码,不要写 password=,,直接省略即可
  3. KeyPrefix 会从配置读取,确保配置正确

注入服务:

接口 实现 生命周期 用途
IConnectionMultiplexer ConnectionMultiplexer Singleton Redis 连接
IRedisService / ICacheService RedisService Singleton 缓存读写、模式匹配、TTL
IDistributedLockService DistributedLockService Singleton 分布式锁(SETNX + Lua 原子释放)

IRedisService 核心 API:

// ICacheService 基础方法
Task SetAsync<T>(string key, T value, TimeSpan? expiry = null);
Task<T?> GetAsync<T>(string key);
Task<T?> GetOrSetAsync<T>(string key, Func<Task<T>> factory, TimeSpan? expiry = null);
Task RemoveAsync(string key);
Task<bool> ExistsAsync(string key);

// IRedisService 扩展方法
Task RefreshAsync(string key, TimeSpan expiry);         // 刷新过期时间
Task<List<string>> GetKeysByPatternAsync(string pattern); // SCAN 模式匹配
Task RemoveByPatternAsync(string pattern);               // 批量删除(Pipeline)
Task ClearAsync();                                       // FLUSHDB(危险操作)
Task<long> GetTtlAsync(string key);                      // 剩余 TTL(秒)
string KeyPrefix { get; set; }                           // 键前缀(默认 "Healnet:")

🔒 安全特性: 释放锁使用 Lua 脚本 GET + DEL 原子校验锁值,防止误删他人持有的锁;锁值通过 AsyncLocal 上下文隔离存储。


8. RabbitMQ 消息队列 (Healnet.Infrastructure.RabbitMQ)

注册方式:

// 注册 RabbitMQ 连接
builder.Services.AddSingleton<IConnection>(sp =>
{
    var factory = new ConnectionFactory
    {
        HostName = "192.168.114.206",
        UserName = "guest",
        Password = "guest",
        VirtualHost = "/"
    };
    return factory.CreateConnection();
});

// 注册服务
builder.Services.AddSingleton<IRabbitMQService, RabbitMQService>();

注入服务:

接口 实现 生命周期 用途
IRabbitMQService RabbitMQService Singleton 消息发布、订阅、队列/交换机管理

核心 API:

// 消息发布
void Publish<T>(string exchange, string routingKey, T message);
Task PublishAsync<T>(string exchange, string routingKey, T message);

// 消息订阅
void Subscribe<T>(string queue, Func<T, Task> handler);
Task SubscribeAsync<T>(string queue, Func<T, Task> handler);

// 队列管理
void DeclareQueue(string queue, bool durable = true, bool exclusive = false, bool autoDelete = false);
void DeclareExchange(string exchange, string type = "direct");
void BindQueue(string queue, string exchange, string routingKey);
void PurgeQueue(string queue);
void DeleteQueue(string queue);
void DeleteExchange(string exchange);
bool IsConnected { get; }
void Initialize();

9. Consul 服务发现 (Healnet.Infrastructure.Consul)

注册方式:

// 直接指定地址
builder.Services.AddConsul("http://consul.healnet.net:8500");

// 配置委托
builder.Services.AddConsul(options =>
{
    options.Address = "http://consul.healnet.net:8500";
});

// 配置文件
builder.Services.AddConsul(builder.Configuration);

配置示例:

{
  "Healnet": {
    "Consul": {
      "Address": "http://consul.healnet.net:8500"
    }
  }
}

注入服务:

接口 实现 生命周期 用途
IConsulService ConsulService Singleton 服务注册、发现、KV 存储、健康检查

10. HTTP 客户端 (Healnet.Infrastructure.Http)

内置 重试(指数退避 2^n 秒)、熔断(阈值 5 次/30 秒)、超时(30 秒)三种 Polly 策略。

注册方式:

// 最简
builder.Services.AddHttpClientService();

// 带 BaseAddress
builder.Services.AddHttpClientService(client =>
{
    client.BaseAddress = new Uri("https://api.example.com");
    client.DefaultRequestHeaders.Add("Accept", "application/json");
});

// 自定义弹性策略
builder.Services.AddHttpClientService(
    client => client.BaseAddress = new Uri("https://api.example.com"),
    options =>
    {
        options.MaxRetries = 5;
        options.TimeoutSeconds = 60;
        options.CircuitBreakerThreshold = 10;
    });

// 泛型客户端
builder.Services.AddHttpClientService<IMyApiClient, MyApiClient>("my-api");

// 从配置读取(支持 Consul 服务发现集成)
builder.Services.AddHttpClientService(builder.Configuration, "default");

注入服务:

接口 实现 生命周期 用途
IHttpClientService HttpClientService Scoped HTTP 调用(GET/POST/PUT/DELETE)
IHttpClientFactoryService HttpClientFactoryService Singleton HttpClient 工厂

配置示例:

{
  "Healnet": {
    "HttpClient": {
      "default": {
        "BaseAddress": "https://api.example.com",
        "TimeoutSeconds": 30,
        "MaxRetries": 3,
        "CircuitBreakerThreshold": 5,
        "CircuitBreakerDurationSeconds": 30,
        "EnableConsulIntegration": false
      }
    }
  }
}

弹性策略 Builder 扩展(用于其他 IHttpClientBuilder):

services.AddHttpClient<ISomeClient, SomeClient>()
    .AddResiliencePolicies()              // 三合一(重试+熔断+超时)
    .AddRetryPolicy(maxRetries: 5)        // 仅重试
    .AddCircuitBreakerPolicy(10, 60)      // 仅熔断
    .AddTimeoutPolicy(seconds: 60);       // 仅超时

11. YARP API 网关 (Healnet.Infrastructure.YARP)

静态路由:

builder.Services.AddReverseProxy();
builder.Services.AddYarpConfigBuilder();

// 代码配置
builder.Services.AddYarpStaticConfig(options =>
{
    options.Routes.Add(new YarpRoute
    {
        RouteId = "api-route",
        ClusterId = "api-cluster",
        MatchPath = "/api/{**catch-all}"
    });
    options.Clusters.Add(new YarpCluster
    {
        ClusterId = "api-cluster",
        Destinations = new() { "http://localhost:5001" }
    });
});

Consul 动态服务发现:

builder.Services.AddReverseProxy();
builder.Services.AddYarpConsulDiscovery(options =>
{
    options.AddServiceMapping("auth-route", "auth-cluster", "auth-service", "/auth/{**catch-all}");
    options.AddServiceMapping("order-route", "order-cluster", "order-service", "/orders/{**catch-all}");
});

YARP 弹性策略(Polly 装饰器):

// 必须在 AddReverseProxy() 之后调用
builder.Services.AddReverseProxy();
builder.Services.AddResilience();  // 注册 IResiliencePolicyProvider
builder.Services.AddYarpResilience();  // 装饰 IHttpForwarder

12. gRPC (Healnet.Infrastructure.gRPC)

// 注册
builder.Services.AddGrpcService();

// 带配置
builder.Services.AddGrpcService(options =>
{
    options.EnableConsulIntegration = true;
});

// 从配置
builder.Services.AddGrpcService(builder.Configuration);

配置示例:

{
  "Healnet": {
    "gRPC": {
      "EnableConsulIntegration": false,
      "ConsulAddress": "http://localhost:8500",
      "DefaultTimeoutSeconds": 30,
      "EnableRetry": true,
      "MaxRetryAttempts": 3
    }
  }
}

⚠️ IGrpcService.CallGrpcMethodAsync 当前抛出 NotSupportedException,需业务系统自行集成 gRPC 客户端调用。


13. 日志 - Serilog (Healnet.Infrastructure.Logging)

推荐方式 — IHostBuilder:

var builder = WebApplication.CreateBuilder(args);
builder.Host.UseHealnetSerilog();  // 自动读取 Healnet:Serilog 配置,注册 ILoggerService

// 启用请求日志
app.UseSerilogRequestLogging();

IServiceCollection 方式:

// 默认控制台 + 文件日志
builder.Services.AddSerilogDefault();

// 自定义
builder.Services.AddSerilog(config =>
{
    config.MinimumLevel.Debug()
          .WriteTo.Console()
          .WriteTo.File("logs/app.log");
});

// 从配置文件
builder.Services.AddSerilog(builder.Configuration);

配置示例:

{
  "Healnet": {
    "Serilog": {
      "MinimumLevel": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      },
      "Console": {
        "Enabled": true,
        "OutputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Level:u3}] {Message:lj}{NewLine}{Exception}"
      },
      "File": {
        "Enabled": true,
        "Path": "logs/log-.txt",
        "RollingInterval": "Day",
        "RetainedFileCountLimit": 30,
        "OutputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Level:u3}] {Message:lj}{NewLine}{Exception}"
      },
      "Elasticsearch": {
        "Enabled": false,
        "NodeUris": "http://localhost:9200",
        "IndexFormat": "healnet-logs-{0:yyyy.MM.dd}",
        "AutoRegisterTemplate": true
      }
    }
  }
}

日志级别映射:

verbose / trace → Verbose
debug           → Debug
information/info → Information
warning/warn    → Warning
error           → Error
fatal/critical  → Fatal

14. OpenTelemetry 可观测性 (Healnet.Infrastructure.OpenTelemetry)

builder.Services.AddHealnetOpenTelemetry(options =>
{
    options.Enabled = true;
    options.ServiceName = "MyService";
    options.ServiceVersion = "1.0.0";

    // Trace / Metrics / Logging(默认全开)
    options.EnableTracing = true;
    options.EnableMetrics = true;
    options.EnableLogging = true;

    // 导出器
    options.Console.Enabled = true;
    options.Otlp.Enabled = true;
    options.Otlp.Endpoint = "http://jaeger:4317";
    options.Jaeger.Enabled = false;
    options.Zipkin.Enabled = false;

    // 自动埋点
    options.InstrumentationNames = new() { "AspNetCore", "HttpClient", "SqlClient" };
});

app.UseHealnetOpenTelemetry();

支持的导出器:

导出器 配置属性 默认地址
Console Console.Enabled
OTLP (gRPC) Otlp.Enabled / Otlp.Endpoint http://localhost:4317
Jaeger Jaeger.Enabled / Jaeger.Host:Port localhost:6831
Zipkin Zipkin.Enabled / Zipkin.Endpoint http://localhost:9411/api/v2/spans

15. 健康检查 (Healnet.Infrastructure.HealthChecks)

// 注册(支持 Redis / MongoDB / RabbitMQ)
builder.Services.AddHealnetHealthChecks(
    redisEnabled: true,
    mongoEnabled: true,
    rabbitMqEnabled: true);

// 映射端点(返回 JSON)
app.MapHealnetHealthChecks("/health");

健康检查响应格式:

{
  "Status": "Healthy",
  "Checks": [
    {
      "Name": "redis",
      "Status": "Healthy",
      "Description": "Redis is connected",
      "Duration": 12.5,
      "ErrorMessage": null
    }
  ],
  "TotalDuration": 25.8
}

16. 中间件 (Healnet.Infrastructure.Middleware)

// 异常处理(自动捕获未处理异常,返回统一 JSON)
app.UseExceptionHandling(showDetailedErrors: false);

// 请求日志(记录请求路径 + 耗时)
app.UseRequestLogging();

// 关联 ID(从 X-Correlation-Id 头读取或自动生成)
app.UseCorrelationId();

// 健康检查端点(自定义路径)
app.UseHealthCheck("/healthz");

⚠️ HealthCheckMiddlewareExceptionHandlingMiddleware (Infrastructure 版本) 已标记 [Obsolete],推荐使用 ASP.NET Core 内置健康检查及 Core 层 ExceptionHandlerMiddleware


17. 弹性策略 (Healnet.Infrastructure.Resilience)

// 默认配置
builder.Services.AddResilience();

// 自定义
builder.Services.AddResilience(options =>
{
    options.RetryCount = 5;
    options.CircuitBreakerThreshold = 10;
    options.CircuitBreakerDurationSeconds = 60;
});

// 注入
public class MyService
{
    public MyService(IResiliencePolicyProvider provider)
    {
        var retryPolicy = provider.GetRetryPolicy();
        var circuitBreaker = provider.GetCircuitBreakerPolicy();
    }
}

18. AOP 拦截器 (Healnet.Infrastructure.AOP)

基于 AspectCore 提供 5 个内置拦截器:

拦截器 用途
LogInterceptor 方法调用日志(入参/出参/耗时)
CacheInterceptor 方法结果缓存
ExceptionHandlerInterceptor 异常捕获与统一处理
PerformanceMonitorInterceptor 性能监控(慢方法告警)
RetryInterceptor 方法重试

注册方式:

// 方式一:全部注册
builder.Services.AddAspectCoreWithInterceptors();

// 方式二:选择性注册
builder.Services.AddAspectCore(config =>
{
    config.AddLogInterceptor()
          .AddExceptionHandlerInterceptor()
          .AddPerformanceMonitorInterceptor();
});

// 然后在需要代理的服务上用 [Intercept] 标记
[Intercept(typeof(LogInterceptor))]
public class UserService : IUserService
{
    // 所有方法自动记录日志
}

19. Swagger API 文档 (Healnet.Infrastructure.Swagger)

// 注册
builder.Services.AddSwagger(options =>
{
    options.Title = "My API";
    options.Version = "v1";
    options.EnableJwtAuth = true;
    options.IncludeXmlComments = true;
});

// 或从配置读取
builder.Services.AddSwagger(builder.Configuration);

// 启用
app.UseSwaggerWithUI();  // 路径: /swagger

配置示例:

{
  "Healnet": {
    "Swagger": {
      "Title": "Healnet API",
      "Description": "Healnet 微服务 API 文档",
      "Version": "v1",
      "EnableJwtAuth": true,
      "JwtSchemeName": "Bearer",
      "IncludeXmlComments": true,
      "DocExpansion": "List",
      "DefaultModelExpandDepth": 2
    }
  }
}

20. 阿里云 OSS 对象存储 (Healnet.Infrastructure.OSS)

// 方式一:简单参数
builder.Services.AddAliyunOssFileService(
    endpoint: "oss-cn-hangzhou.aliyuncs.com",
    accessKeyId: "your-access-key",
    accessKeySecret: "your-secret",
    bucketName: "my-bucket");

// 方式二:配置委托
builder.Services.AddAliyunOssFileService(options =>
{
    options.OssEndpoint = "oss-cn-hangzhou.aliyuncs.com";
    options.OssAccessKeyId = "your-access-key";
    options.OssAccessKeySecret = "your-secret";
    options.OssBucketName = "my-bucket";
});

// 方式三:配置文件
builder.Services.AddAliyunOssFileService(builder.Configuration);

配置示例:

{
  "Healnet": {
    "FileStorage": {
      "StorageType": "Oss",
      "OssEndpoint": "oss-cn-hangzhou.aliyuncs.com",
      "OssAccessKeyId": "your-access-key",
      "OssAccessKeySecret": "your-secret",
      "OssBucketName": "my-bucket",
      "BaseUrl": "https://cdn.example.com"
    }
  }
}

注入服务:

接口 实现 生命周期 用途
IFileService AliyunOssFileService Singleton 文件上传/下载/删除(替换默认实现)

21. AI 服务集成 (Healnet.Infrastructure.AI)

支持 Semantic KernelMicrosoft.Extensions.AI 两种 AI 框架,以及 Agent 框架。

// 完整 AI 服务
builder.Services.AddAIServices(options =>
{
    options.Provider = AIProvider.SemanticKernel;
    options.ApiKey = "sk-xxx";
    options.ModelName = "gpt-4o";
    options.Endpoint = "https://api.openai.com/v1";
});

// 仅 Semantic Kernel
builder.Services.AddSemanticKernelOnly(options => { ... });

// 仅 Microsoft.Extensions.AI
builder.Services.AddMicrosoftAIOnly(options => { ... });

// 仅 Agent Framework
builder.Services.AddAgentFrameworkOnly(options => { ... });

// 从配置文件
builder.Services.AddAIServices(builder.Configuration);

配置示例:

{
  "Healnet": {
    "AI": {
      "Provider": "SemanticKernel",
      "ApiKey": "sk-xxx",
      "Endpoint": "https://api.openai.com/v1",
      "ModelName": "gpt-4o",
      "MaxTokens": 4096,
      "Temperature": 0.7,
      "TopP": 0.9,
      "ContextWindowSize": 128000,
      "RAG": {
        "Enabled": true,
        "TopK": 5,
        "MaxContextLength": 8192
      },
      "AgentFramework": {
        "Endpoint": "https://agent.example.com",
        "DeploymentName": "my-agent",
        "EnableToolCalling": true,
        "MaxIterations": 10
      }
    }
  }
}

注入服务:

接口 实现 用途
IAIService UnifiedAIService 统一 AI 服务入口
IChatContextManager ChatContextManager 对话上下文管理
IRAGService RAGService 检索增强生成
IAgentService AgentService Agent 服务
IAgentContextManager AgentContextManager Agent 上下文管理
ICopilotClient CopilotClient / MicrosoftAIClient AI 客户端

22. 工作单元 (Healnet.Infrastructure.UnitOfWork)

builder.Services.AddUnitOfWork();

// 使用
public class OrderService
{
    private readonly IUnitOfWork _uow;
    public OrderService(IUnitOfWork uow) => _uow = uow;

    public async Task Process()
    {
        await _uow.BeginTransactionAsync();
        try
        {
            // 业务操作...
            await _uow.CommitTransactionAsync();
        }
        catch
        {
            await _uow.RollbackTransactionAsync();
            throw;
        }
    }
}

完整配置总览

以下是所有模块在实际 appsettings.json 中的配置结构一览(按需使用):

{
  "Healnet": {
    "Redis": {
      "Configuration": "localhost:6379",
      "InstanceName": "Healnet",
      "KeyPrefix": "Healnet:",
      "ConnectTimeout": 5000,
      "SyncTimeout": 5000,
      "AbortOnConnectFail": false,
      "DefaultDatabase": 0,
      "PoolSize": 10
    },
    "Jwt": {
      "SecretKey": "your-secret-key-at-least-32-characters-long!!",
      "Issuer": "Healnet",
      "Audience": "Healnet.Api",
      "AccessTokenExpireMinutes": 60,
      "RefreshTokenExpireDays": 7
    },
    "SqlSugar": {
      "ConnectionString": "Server=localhost;Database=MyDB;Uid=root;Pwd=123456;",
      "DbType": "MySql",
      "IsAutoCloseConnection": true,
      "InitKeyType": "Attribute"
    },
    "ElasticSearch": {
      "Uri": "http://localhost:9200",
      "DefaultIndex": "healnet-logs",
      "Username": "",
      "Password": ""
    },
    "Consul": {
      "Address": "http://localhost:8500"
    },
    "Serilog": {
      "MinimumLevel": "Information",
      "Console": { "Enabled": true },
      "File": { "Enabled": true, "Path": "logs/log-.txt", "RollingInterval": "Day" }
    },
    "Swagger": {
      "Title": "Healnet API",
      "Version": "v1",
      "EnableJwtAuth": true
    },
    "Security": {
      "EnableHsts": true,
      "EnableXssProtection": true
    },
    "Cors": {
      "AllowedOrigins": ["https://app.example.com"],
      "AllowedMethods": ["GET", "POST", "PUT", "DELETE"],
      "AllowedHeaders": ["Authorization", "Content-Type"]
    },
    "AI": {
      "Provider": "SemanticKernel",
      "ApiKey": "",
      "ModelName": "gpt-4o"
    },
    "FileStorage": {
      "StorageType": "Oss",
      "OssEndpoint": "",
      "OssAccessKeyId": "",
      "OssAccessKeySecret": "",
      "OssBucketName": ""
    },
    "gRPC": {
      "EnableConsulIntegration": false,
      "DefaultTimeoutSeconds": 30
    }
  }
}

依赖关系

Healnet.Infrastructure (net10.0)
├── Healnet.Core
├── Healnet.Common
├── StackExchange.Redis 2.9.0
├── MongoDB.Driver 2.29.0
├── SqlSugarCore 5.1.4
├── NEST 7.17.5
├── RabbitMQ.Client 6.8.1
├── Consul 1.7.14
├── Yarp.ReverseProxy 2.2.0
├── Grpc.AspNetCore 2.65.0
├── Serilog.AspNetCore 8.0.0
├── OpenTelemetry 1.7.x(Tracing + Metrics + Logging)
├── Polly 8.3.1
├── AspectCore 2.4.0
├── Swashbuckle 6.5.0
├── Microsoft.SemanticKernel 1.67.1
├── Microsoft.Extensions.AI 9.10.0
├── Aliyun.OSS.SDK.NetCore 2.14.1
└── Microsoft.AspNetCore.Authentication.JwtBearer 8.0.8

版本历史

版本 日期 变更
1.0.0 初始版本
1.1.0 添加 Microsoft.Extensions.AI 封装,完善文档
1.2.0 2026-05 新增 YARP 弹性策略装饰器、AddYarpResilience;AddSwagger 自动注册 AddEndpointsApiExplorer;UseHealnetSerilog 自动注册 ILoggerService;安全修复(分布式锁原子操作、密码哈希随机盐);gRPC/AI 桩实现改为 NotSupportedException;AOP 拦截器正确注册

已知问题与封装改进建议

检查日期: 2026-06-25 检查范围: Healnet.Infrastructure 所有模块 问题总数: 37 个

问题严重程度说明

严重程度 说明 数量
🔴 高 会导致运行时错误、数据丢失或安全漏洞 4
🟡 中 影响功能完整性、性能或可维护性 18
🟢 低 代码规范、文档完善等优化建议 15

🔴 高优先级问题(需要立即修复)

1. UnitOfWork.SaveChangesAsync 实现不正确

模块: UnitOfWork
文件: UnitOfWork/UnitOfWork.cs
问题: SaveChangesAsync() 方法直接返回 Task.FromResult(0),没有实际保存更改的逻辑
影响: 如果业务代码调用此方法,会误以为更改已保存
修复状态: ✅ 已修复(添加说明注释,SqlSugar 会自动保存更改)
建议: 对于 EF Core 等需要显式保存的 ORM,此方法需要真正实现

2. RabbitMQ 消息反序列化类型不安全

模块: RabbitMQ
文件: RabbitMQConsumerBase.cs
问题: DeserializeMessage<object> 反序列化所有消息为 object 类型,丢失类型信息
影响: 消息处理逻辑无法获取正确的类型,可能导致运行时错误
建议: 使用泛型或类型安全的消息包装器

3. AOP 模块中重复的 NullLogger 实现

模块: AOP
文件: LogInterceptor.cs, PerformanceMonitorInterceptor.cs, RetryInterceptor.cs
问题: 三个拦截器都实现了自己的 NullLogger 类,代码重复
影响: 代码维护困难,增加程序集大小
修复状态: ✅ 已修复(使用 Microsoft.Extensions.Logging.Abstractions.NullLogger.Instance
建议: 使用 .NET 内置的 NullLogger.Instance

4. MongoDB 审计处理器使用反射性能差

模块: MongoDB
文件: MongoHandlers.cs
问题: SetPropertyValue 方法使用反射设置属性值,性能较差
影响: 高频操作时性能下降
建议: 使用表达式树或预先编译的委托


🟡 中优先级问题(建议近期修复)

5. 配置选项类缺失或不完整

** affected 模块**: AI, ElasticSearch, gRPC, Http, Resilience

问题详情:

  • AI 模块: AddAIServices(IConfiguration) 方法中复制 options 的方式有问题
  • ElasticSearch 模块: 缺少 IElasticClient 的注册
  • gRPC 模块: GrpcOptions 类中的配置没有被实际使用
  • Http 模块: Consul 集成调用方式有误
  • Resilience 模块: 配置类命名不一致

修复状态: ✅ 已全部修复

6. 硬编码的默认值和 Header 名称

** affected 模块**: AOP, Middleware, MongoDB, OpenTelemetry

问题详情:

  • AOP 模块: 缓存过期时间、重试次数等硬编码
  • Middleware 模块: 关联 ID 的 Header 名称硬编码
  • MongoDB 模块: 默认数据库名称不合适
  • OpenTelemetry 模块: Jaeger 端口配置过时

建议: 创建配置类,支持从配置文件读取

7. 接口命名拼写错误和不一致

** affected 模块**: Resilience, YARP

问题详情:

  • Resilience 模块: 方法名拼写错误(GetCircuitBreakerPolicy 应为 GetCircuitBreakerPolicy
  • YARP 模块: 文件夹名为 YARP,但类和配置使用 YarpYarp(大小写不一致)

建议: 统一命名规范,修正拼写错误

8. 过时的代码未清理

** affected 模块**: Middleware

问题详情:

  • HealthCheckMiddleware.csExceptionHandlingMiddleware.cs 已标记 [Obsolete],但代码仍未删除

建议: 直接删除这些过时文件


🟢 低优先级问题(可后续优化)

9. 代码注释和文档完善

** affected 模块**: 所有模块

建议:

  • 添加 XML 文档注释
  • 更新 README.md 文件
  • 添加更多使用示例
10. 配置验证增强

** affected 模块**: 所有模块

建议:

  • 添加配置验证
  • 提供默认配置
  • 验证必要的配置项
11. 日志记录的规范化

** affected 模块**: 所有模块

建议:

  • 统一日志格式
  • 使用结构化日志
  • 添加适当的日志级别

模块检查状态汇总

模块 检查状态 问题数 修复状态
AOP ✅ 已检查 4 ✅ 已修复
Extensions ✅ 已检查 2 ⏳ 待修复
Middleware ✅ 已检查 4 ⏳ 待修复
MongoDB ✅ 已检查 3 ⏳ 待修复
OpenTelemetry ✅ 已检查 3 ⏳ 待修复
OSS ✅ 已检查 3 ⏳ 待修复
RabbitMQ ✅ 已检查 4 ⏳ 待修复
Resilience ✅ 已检查 3 ⏳ 待修复
UnitOfWork ✅ 已检查 3 ✅ 已修复
YARP ✅ 已检查 4 ⏳ 待修复
AI ✅ 已检查 2 ✅ 已修复
ElasticSearch ✅ 已检查 2 ✅ 已修复
gRPC ✅ 已检查 3 ✅ 已修复
HealthChecks ✅ 已检查 1 ✅ 已修复
Http ✅ 已检查 2 ✅ 已修复
Logging ✅ 已检查 1 ✅ 已修复
Authentication ✅ 已检查 0 -
Consul ✅ 已检查 0 -
Redis ✅ 已检查 0 -
Security ✅ 已检查 0 -
SqlSugar ✅ 已检查 0 ✅ 已修复
Swagger ✅ 已检查 0 -

下一步行动计划

  1. 立即修复(高优先级): 4 个问题已全部修复 ✅
  2. 近期修复(中优先级): 18 个问题,已修复 10 个,剩余 8 个待修复
  3. 后续优化(低优先级): 15 个问题,建议后续逐步优化

如何贡献

如果你发现了新的问题或有改进建议,请:

  1. 在代码中添加 TODOFIXME 注释
  2. 更新相应的 README.md 文件
  3. 提交 Pull Request 并描述问题和修复方案

维护者: Healnet Team
最后更新: 2026-06-25

更新日志

v1.7.2 (2026-06-25)

🐛 修复:

  • 消除所有编译警告(52个)
  • 更新所有 NuGet 包为具体版本号,避免版本降级警告
  • 使用 Directory.Build.props 统一设置输出路径,消除 MSB3539 警告
  • 修复 NullLogger 实现的可空性约束问题

📦 依赖更新:

  • SqlSugarCore: 5.1.4.58
  • SqlSugar.ClickHouseCore: 5.1.4.1
  • Consul: 1.7.14.1
  • StackExchange.Redis: 2.9.11
  • 其他所有包更新为具体版本

v1.7.1 (2026-06-20)

🐛 修复:

  • 修复 GrpcOperationFilter 空引用 bug

v1.7.0 (2026-06-15)

✨ 新增:

  • Consul 便捷调用接口 (IConsulHttpClient)
  • YARP 配置文件驱动
  • YARP 弹性策略集成
  • Swagger gRPC 支持

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.0.0 38 7/16/2026
2.0.7 59 7/10/2026
2.0.5 61 7/8/2026
2.0.3 65 6/30/2026
2.0.1 65 6/30/2026
2.0.0 64 6/29/2026
1.7.3 58 6/29/2026
1.7.2 63 6/25/2026
1.7.1 58 6/25/2026
1.7.0 63 6/25/2026
1.6.0 75 6/24/2026
1.5.0 63 6/16/2026
1.4.0 62 6/15/2026
1.3.0 76 5/29/2026
1.1.1 63 5/25/2026
1.1.0 66 5/22/2026
1.0.19 69 5/20/2026
1.0.18 59 5/20/2026
1.0.17 59 5/20/2026
1.0.15 63 5/20/2026
Loading failed

v2.0.3: 统一三库版本号;升级目标框架至 net10.0;更新所有依赖包至最新稳定版;移除 Infrastructure 项目中多余的 MSBuild 属性。v2.0.1: 依赖包版本升级,修复若干已知问题。v2.0.0: 重大版本更新,目标框架从 net8.0 升级至 net10.0,全面更新依赖包版本,优化 API 设计。