Table of Contents

gRPC 服务间通信

内部服务之间的高性能调用用 gRPC(HTTP/2 + 二进制 + 强类型契约)。Ledon 把"服务发现/映射/客户端注册"接到同一套自动发现约定上。

服务端:自动发现 + 约定映射

builder.Services.AddLedonGrpc();   // AddGrpc + 发现 gRPC 服务实现类
app.MapLedonGrpcServices();        // 逐个映射(幂等)

发现判据与 protoc 生成代码的形状对齐:具体类、非抽象,且基类链上带 [BindServiceMethod] 特性(即 XxxBase 的派生类)。业务实现类照常写在模块程序集里:

public class GreeterService(GreeterDbContext db) : Greeter.GreeterBase
{
    public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context) { /* ... */ }
}
  • 手动 MapGrpcService<T>() 已映射过的服务不会重复映射(多处装配安全);
  • 想精确控制时直接用自己的 MapGrpcService 调用,不冲突。

客户端:强类型客户端

builder.Services.AddLedonGrpcClient<Greeter.GreeterClient>("https://localhost:7001");

地址配置驱动。注意:Ledon.Resilience 的策略挂在 HttpClient 管道上(只认 HttpRequestException 与 5xx),不会自动套到 gRPC 调用上——gRPC 失败抛的是 RpcException。需要重试/熔断时请自行配置 GrpcClientFactoryOptions 或按 RpcException.Status.StatusCode 自建策略。多服务寻址可接 Ledon.Aspire 的服务发现(https+服务名://)。

异常 → 状态码映射

builder.Services.AddLedonGrpc();   // UseErrorInterceptor 默认开

业务异常不再一律变成 Unknown + 堆栈(那等于把内部结构送给调用方):

异常 状态码
ArgumentException InvalidArgument
KeyNotFoundException NotFound
UnauthorizedAccessException PermissionDenied
OperationCanceledException Cancelled
TimeoutException DeadlineExceeded
InvalidOperationException FailedPrecondition
其余 Unknown + 通用文案(真实原因只进日志)

自定义映射实现 IGrpcExceptionMapper 并注册进容器,优先于默认表:

public class StockExceptionMapper : IGrpcExceptionMapper
{
    public bool TryMap(Exception ex, out StatusCode code, out string detail)
    {
        if (ex is InsufficientStockException stock)
        {
            code = StatusCode.ResourceExhausted;
            detail = $"库存不足:{stock.Sku}";
            return true;
        }
        code = StatusCode.Unknown;
        detail = "";
        return false;
    }
}

deadline 兜底:客户端没传 deadline 时按 LedonGrpcOptions.DefaultDeadline(默认 30 秒) 强制取消。没有它,一个不观察取消令牌的处理器会把连接永久占住。

健康检查与日志拦截器

builder.Services.AddLedonGrpc();   // UseHealthChecks / UseLoggingInterceptor 默认都开
app.MapLedonGrpcServices();        // 一并映射 grpc.health.v1.Health
  • 标准健康服务:grpc.health.v1.Health/Check(整体状态默认 Serving)——负载均衡/K8s 的 gRPC 探针直接可用,不必自己实现;
  • 日志拦截器:每次调用记录方法、耗时与成败(unary/客户端流/服务端流/双流四种都覆盖)——gRPC 调用不只在链路里可见;
  • 异常映射拦截器:业务异常 → 语义化状态码(见上一节),且在日志拦截器外层,所以日志记的是最终状态码;
  • 关掉任一:AddLedonGrpc(o => { o.UseHealthChecks = false; o.UseLoggingInterceptor = false; o.UseErrorInterceptor = false; })。

与 HTTP API 的分工

场景 选择
浏览器/第三方开放 API Ledon.Web(REST)
内部服务间高频、强契约调用 Ledon.Grpc
异步解耦、跨服务领域事件 Ledon.Queues + 传输

相关主题