本文档讨论了在 .NET 上开发 gRPC 应用程序时经常遇到的问题。
默认情况下,gRPC 模板和示例使用传输层安全性(TLS)来保护 gRPC 服务。 gRPC 客户端需要使用安全连接来成功调用受保护的 gRPC 服务。
可以在应用启动时,验证 ASP.NET Core gRPC 服务是否正在使用 TLS。 该服务将侦听 HTTPS 终结点:
info: Microsoft.Hosting.Lifetime[0] Now listening on: https://localhost:5001 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development
.NET Core 客户端必须使用服务器地址中 https
,才能使用安全连接调用:
static async Task Main(string[] args) { // The port number(5001) must match the port of the gRPC server. var channel = GrpcChannel.ForAddress("https://localhost:5001"); var client = new Greet.GreeterClient(channel); }
所有 gRPC 客户端实现都支持 TLS。 从其他语言 gRPC 的客户端通常需要配置有 SslCredentials
的通道。 SslCredentials
指定客户端将使用的证书,并且必须使用该证书,而不是使用不安全凭据。 有关将不同 gRPC 客户端实现配置为使用 TLS 的示例,请参阅GRPC Authentication。
.NET gRPC 客户端要求服务具有可信证书。 在没有受信任的证书的情况下调用 gRPC 服务时,将返回以下错误消息:
未经处理的异常。 System.net.http.httprequestexception:无法建立 SSL 连接,请参阅内部异常。 ---的 > AuthenticationException:根据验证过程,远程证书无效。
如果要在本地测试应用程序,并且不信任 ASP.NET Core HTTPS 开发证书,则可能会看到此错误。 有关解决此问题的说明,请参阅在 Windows 和 macOS 上信任 ASP.NET Core HTTPS 开发证书。
如果要在另一台计算机上调用 gRPC 服务,并且无法信任该证书,则可以将 gRPC 客户端配置为忽略无效的证书。 以下代码使用HttpClientHandler来允许不带可信证书的调用:
var httpClientHandler = new HttpClientHandler(); // Return `true` to allow certificates that are untrusted/invalid httpClientHandler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator; var httpClient = new HttpClient(httpClientHandler); var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpClient = httpClient }); var client = new Greet.GreeterClient(channel);
警告
不受信任的证书只应在应用程序开发过程中使用。 生产应用应始终使用有效的证书。
若要将不安全的 gRPC 服务与 .NET Core 客户端一起调用,需要进行其他配置。 GRPC 客户端必须将 System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
开关设置为 true
并使用服务器地址中的 http
:
// This switch must be set before creating the GrpcChannel/HttpClient. AppContext.SetSwitch( "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); // The port number(5000) must match the port of the gRPC server. var channel = GrpcChannel.ForAddress("http://localhost:5000"); var client = new Greet.GreeterClient(channel);
Kestrel 不支持 macOS 上的 HTTP/2 和更早的 Windows 版本,如 Windows 7。 默认情况下,ASP.NET Core gRPC 模板和示例使用 TLS。 当您尝试启动 gRPC 服务器时,您将看到以下错误消息:
无法绑定到 IPv4 环回接口上的 https://localhost:5001:在 macOS 上不支持 HTTP/2,因为缺少 ALPN 支持。 "。
若要解决此问题,请将 Kestrel 和 gRPC 客户端配置为在不使用 TLS 的情况下使用 HTTP/2。 只应在开发过程中执行此操作。 如果不使用 TLS,将会在不加密的情况下发送 gRPC 消息。
Kestrel 必须在Program.cs中配置不包含 TLS 的 HTTP/2 终结点:
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.ConfigureKestrel(options => { // Setup a HTTP/2 endpoint without TLS. options.ListenLocalhost(5000, o => o.Protocols = HttpProtocols.Http2); }); webBuilder.UseStartup<Startup>(); });
如果未使用 TLS 配置 HTTP/2 终结点,则终结点的ListenOptions必须设置为 HttpProtocols.Http2
。 无法使用 HttpProtocols.Http1AndHttp2
,因为需要使用 TLS 来协商 HTTP/2。 如果没有 TLS,与端点的所有连接默认为 HTTP/1.1,并且 gRPC 调用失败。
GRPC 客户端还必须配置为不使用 TLS。 有关详细信息,请参阅Call 不安全的 gRPC services 与 .Net Core client。
警告
只应在应用程序开发过程中使用不带 TLS 的 HTTP/2。 生产应用应始终使用传输安全性。 有关详细信息,请参阅gRPC for ASP.NET Core 中的安全注意事项。
具体的客户端和服务基类的 gRPC 代码生成需要从项目引用 protobuf 文件和工具。 必须包括:
<Protobuf>
项组中使用的proto文件。 导入的proto文件必须由项目引用。有关生成 gRPC C#资产的详细信息,请参阅 使用 C# 的 gRPC 服务。
默认情况下,<Protobuf>
引用将生成具体的客户端和服务基类。 可以使用引用元素的 GrpcServices
特性来限制C#资产生成。 有效 GrpcServices
选项如下:
Both
(当不存在时则为默认值)Server
Client
None
托管 gRPC services 的 ASP.NET Core web 应用只需生成服务基类:
<ItemGroup> <Protobuf Include="Protos\greet.proto" GrpcServices="Server" /> </ItemGroup>
发出 gRPC 调用的 gRPC 客户端应用只需要生成的具体客户端:
<ItemGroup> <Protobuf Include="Protos\greet.proto" GrpcServices="Client" /> </ItemGroup>
WPF 项目有一个已知问题,可阻止 gRPC 代码生成正常运行。 在 WPF 项目中生成的任何 gRPC 类型(通过引用 Grpc.Tools
和proto文件)在使用时将创建编译错误:
错误 CS0246:找不到类型或命名空间名称 "MyGrpcServices" (是否缺少 using 指令或程序集引用?)
可以通过以下方式解决此问题:
<Protobuf>
项目组。WPF 应用程序可以使用来自新类库项目的 gRPC 生成类型。
警告
Azure 应用服务或 IIS 当前不支持 ASP.NET Core gRPC。 Http.Sys 的 HTTP/2 实现不支持 gRPC 依赖的 HTTP 响应尾随标头。 有关详细信息,请参阅此 GitHub 问题。