Řešení potíží s gRPC v .NET Core
Tento dokument popisuje běžné problémy při vývoji aplikací gRPC v .NET.
Neshoda mezi konfigurací SSL/TLS klienta a služby
Šablona a ukázky gRPC ve výchozím nastavení používají protokol TLS (Transport Layer Security) k zabezpečení služeb gRPC. Klienti gRPC musí k úspěšnému volání zabezpečených služeb gRPC použít zabezpečené připojení.
Ověření, jestli ASP.NET Core gRPC používá PROTOKOL TLS, můžete ověřit v protokolech napsaných při spuštění aplikace. Služba bude naslouchat na koncovém bodu 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
Klient .NET Core musí na adrese serveru používat k https volání se zabezpečeným připojením:
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);
}
Všechny implementace klienta gRPC podporují protokol TLS. Klienti gRPC z jiných jazyků obvykle vyžadují kanál nakonfigurovaný pomocí SslCredentials . SslCredentials určuje certifikát, který bude klient používat, a musí se použít místo nezabezpečených přihlašovacích údajů. Příklady konfigurace různých implementací klienta gRPC pro použití protokolu TLS najdete v tématu o ověřování gRPC.
Volání služby gRPC s nedůvěryhodným nebo neplatným certifikátem
Klient .NET gRPC vyžaduje, aby služba měl důvěryhodný certifikát. Při volání služby gRPC bez důvěryhodného certifikátu se vrátí následující chybová zpráva:
Neošetřená výjimka. System.Net.Http.HttpRequestException: Připojení SSL nebylo možné navázat, viz vnitřní výjimka. ---> System. Security. Authentication. AuthenticationException –: vzdálený certifikát je podle ověřovací procedury neplatný.
Tato chyba se může zobrazit, pokud testujete aplikaci místně a ASP.NET Core certifikát pro vývoj HTTPS není důvěryhodný. Pokyny k vyřešení tohoto problému naleznete v tématu Trust ASP.NET Core certifikát pro vývoj https ve Windows a MacOS.
Pokud voláte službu gRPC na jiném počítači a nemůžete důvěřovat certifikátu, může být klient gRPC nakonfigurovaný tak, aby ignoroval neplatný certifikát. Následující kód používá HttpClientHandler. ServerCertificateCustomValidationCallback k povolení volání bez důvěryhodného certifikátu:
var httpHandler = new HttpClientHandler();
// Return `true` to allow certificates that are untrusted/invalid
httpHandler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = httpHandler });
var client = new Greet.GreeterClient(channel);
Upozornění
Nedůvěryhodné certifikáty by se měly používat jenom při vývoji aplikací. Produkční aplikace by měly vždy používat platné certifikáty.
Volání nezabezpečených služeb gRPC pomocí klienta .NET Core
Klient .NET gRPC může na adrese serveru volat nezabezpečené služby gRPC od určující http . Například, GrpcChannel.ForAddress("http://localhost:5000").
Existují některé další požadavky na volání nezabezpečených služeb gRPC v závislosti na verzi rozhraní .NET, kterou používá aplikace:
Rozhraní .NET 5 nebo novější vyžaduje Grpc .NET. Client verze 2.32.0 nebo novější.
.NET Core 3. x vyžaduje další konfiguraci. Aplikace musí nastavit
System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupportpřepínač natrue:// 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);
System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupportPřepínač je vyžadován pouze pro .NET Core 3. x. Neprovede nic v rozhraní .NET 5 a není vyžadováno.
Nepovedlo se spustit aplikaci ASP.NET Core gRPC v macOS
Kestrel nepodporuje HTTP/2 s TLS na macOS a ve starších verzích Windows, jako je Windows 7. ASP.NET Core šablona a ukázky gRPC standardně používají protokol TLS. Při pokusu o spuštění serveru gRPC se zobrazí následující chybová zpráva:
Nedá se vytvořit vazba na https://localhost:5001 rozhraní IPv4 zpětné smyčky: v MacOS se nepodporuje HTTP/2 přes TLS, protože chybí podpora ALPN.
Pokud chcete tento problém obvyřešit, nakonfigurujte klienta gRPC tak, aby Kestrel protokol HTTP/2 bez protokolu TLS používat. Měli byste to provést pouze během vývoje. Pokud protokol TLS nepou ít, budou se zprávy gRPC odesílat bez šifrování.
Kestrel v souboru Program.cs musí nakonfigurovat koncový bod HTTP/2 bez protokolu TLS:
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>();
});
Pokud je koncový bod HTTP/2 nakonfigurovaný bez protokolu TLS, musí být parametr ListenOptions.Protocols koncového bodu nastavený na HttpProtocols.Http2 . HttpProtocols.Http1AndHttp2 nelze použít, protože protokol TLS je potřeba k vyjednání protokolu HTTP/2. Bez TLS všechna připojení ke koncovému bodu ve výchozím nastavení http/1.1 a volání gRPC selžou.
Pokud je koncový bod HTTP/2 nakonfigurovaný bez protokolu TLS, musí být parametr ListenOptions.Protocols koncového bodu nastavený na HttpProtocols.Http2 . HttpProtocols.Http1AndHttp2 nelze použít, protože protokol TLS je potřeba k vyjednání protokolu HTTP/2. Bez TLS všechna připojení ke koncovému bodu ve výchozím nastavení http/1.1 a volání gRPC selžou.
Klient gRPC musí být také nakonfigurovaný tak, aby nepouoval protokol TLS. Další informace najdete v tématu Volání nezabezpečených služeb gRPC pomocí klienta .NET Core.
Upozornění
Protokol HTTP/2 bez protokolu TLS by se měl používat pouze během vývoje aplikací. Produkční aplikace by vždy měly používat zabezpečení přenosu. Další informace najdete v tématu Aspekty zabezpečení v gRPC pro ASP.NET Core.
Prostředky gRPC jazyka C# nejsou kódem generovaným ze souborů .proto.
Generování kódu gRPC konkrétních klientů a základních tříd služeb vyžaduje, aby se na soubory protobuf a nástroje odkazovala z projektu. Musíte zahrnout:
- Soubory .proto, které chcete použít ve
<Protobuf>skupině položek. Na importované soubory .proto musí odkazovat projekt. - Odkaz na balíček nástrojů pro gRPC nástrojů pro gRPC. Tools.
Další informace o generování gRPCch prostředků jazyka C# naleznete v tématu Služby gRPC s jazykem C# .
ASP.NET Core webová aplikace hostující služby gRPC potřebuje jenom vygenerovanou základní třídu služby:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
Klientská aplikace gRPC, která provádí volání gRPC, potřebuje jenom konkrétního vygenerovaného klienta:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>
Projekty WPF nemůžou generovat gRPC prostředky C# z. Proto soubory
Projekty WPF mají známý problém , který brání správnému fungování generování kódu gRPC. Všechny typy gRPC generované v projektu WPF odkazem Grpc.Tools a . proto soubory vytvoří chyby kompilace při použití:
Chyba CS0246: nepovedlo se najít typ nebo název oboru názvů ' MyGrpcServices ' (nechybí Direktiva using nebo odkaz na sestavení?)
Tento problém můžete vyřešit pomocí těchto potíží:
- Vytvořte nový projekt knihovny tříd .NET Core.
- V novém projektu přidejte odkazy pro povolení generování kódu jazyka C# z * . proto soubory:
- Přidejte následující odkazy na balíčky:
- Do skupiny položek přidejte soubory * .. .
<Protobuf>
- V aplikaci WPF přidejte odkaz na nový projekt.
Aplikace WPF může použít gRPC generované typy z nového projektu knihovny tříd.
Volání služeb gRPC hostovaných v podadresáři
Součást cesty adresy kanálu gRPC se při provádění volání gRPC ignoruje. Například GrpcChannel.ForAddress("https://localhost:5001/ignored_path") nebudete používat ignored_path při směrování volání gRPC pro službu.
Cesta k adrese se ignoruje, protože gRPC má standardizovanou, cestunou strukturu adres. GRPC adresa kombinuje názvy balíčků, služeb a metod: https://localhost:5001/PackageName.ServiceName/MethodName .
Existují některé scénáře, kdy aplikace potřebuje zahrnout cestu s gRPC voláními. Například když je aplikace ASP.NET Core gRPC hostovaná v adresáři IIS a adresář musí být zahrnutý v žádosti. Je-li požadována cesta, lze ji přidat do volání gRPC pomocí SubdirectoryHandler níže uvedené vlastní:
/// <summary>
/// A delegating handler that adds a subdirectory to the URI of gRPC requests.
/// </summary>
public class SubdirectoryHandler : DelegatingHandler
{
private readonly string _subdirectory;
public SubdirectoryHandler(HttpMessageHandler innerHandler, string subdirectory)
: base(innerHandler)
{
_subdirectory = subdirectory;
}
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var url = $"{request.RequestUri.Scheme}://{request.RequestUri.Host}";
url += $"{_subdirectory}{request.RequestUri.AbsolutePath}";
request.RequestUri = new Uri(url, UriKind.Absolute);
return base.SendAsync(request, cancellationToken);
}
}
SubdirectoryHandler se používá při vytvoření kanálu gRPC.
var handler = new SubdirectoryHandler(new HttpClientHandler(), "/MyApp");
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
var reply = await client.SayHelloAsync(new HelloRequest { Name = ".NET" });
Předchozí kód:
- Vytvoří
SubdirectoryHandlers cestou/MyApp. - Nakonfiguruje kanál, který se má použít
SubdirectoryHandler. - Volá službu gRPC s
SayHelloAsync. Volání gRPC je odesláno dohttps://localhost:5001/MyApp/greet.Greeter/SayHello.
Upozornění
ASP.NET Core gRPC má další požadavky pro použití s Azure App Service nebo službou IIS. Další informace o tom, kde lze použít gRPC, naleznete v tématu gRPC na platformách podporovaných .NET .