XiHan Framework 处于预览阶段

查看获取方式
跳转到内容

XiHan.Framework.Protocols.Grpc ​

gRPC 协议适配器,提供 protocols.grpc@1:把 Expose.Grpc 的操作契约发布成 gRPC 一元方法(服务 {Resource}、方法 {Verb}),以操作的 JSON Schema 作为 protobuf 描述在两种线格式之间转换,并发布由同一份描述生成的 .proto。适用于服务之间要用 gRPC 调用操作的场景。

项内容
包 IDXiHan.Framework.Protocols.Grpc
环层Ring 5(协议与插件)
能力提供 protocols.grpc@1;依赖 kernel.hosting@1
特性入口GrpcProtocolFeature
配置节XiHan:Protocols:Grpc
依赖XiHan.Framework.Kernel、XiHan.Framework.Hosting.AspNetCore、XiHan.Framework.Localization.Abstractions;Grpc.AspNetCore.Server;共享框架 Microsoft.AspNetCore.App
AOT兼容(IsAotCompatible)
稳定性Preview

概述 ​

GrpcProtocolFeature 调用 AddGrpc(),登记选项与一个 IServiceMethodProvider:方法在运行时按操作表动态绑定,消息以字节数组传递,不需要编译 .proto,也不依赖 Google.Protobuf。操作表在第一次解析时建成,这时全部特性已装配、登记表已定型。

每个方法调用都是一次独立调用:处理器以请求的 HTTP/2 头建调用上下文(traceparent、baggage、authorization、accept-language、xihan-deadline 或 grpc-timeout),把请求按 Schema 从 protobuf 解码为 JSON 载荷,经完整内核管道执行,再把响应编码回 protobuf。gRPC 方法带 PipelineBypassMetadata,不经 UseXiHan() 的外层调用。失败映射为 gRPC 状态,错误码与 trace-id 放在尾部元数据。

何时使用 ​

调用方是 gRPC 客户端(其他语言的服务、需要 HTTP/2 与二进制线格式的场景)时用它。浏览器与通用 HTTP 客户端用 Protocols.Http。只支持一元方法,流式方法与 gRPC 反射服务未提供。

安装与启用 ​

bash
dotnet add package XiHan.Framework.Protocols.Grpc --prerelease

当前是预览版,安装要带 --prerelease;从源码或本地包源引用见快速上手。Profiles.Full 已包含本包。

csharp
using XiHan.Framework.Hosting.AspNetCore;
using XiHan.Framework.Profiles.Standard;
using XiHan.Framework.Protocols.Grpc;
using XiHan.Framework.Protocols.Grpc.Services;

var builder = WebApplication.CreateBuilder(args);
builder.AddXiHan(xihan => xihan.UseStandardProfile().UseFeature<GrpcProtocolFeature>());

var app = builder.Build();
app.UseXiHan();
app.MapXiHanGrpc();    // /{package}.{Service}/{Method}
app.MapXiHanProto();   // GET /operations.proto
app.Run();

不用 TLS 时给 gRPC 单开一个 HTTP/2 端点(h2c):

json
{
  "Kestrel": {
    "Endpoints": {
      "Http": { "Url": "http://localhost:5000" },
      "Grpc": { "Url": "http://localhost:5001", "Protocols": "Http2" }
    }
  }
}

配置 ​

键类型缺省说明
XiHan:Protocols:Grpc:Packagestring空protobuf 包名(小写标识符以点分隔),写进 .proto 的 package,也是方法路径前缀
XiHan:Protocols:Grpc:Methods:<操作 ID>string—Service/Method,覆盖推导的名字
json
{
  "XiHan": {
    "Protocols": {
      "Grpc": {
        "Package": "acme.orders",
        "Methods": { "orders.list": "Orders/ListAll" }
      }
    }
  }
}

主要类型 ​

类型说明
GrpcProtocolFeature特性入口
GrpcProtocolOptionsPackage、Methods;MethodFor(contract);FromConfiguration
Services.OperationGrpcEndpointRouteBuilderExtensionsMapXiHanGrpc()、MapXiHanProto(pattern)(缺省 /operations.proto,text/plain)
Methods.GrpcMethodConventionDerive(contract):资源段与动词的 PascalCase
Methods.GrpcMethodName服务名与方法名;PathFor(package)、FullServiceName(package)、Parse("Orders/List")
Methods.GrpcOperationTable暴露给 gRPC 的操作、各自的请求与响应消息、生成的 .proto 文本
Proto.ProtoSchemaFromJsonSchema(schema):由 JSON Schema 建 protobuf 消息描述
Proto.ProtoDecoder、Proto.ProtoEncoderprotobuf 与 JSON 之间的转换
Proto.ProtoFileBuilder由消息描述生成 .proto
Proto.ProtoMessage、ProtoField、ProtoValueType、ProtoKind、ProtoCardinality消息描述模型
GrpcErrors本包的错误码

