将 gRPC services 从 C 核迁移到 ASP.NET Core
作者:John Luo
由于底层堆栈的实现,并非所有功能在基于 C 核的 gRPC应用与基于 ASP.NET Core 的应用程序之间的工作方式相同。 本文档重点介绍两个堆栈之间的迁移的主要区别。
gRPC 服务实现生存期
在 ASP.NET Core 堆栈中,默认情况下,使用范围内的生存期创建 gRPC services。 与此相反,默认情况下 gRPC C 核心将绑定到单一实例生存期内的服务。
范围内的生存期允许服务实现使用范围内的生存期解析其他服务。 例如,作用域内的生存期还可以通过构造函数注入解析 DI 容器 DbContext
。 使用范围生存期:
- 为每个请求构造服务实现的新实例。
- 不能通过实现类型上的实例成员来共享请求之间的状态。
- 预期是在 DI 容器的单一实例服务中存储共享状态。 在 gRPC 服务实现的构造函数中解析存储的共享状态。
有关服务生存期的详细信息,请参阅 在 ASP.NET Core 依赖注入。
添加单一实例服务
为了促进从 gRPC 的 C 核心实现到 ASP.NET Core 的转换,可以将服务实现的服务生存期从作用域改为单一实例。 这涉及到将服务实现的实例添加到 DI 容器:
public void ConfigureServices(IServiceCollection services) { services.AddGrpc(); services.AddSingleton(new GreeterService()); }
但是,具有单一生存期的服务实现不再能够通过构造函数注入来解析范围内的服务。
配置 gRPC services 选项
在基于 C 的应用程序中,当构造服务器实例时,将在 ChannelOption
配置 grpc.max_receive_message_length
和 grpc.max_send_message_length
等设置。
在 ASP.NET Core 中,gRPC 通过 GrpcServiceOptions
类型提供配置。 例如,可以通过 AddGrpc
配置 gRPC 服务的最大传入消息大小。 下面的示例将默认 MaxReceiveMessageSize
为 4 MB 到 16 MB:
public void ConfigureServices(IServiceCollection services) { services.AddGrpc(options => { options.MaxReceiveMessageSize = 16 * 1024 * 1024; // 16 MB }); }
有关配置的详细信息,请参阅 gRPC for .NET 配置。
Logging
基于 C 核的应用依赖于 GrpcEnvironment
来配置记录器,以便进行调试。 ASP.NET Core 堆栈通过日志记录 API提供此功能。 例如,可以通过构造函数注入将记录器添加到 gRPC 服务:
public class GreeterService : Greeter.GreeterBase { public GreeterService(ILogger<GreeterService> logger) { } }
HTTPS
基于 C 核的应用通过服务器端口属性配置 HTTPS。 类似的概念用于在 ASP.NET Core 中配置服务器。 例如,Kestrel 使用终结点配置来实现此功能。
gRPC 拦截 vs 中间件
与基于 gRPC 的应用中的侦听器相比,中间件提供的功能类似。 ASP.NET Core ASP.NET Core 中间件和侦听器在概念上类似。 两者:
- 用于构造处理 gRPC 请求的管道。
- 允许在管道中的下一个组件之前或之后执行工作。
- 提供对
HttpContext
的访问权限:- 在中间件中,
HttpContext
是参数。 - 在拦截中,可以通过
ServerCallContext.GetHttpContext
扩展方法使用ServerCallContext
参数访问HttpContext
。 请注意,此功能特定于运行 ASP.NET Core 中的侦听器。
- 在中间件中,
gRPC 侦听器与 ASP.NET Core 中间件的不同之处:
- 侦听器
- 使用ServerCallContext在 gRPC 抽象层上操作。
- 提供以下内容的访问权限:
- 发送到调用的反序列化消息。
- 序列化之前从调用返回的消息。
- 可以捕获和处理从 gRPC 服务引发的异常。
- 中间件:
- 在 gRPC 侦听器之前运行。
- 对基础 HTTP/2 消息进行操作。
- 只能访问请求和响应流中的字节。