使用示例 ​

客户端用发布出的 .proto 调用(samples/SimpleApp):

bash
curl -s localhost:5000/operations.proto -o operations.proto
grpcurl -plaintext -proto operations.proto -H "authorization: ApiKey dev-alice-key" \
  -d '{"name":"widget","amount":3}' localhost:5001 Orders/Create

JSON Schema 到 protobuf 的映射表与生成的 .proto 见 gRPC、MCP 与 CloudEvents。

行为与限制 ​

  • 暴露给 gRPC 的操作必须有 Schema;名字、Schema 与消息形状的问题都在映射时失败,应用启动不起来。
  • 方法名:服务 = 资源段的 PascalCase(order-lines → OrderLines),方法 = 动词的 PascalCase;XiHan:Protocols:Grpc:Methods:<操作 ID> = Service/Method 显式覆盖;包名 XiHan:Protocols:Grpc:Package 写进 .proto 的 package,也是路径前缀(/{package}.Orders/Create)。名字不合法或重复即启动失败。发布范围是 Expose 含 Grpc 且非 Stability.Internal 的操作。
  • 消息映射(ProtoSchema):消息名取 Schema 的 title(封闭泛型带实参名,如 PageResultOfUserResponse,ADR-0034),$defs 里的每个对象定义一个消息;字段号按 Schema 属性顺序从 1 起;string → string(base64 → bytes)、boolean → bool、integer 按 format int32 / int64(无格式 → 十进制文本)、number 按 format float / double(decimal、无格式 → 十进制文本)、数组 → repeated、additionalProperties → map<string, T>、$ref → 嵌套消息(指向字符串枚举这类标量定义时按该标量映射为 string,不建消息也不建 proto enum)、可空 → optional、无约束 → JSON 文本。嵌套数组与映射里的映射不可表示,启动失败。.proto 文件由同一份描述生成并经 MapXiHanProto()(GET /operations.proto)发布给客户端。
  • 调用来源记 grpc 与方法全名,远端地址与 User-Agent 沿用 HTTP/2 请求(ADR-0043);端点绕过 UseXiHan() 的回写,响应完全由 gRPC 处理器产出。流式方法与 gRPC 反射服务未提供。
  • 线上缺席的布尔、数值、repeated、map 字段按 proto3 默认值补进 JSON;字符串、字节、嵌套消息缺席即缺席。
  • 字符串枚举映射为 string,不建 proto enum;integer 无格式与 decimal 映射为十进制文本。
  • 应用未就绪(启动中或正在停止)时以 Unavailable 拒绝、不进管道:尾部元数据带 xihan-error-code: KERNEL_UNAVAILABLE_001 与 xihan-trace-id,grpc-message 按 accept-language 翻译。
KINDgRPC 状态
VALIDATIONInvalidArgument
NOTFOUNDNotFound
CONFLICTAborted
DENIEDPermissionDenied;SECURITY_DENIED_001、SECURITY_DENIED_003 为 Unauthenticated
UNAVAILABLEUnavailable
TIMEOUTDeadlineExceeded
CANCELLEDCancelled
其他Internal
错误码情形
PROTOCOLS_VALIDATION_005请求不是合法的 protobuf 或与 Schema 不符(InvalidArgument)
PROTOCOLS_VALIDATION_006暴露给 gRPC 的操作没有 Schema,或 Schema 无法映射为 protobuf(启动失败)
PROTOCOLS_VALIDATION_007推导或配置的服务 / 方法名不合法(启动失败)
PROTOCOLS_CONFLICT_004两个操作得到同一个服务 / 方法名(启动失败)
PROTOCOLS_CONFLICT_003同名 protobuf 消息在不同操作里形状不同(启动失败)
PROTOCOLS_UNEXPECTED_001响应无法按 Schema 编码为 protobuf(Internal)

尾部元数据 xihan-error-code 是错误码,xihan-trace-id 是 trace-id(成功时也有);grpc-message 按 accept-language 翻译。

相关 ​

Released under The MIT License