Rozwiązywanie problemów z usługą gRPC na platformie .NET
Autor: James Newton-King
Uwaga
Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.
Ostrzeżenie
Ta wersja ASP.NET Core nie jest już obsługiwana. Aby uzyskać więcej informacji, zobacz .NET i .NET Core Support Policy (Zasady obsługi platformy .NET Core). Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.
Ważne
Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.
W tym dokumencie omówiono często występujące problemy podczas tworzenia aplikacji gRPC na platformie .NET.
Niezgodność między konfiguracją protokołu SSL/TLS klienta i usługi
Szablon gRPC i przykłady używają protokołu Transport Layer Security (TLS) do zabezpieczania usług gRPC domyślnie. Klienci gRPC muszą pomyślnie wywoływać zabezpieczone usługi gRPC przy użyciu bezpiecznego połączenia.
Możesz sprawdzić, czy usługa gRPC platformy ASP.NET Core używa protokołu TLS w dziennikach zapisanych podczas uruchamiania aplikacji. Usługa nasłuchuje w punkcie końcowym 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 platformy .NET Core musi używać https
w adresie serwera, aby wykonywać wywołania z zabezpieczonym połączeniem:
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
Wszystkie implementacje klienta gRPC obsługują protokół TLS. Klienci gRPC z innych języków zwykle wymagają kanału skonfigurowanego za pomocą SslCredentials
polecenia . SslCredentials
Określa certyfikat, którego będzie używać klient, i musi być używany zamiast niezabezpieczonych poświadczeń. Przykłady konfigurowania różnych implementacji klienta gRPC do używania protokołu TLS można znaleźć w temacie gRPC Authentication (Uwierzytelnianie gRPC).
Wywoływanie usługi gRPC z niezaufanym/nieprawidłowym certyfikatem
Klient gRPC platformy .NET wymaga, aby usługa miała zaufany certyfikat. Podczas wywoływania usługi gRPC bez zaufanego certyfikatu jest zwracany następujący komunikat o błędzie:
Nieobsługiwany wyjątek. System.Net.Http.HttpRequestException: Nie można ustanowić połączenia SSL, zobacz wyjątek wewnętrzny. >--- System.Security.Authentication.AuthenticationException: Certyfikat zdalny jest nieprawidłowy zgodnie z procedurą weryfikacji.
Ten błąd może wystąpić, jeśli testujesz aplikację lokalnie, a certyfikat dewelopera ASP.NET Core HTTPS nie jest zaufany. Aby uzyskać instrukcje dotyczące rozwiązania tego problemu, zobacz Ufaj certyfikatowi programistycznemu https platformy ASP.NET Core w systemach Windows i macOS.
Jeśli wywołujesz usługę gRPC na innym komputerze i nie możesz ufać certyfikatowi, można skonfigurować klienta gRPC tak, aby zignorował nieprawidłowy certyfikat. Poniższy kod używa HttpClientHandler.ServerCertificateCustomValidationCallback metody do zezwalania na wywołania bez zaufanego certyfikatu:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greeter.GreeterClient(channel);
Fabryka klienta gRPC umożliwia wywołania bez zaufanego certyfikatu. ConfigurePrimaryHttpMessageHandler Użyj metody rozszerzenia, aby skonfigurować program obsługi na kliencie:
var services = new ServiceCollection();
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
return handler;
});
Ostrzeżenie
Niezaufane certyfikaty powinny być używane tylko podczas tworzenia aplikacji. Aplikacje produkcyjne powinny zawsze używać prawidłowych certyfikatów.
Wywoływanie niezabezpieczonych usług gRPC za pomocą klienta platformy .NET Core
Klient gRPC platformy .NET może wywoływać niezabezpieczone usługi gRPC, określając http
adres serwera. Na przykład GrpcChannel.ForAddress("http://localhost:5000")
.
Istnieją pewne dodatkowe wymagania dotyczące wywoływania niezabezpieczonych usług gRPC w zależności od wersji platformy .NET używanej przez aplikację:
- Program .NET 5 lub nowszy wymaga klienta Grpc.Net.Client w wersji 2.32.0 lub nowszej.
- Program .NET Core 3.x wymaga dodatkowej konfiguracji. Aplikacja musi ustawić
System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
przełącznik natrue
. Aby uzyskać więcej informacji, zobacz Asp.Net Core 3.x: Wywoływanie niezabezpieczonych usług gRPC przy użyciu klienta platformy .NET:
Ważne
Niezabezpieczone usługi gRPC muszą być hostowane na porcie tylko http/2. Aby uzyskać więcej informacji, zobacz ASP.NET core negocjacji protokołu.
Nie można uruchomić aplikacji gRPC platformy ASP.NET Core w systemie macOS
Kestrel nie obsługuje protokołu HTTP/2 z protokołem TLS w systemie macOS przed platformą .NET 8. Szablon ASP.NET Core gRPC i przykłady domyślnie używają protokołu TLS. Podczas próby uruchomienia serwera gRPC zostanie wyświetlony następujący komunikat o błędzie:
Nie można powiązać z https://localhost:5001 interfejsem sprzężenia zwrotnego protokołu IPv4: "Protokół HTTP/2 za pośrednictwem protokołu TLS nie jest obsługiwany w systemie macOS z powodu braku obsługi alpn".
Aby obejść ten problem na platformie .NET 7 i starszych wersjach, skonfiguruj Kestrel i klienta gRPC do używania protokołu HTTP/2 bez protokołu TLS. Należy to zrobić tylko podczas opracowywania. Nieużywane protokoły TLS spowodują wysyłanie komunikatów gRPC bez szyfrowania. Aby uzyskać więcej informacji, zobacz Asp.Net Core 7.0: Nie można uruchomić aplikacji gRPC platformy ASP.NET Core w systemie macOS.
Zasoby języka C# gRPC nie są kodami wygenerowanymi na podstawie .proto
plików
Generowanie kodu gRPC konkretnych klientów i klas bazowych usługi wymaga odwoływania się do plików protobuf i narzędzi z projektu. Musisz uwzględnić następujące elementy:
.proto
pliki, których chcesz użyć w<Protobuf>
grupie elementów. Zaimportowane.proto
pliki muszą odwoływać się do projektu.- Odwołanie do pakietu narzędzi gRPC Grpc.Tools.
Aby uzyskać więcej informacji na temat generowania zasobów gRPC C#, zobacz usługi gRPC w języku C#.
Aplikacja internetowa ASP.NET Core hostująca usługi gRPC wymaga tylko wygenerowanej klasy bazowej usługi:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
Aplikacja kliencka gRPC wykonująca wywołania gRPC wymaga tylko wygenerowanego konkretnego klienta:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>
Projekty WPF nie mogą wygenerować zasobów gRPC C# z .proto
plików
Projekty WPF mają znany problem uniemożliwiający poprawne działanie generowania kodu gRPC. Wszystkie typy gRPC wygenerowane w projekcie WPF przez odwołanie Grpc.Tools
i .proto
pliki będą tworzyć błędy kompilacji w przypadku użycia:
błąd CS0246: Nie można odnaleźć nazwy typu lub przestrzeni nazw "MyGrpcServices" (czy brakuje dyrektywy using lub odwołania do zestawu?)
Ten problem można obejść, wykonując następujące czynności:
- Utwórz nowy projekt biblioteki klas platformy .NET Core.
- W nowym projekcie dodaj odwołania, aby włączyć generowanie kodu w języku C# z
.proto
plików:- Dodaj następujące odwołania do pakietu:
- Dodaj pliki
.proto
do grupy elementów<Protobuf>
.
- W aplikacji WPF dodaj odwołanie do nowego projektu.
Aplikacja WPF może używać typów wygenerowanych przez gRPC z nowego projektu biblioteki klas.
Wywoływanie usług gRPC hostowanych w podkatalogu
Ostrzeżenie
Wiele narzędzi gRPC innych firm nie obsługuje usług hostowanych w podkatalogach. Rozważ znalezienie sposobu hostowania gRPC jako katalogu głównego.
Składnik ścieżki adresu kanału gRPC jest ignorowany podczas wykonywania wywołań gRPC. Na przykład GrpcChannel.ForAddress("https://localhost:5001/ignored_path")
nie będzie używany ignored_path
podczas routingu wywołań gRPC dla usługi.
Ścieżka adresu jest ignorowana, ponieważ gRPC ma ustandaryzowaną, preskrypcyjną strukturę adresów. Adres gRPC łączy nazwy pakietu, usługi i metody: https://localhost:5001/PackageName.ServiceName/MethodName
.
Istnieją pewne scenariusze, w których aplikacja musi zawierać ścieżkę z wywołaniami gRPC. Na przykład gdy aplikacja gRPC platformy ASP.NET Core jest hostowana w katalogu usług IIS, a katalog musi zostać uwzględniony w żądaniu. Gdy ścieżka jest wymagana, można ją dodać do wywołania gRPC przy użyciu niestandardowego SubdirectoryHandler
określonego poniżej:
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 old = request.RequestUri;
var url = $"{old.Scheme}://{old.Host}:{old.Port}";
url += $"{_subdirectory}{request.RequestUri.AbsolutePath}";
request.RequestUri = new Uri(url, UriKind.Absolute);
return base.SendAsync(request, cancellationToken);
}
}
SubdirectoryHandler
jest używany podczas tworzenia kanału gRPC.
var handler = new SubdirectoryHandler(new HttpClientHandler(), "/MyApp");
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = handler });
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Powyższy kod ma następujące działanie:
- Tworzy obiekt
SubdirectoryHandler
ze ścieżką/MyApp
. - Konfiguruje kanał do użycia .
SubdirectoryHandler
- Wywołuje usługę gRPC za pomocą polecenia
SayHelloAsync
. Wywołanie gRPC jest wysyłane do .https://localhost:5001/MyApp/greet.Greeter/SayHello
Alternatywnie fabrykę klienta można skonfigurować SubdirectoryHandler
przy użyciu polecenia AddHttpMessageHandler.
Konfigurowanie klienta gRPC do używania protokołu HTTP/3
Klient gRPC platformy .NET obsługuje protokół HTTP/3 z platformą .NET 6 lub nowszą wersją. Jeśli serwer wysyła alt-svc
nagłówek odpowiedzi do klienta, który wskazuje, że serwer obsługuje protokół HTTP/3, klient automatycznie uaktualni połączenie z protokołem HTTP/3. Aby uzyskać więcej informacji, zobacz Use HTTP/3 with the ASP.NET Core web server (Używanie protokołu HTTP/3 z serwerem internetowym ASP.NET CoreKestrel).
Element DelegatingHandler może służyć do wymuszenia użycia protokołu HTTP/3 przez klienta gRPC. Wymuszanie protokołu HTTP/3 pozwala uniknąć narzutów związanych z uaktualnianiem żądania. Wymuś http/3 z kodem podobnym do następującego:
public class Http3Handler : DelegatingHandler
{
public Http3Handler() { }
public Http3Handler(HttpMessageHandler innerHandler) : base(innerHandler) { }
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Version = HttpVersion.Version30;
request.VersionPolicy = HttpVersionPolicy.RequestVersionExact;
return base.SendAsync(request, cancellationToken);
}
}
Http3Handler
jest używany podczas tworzenia kanału gRPC. Poniższy kod tworzy kanał skonfigurowany do używania programu Http3Handler
.
var handler = new Http3Handler(new HttpClientHandler());
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = handler });
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Alternatywnie fabrykę klienta można skonfigurować Http3Handler
przy użyciu polecenia AddHttpMessageHandler.
Tworzenie gRPC w systemie Alpine Linux
Pakiet Grpc.Tools
generuje typy .NET z .proto
plików przy użyciu pakietu natywnego pliku binarnego o nazwie protoc
. Dodatkowe kroki są wymagane do tworzenia aplikacji gRPC na platformach, które nie są obsługiwane przez natywne pliki binarne w systemie Grpc.Tools
, takich jak Alpine Linux.
Generowanie kodu z wyprzedzeniem
Jednym z rozwiązań jest wygenerowanie kodu z wyprzedzeniem.
- Przenieś
.proto
pliki iGrpc.Tools
odwołanie do pakietu do nowego projektu. - Opublikuj projekt jako pakiet NuGet i przekaż go do źródła danych NuGet.
- Zaktualizuj aplikację, aby odwoływać się do pakietu NuGet.
W poprzednich krokach aplikacja nie wymaga Grpc.Tools
już kompilowania, ponieważ kod jest generowany z wyprzedzeniem.
Dostosowywanie Grpc.Tools
natywnych plików binarnych
Grpc.Tools
obsługuje używanie niestandardowych natywnych plików binarnych. Ta funkcja umożliwia uruchamianie narzędzi gRPC w środowiskach, w których są dołączone pliki binarne natywne, nie są obsługiwane.
Kompilowanie lub uzyskiwanie i grpc_csharp_plugin
natywnych protoc
plików binarnych oraz konfigurowanie Grpc.Tools
ich używania. Skonfiguruj natywne pliki binarne, ustawiając następujące zmienne środowiskowe:
PROTOBUF_PROTOC
- Pełna ścieżka do kompilatora protokołuGRPC_PROTOC_PLUGIN
- Pełna ścieżka do grpc_csharp_plugin
W przypadku systemu Alpine Linux dostępne są pakiety udostępnione przez społeczność dla kompilatora protokołu i wtyczek gRPC w witrynie https://pkgs.alpinelinux.org/.
# Build or install the binaries for your architecture.
# For Alpine Linux, the grpc-plugins package can be used.
# See https://pkgs.alpinelinux.org/package/edge/community/x86_64/grpc-plugins
apk add grpc-plugins # Alpine Linux specific package installer
# Set environment variables for the built/installed protoc
# and grpc_csharp_plugin binaries
export PROTOBUF_PROTOC=/usr/bin/protoc
export GRPC_PROTOC_PLUGIN=/usr/bin/grpc_csharp_plugin
# When dotnet build runs, the Grpc.Tools NuGet package
# uses the binaries pointed to by the environment variables.
dotnet build
Aby uzyskać więcej informacji na temat używania Grpc.Tools
z nieobsługiwanymi architekturami, zobacz dokumentację integracji kompilacji gRPC.
Limit czasu wywołania gRPC z HttpClient.Timeout
HttpClient jest domyślnie skonfigurowany z limitem czasu 100 sekund. GrpcChannel
Jeśli element jest skonfigurowany do używania , długotrwałe wywołania przesyłania strumieniowego HttpClient
gRPC zostaną anulowane, jeśli nie zostaną ukończone w limicie czasu.
System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
Istnieje kilka sposobów naprawienia tego błędu. Pierwszą z nich jest skonfigurowanie HttpClient.Timeout do większej wartości. Timeout.InfiniteTimeSpan wyłącza limit czasu:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var httpClient = new HttpClient(handler) { Timeout = Timeout.InfiniteTimeSpan };
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpClient = httpClient });
var client = new Greeter.GreeterClient(channel);
Możesz też unikać tworzenia i ustawiania HttpClient
GrpcChannel.HttpHandler
:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greeter.GreeterClient(channel);
W tym dokumencie omówiono często występujące problemy podczas tworzenia aplikacji gRPC na platformie .NET.
Niezgodność między konfiguracją protokołu SSL/TLS klienta i usługi
Szablon gRPC i przykłady używają protokołu Transport Layer Security (TLS) do zabezpieczania usług gRPC domyślnie. Klienci gRPC muszą pomyślnie wywoływać zabezpieczone usługi gRPC przy użyciu bezpiecznego połączenia.
Możesz sprawdzić, czy usługa gRPC platformy ASP.NET Core używa protokołu TLS w dziennikach zapisanych podczas uruchamiania aplikacji. Usługa nasłuchuje w punkcie końcowym 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 platformy .NET Core musi używać https
w adresie serwera, aby wykonywać wywołania z zabezpieczonym połączeniem:
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);
}
Wszystkie implementacje klienta gRPC obsługują protokół TLS. Klienci gRPC z innych języków zwykle wymagają kanału skonfigurowanego za pomocą SslCredentials
polecenia . SslCredentials
Określa certyfikat, którego będzie używać klient, i musi być używany zamiast niezabezpieczonych poświadczeń. Przykłady konfigurowania różnych implementacji klienta gRPC do używania protokołu TLS można znaleźć w temacie gRPC Authentication (Uwierzytelnianie gRPC).
Wywoływanie usługi gRPC z niezaufanym/nieprawidłowym certyfikatem
Klient gRPC platformy .NET wymaga, aby usługa miała zaufany certyfikat. Podczas wywoływania usługi gRPC bez zaufanego certyfikatu jest zwracany następujący komunikat o błędzie:
Nieobsługiwany wyjątek. System.Net.Http.HttpRequestException: Nie można ustanowić połączenia SSL, zobacz wyjątek wewnętrzny. >--- System.Security.Authentication.AuthenticationException: Certyfikat zdalny jest nieprawidłowy zgodnie z procedurą weryfikacji.
Ten błąd może wystąpić, jeśli testujesz aplikację lokalnie, a certyfikat dewelopera ASP.NET Core HTTPS nie jest zaufany. Aby uzyskać instrukcje dotyczące rozwiązania tego problemu, zobacz Ufaj certyfikatowi programistycznemu https platformy ASP.NET Core w systemach Windows i macOS.
Jeśli wywołujesz usługę gRPC na innym komputerze i nie możesz ufać certyfikatowi, można skonfigurować klienta gRPC tak, aby zignorował nieprawidłowy certyfikat. Poniższy kod używa HttpClientHandler.ServerCertificateCustomValidationCallback metody do zezwalania na wywołania bez zaufanego certyfikatu:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
Fabryka klienta gRPC umożliwia wywołania bez zaufanego certyfikatu. ConfigurePrimaryHttpMessageHandler Użyj metody rozszerzenia, aby skonfigurować program obsługi na kliencie:
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
return handler;
});
Ostrzeżenie
Niezaufane certyfikaty powinny być używane tylko podczas tworzenia aplikacji. Aplikacje produkcyjne powinny zawsze używać prawidłowych certyfikatów.
Wywoływanie niezabezpieczonych usług gRPC za pomocą klienta platformy .NET Core
Klient gRPC platformy .NET może wywoływać niezabezpieczone usługi gRPC, określając http
adres serwera. Na przykład GrpcChannel.ForAddress("http://localhost:5000")
.
Istnieją pewne dodatkowe wymagania dotyczące wywoływania niezabezpieczonych usług gRPC w zależności od wersji platformy .NET używanej przez aplikację:
Program .NET 5 lub nowszy wymaga klienta Grpc.Net.Client w wersji 2.32.0 lub nowszej.
Program .NET Core 3.x wymaga dodatkowej konfiguracji. Aplikacja musi ustawić
System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
przełącznik 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);
Przełącznik System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
jest wymagany tylko dla platformy .NET Core 3.x. Nic nie robi na platformie .NET 5 i nie jest wymagane.
Ważne
Niezabezpieczone usługi gRPC muszą być hostowane na porcie tylko http/2. Aby uzyskać więcej informacji, zobacz ASP.NET core negocjacji protokołu.
Nie można uruchomić aplikacji gRPC platformy ASP.NET Core w systemie macOS
Kestrel nie obsługuje protokołu HTTP/2 z protokołem TLS w systemie macOS przed platformą .NET 8. Szablon ASP.NET Core gRPC i przykłady domyślnie używają protokołu TLS. Podczas próby uruchomienia serwera gRPC zostanie wyświetlony następujący komunikat o błędzie:
Nie można powiązać z https://localhost:5001 interfejsem sprzężenia zwrotnego protokołu IPv4: "Protokół HTTP/2 za pośrednictwem protokołu TLS nie jest obsługiwany w systemie macOS z powodu braku obsługi alpn".
Aby obejść ten problem na platformie .NET 7 i starszych wersjach, skonfiguruj Kestrel i klienta gRPC do używania protokołu HTTP/2 bez protokołu TLS. Należy to zrobić tylko podczas opracowywania. Nieużywane protokoły TLS spowodują wysyłanie komunikatów gRPC bez szyfrowania.
Kestrel musi skonfigurować punkt końcowy HTTP/2 bez protokołu TLS w programie Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
// Setup a HTTP/2 endpoint without TLS.
options.ListenLocalhost(<5287>, o => o.Protocols =
HttpProtocols.Http2);
});
- W poprzednim kodzie zastąp
HTTP
numer portu localhost numerem5287
portu (nieHTTPS
) określonym wProperties/launchSettings.json
projekcie usługi gRPC.
Po skonfigurowaniu punktu końcowego HTTP/2 bez protokołu TLS punkt końcowy ListenOptions.Protocols musi mieć wartość HttpProtocols.Http2
. HttpProtocols.Http1AndHttp2
Nie można użyć, ponieważ protokół TLS jest wymagany do negocjowania protokołu HTTP/2. Bez protokołu TLS wszystkie połączenia z punktem końcowym domyślnie do protokołu HTTP/1.1 i wywołania gRPC kończą się niepowodzeniem.
Klient gRPC musi być również skonfigurowany tak, aby nie używał protokołu TLS. Aby uzyskać więcej informacji, zobacz Wywoływanie niezabezpieczonych usług gRPC za pomocą klienta platformy .NET Core.
Ostrzeżenie
Protokół HTTP/2 bez protokołu TLS powinien być używany tylko podczas tworzenia aplikacji. Aplikacje produkcyjne powinny zawsze używać zabezpieczeń transportu. Aby uzyskać więcej informacji, zobacz Zagadnienia dotyczące zabezpieczeń w gRPC dla ASP.NET Core.
Zasoby języka C# gRPC nie są kodami wygenerowanymi na podstawie .proto
plików
Generowanie kodu gRPC konkretnych klientów i klas bazowych usługi wymaga odwoływania się do plików protobuf i narzędzi z projektu. Musisz uwzględnić następujące elementy:
.proto
pliki, których chcesz użyć w<Protobuf>
grupie elementów. Zaimportowane.proto
pliki muszą odwoływać się do projektu.- Odwołanie do pakietu narzędzi gRPC Grpc.Tools.
Aby uzyskać więcej informacji na temat generowania zasobów gRPC C#, zobacz usługi gRPC w języku C#.
Aplikacja internetowa ASP.NET Core hostująca usługi gRPC wymaga tylko wygenerowanej klasy bazowej usługi:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
Aplikacja kliencka gRPC wykonująca wywołania gRPC wymaga tylko wygenerowanego konkretnego klienta:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>
Projekty WPF nie mogą wygenerować zasobów gRPC C# z .proto
plików
Projekty WPF mają znany problem uniemożliwiający poprawne działanie generowania kodu gRPC. Wszystkie typy gRPC wygenerowane w projekcie WPF przez odwołanie Grpc.Tools
i .proto
pliki będą tworzyć błędy kompilacji w przypadku użycia:
błąd CS0246: Nie można odnaleźć nazwy typu lub przestrzeni nazw "MyGrpcServices" (czy brakuje dyrektywy using lub odwołania do zestawu?)
Ten problem można obejść, wykonując następujące czynności:
- Utwórz nowy projekt biblioteki klas platformy .NET Core.
- W nowym projekcie dodaj odwołania, aby włączyć generowanie kodu w języku C# z
.proto
plików:- Dodaj następujące odwołania do pakietu:
- Dodaj pliki
.proto
do grupy elementów<Protobuf>
.
- W aplikacji WPF dodaj odwołanie do nowego projektu.
Aplikacja WPF może używać typów wygenerowanych przez gRPC z nowego projektu biblioteki klas.
Wywoływanie usług gRPC hostowanych w podkatalogu
Ostrzeżenie
Wiele narzędzi gRPC innych firm nie obsługuje usług hostowanych w podkatalogach. Rozważ znalezienie sposobu hostowania gRPC jako katalogu głównego.
Składnik ścieżki adresu kanału gRPC jest ignorowany podczas wykonywania wywołań gRPC. Na przykład GrpcChannel.ForAddress("https://localhost:5001/ignored_path")
nie będzie używany ignored_path
podczas routingu wywołań gRPC dla usługi.
Ścieżka adresu jest ignorowana, ponieważ gRPC ma ustandaryzowaną, preskrypcyjną strukturę adresów. Adres gRPC łączy nazwy pakietu, usługi i metody: https://localhost:5001/PackageName.ServiceName/MethodName
.
Istnieją pewne scenariusze, w których aplikacja musi zawierać ścieżkę z wywołaniami gRPC. Na przykład gdy aplikacja gRPC platformy ASP.NET Core jest hostowana w katalogu usług IIS, a katalog musi zostać uwzględniony w żądaniu. Gdy ścieżka jest wymagana, można ją dodać do wywołania gRPC przy użyciu niestandardowego SubdirectoryHandler
określonego poniżej:
/// <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 old = request.RequestUri;
var url = $"{old.Scheme}://{old.Host}:{old.Port}";
url += $"{_subdirectory}{request.RequestUri.AbsolutePath}";
request.RequestUri = new Uri(url, UriKind.Absolute);
return base.SendAsync(request, cancellationToken);
}
}
SubdirectoryHandler
jest używany podczas tworzenia kanału 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" });
Powyższy kod ma następujące działanie:
- Tworzy obiekt
SubdirectoryHandler
ze ścieżką/MyApp
. - Konfiguruje kanał do użycia .
SubdirectoryHandler
- Wywołuje usługę gRPC za pomocą polecenia
SayHelloAsync
. Wywołanie gRPC jest wysyłane do .https://localhost:5001/MyApp/greet.Greeter/SayHello
Alternatywnie fabrykę klienta można skonfigurować SubdirectoryHandler
przy użyciu polecenia AddHttpMessageHandler.
Konfigurowanie klienta gRPC do używania protokołu HTTP/3
Klient gRPC platformy .NET obsługuje protokół HTTP/3 z platformą .NET 6 lub nowszą wersją. Jeśli serwer wysyła alt-svc
nagłówek odpowiedzi do klienta, który wskazuje, że serwer obsługuje protokół HTTP/3, klient automatycznie uaktualni połączenie z protokołem HTTP/3. Aby uzyskać informacje na temat włączania protokołu HTTP/3 na serwerze, zobacz Używanie protokołu HTTP/3 z serwerem internetowym ASP.NET CoreKestrel.
Obsługa protokołu HTTP/3 na platformie .NET 8 jest domyślnie włączona. Obsługa protokołu HTTP/3 na platformie .NET 6 i .NET 7 musi być włączona za pośrednictwem flagi konfiguracji w pliku projektu:
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Net.SocketsHttpHandler.Http3Support" Value="true" />
</ItemGroup>
System.Net.SocketsHttpHandler.Http3Support
można również ustawić przy użyciu elementu AppContext.SetSwitch.
Element DelegatingHandler może służyć do wymuszenia użycia protokołu HTTP/3 przez klienta gRPC. Wymuszanie protokołu HTTP/3 pozwala uniknąć narzutów związanych z uaktualnianiem żądania. Wymuś http/3 z kodem podobnym do następującego:
/// <summary>
/// A delegating handler that changes the request HTTP version to HTTP/3.
/// </summary>
public class Http3Handler : DelegatingHandler
{
public Http3Handler() { }
public Http3Handler(HttpMessageHandler innerHandler) : base(innerHandler) { }
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Version = HttpVersion.Version30;
request.VersionPolicy = HttpVersionPolicy.RequestVersionExact;
return base.SendAsync(request, cancellationToken);
}
}
Http3Handler
jest używany podczas tworzenia kanału gRPC. Poniższy kod tworzy kanał skonfigurowany do używania programu Http3Handler
.
var handler = new Http3Handler(new HttpClientHandler());
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" });
Alternatywnie fabrykę klienta można skonfigurować Http3Handler
przy użyciu polecenia AddHttpMessageHandler.
Tworzenie gRPC w systemie Alpine Linux
Pakiet Grpc.Tools
generuje typy .NET z .proto
plików przy użyciu pakietu natywnego pliku binarnego o nazwie protoc
. Dodatkowe kroki są wymagane do tworzenia aplikacji gRPC na platformach, które nie są obsługiwane przez natywne pliki binarne w systemie Grpc.Tools
, takich jak Alpine Linux.
Generowanie kodu z wyprzedzeniem
Jednym z rozwiązań jest wygenerowanie kodu z wyprzedzeniem.
- Przenieś
.proto
pliki iGrpc.Tools
odwołanie do pakietu do nowego projektu. - Opublikuj projekt jako pakiet NuGet i przekaż go do źródła danych NuGet.
- Zaktualizuj aplikację, aby odwoływać się do pakietu NuGet.
W poprzednich krokach aplikacja nie wymaga Grpc.Tools
już kompilowania, ponieważ kod jest generowany z wyprzedzeniem.
Dostosowywanie Grpc.Tools
natywnych plików binarnych
Grpc.Tools
obsługuje używanie niestandardowych natywnych plików binarnych. Ta funkcja umożliwia uruchamianie narzędzi gRPC w środowiskach, w których są dołączone pliki binarne natywne, nie są obsługiwane.
Kompilowanie lub uzyskiwanie i grpc_csharp_plugin
natywnych protoc
plików binarnych oraz konfigurowanie Grpc.Tools
ich używania. Skonfiguruj natywne pliki binarne, ustawiając następujące zmienne środowiskowe:
PROTOBUF_PROTOC
- Pełna ścieżka do kompilatora protokołuGRPC_PROTOC_PLUGIN
- Pełna ścieżka do grpc_csharp_plugin
W przypadku systemu Alpine Linux dostępne są pakiety udostępnione przez społeczność dla kompilatora protokołu i wtyczek gRPC w witrynie https://pkgs.alpinelinux.org/.
# Build or install the binaries for your architecture.
# For Alpine Linux, the grpc-plugins package can be used.
# See https://pkgs.alpinelinux.org/package/edge/community/x86_64/grpc-plugins
apk add grpc-plugins # Alpine Linux specific package installer
# Set environment variables for the built/installed protoc
# and grpc_csharp_plugin binaries
export PROTOBUF_PROTOC=/usr/bin/protoc
export GRPC_PROTOC_PLUGIN=/usr/bin/grpc_csharp_plugin
# When dotnet build runs, the Grpc.Tools NuGet package
# uses the binaries pointed to by the environment variables.
dotnet build
Aby uzyskać więcej informacji na temat używania Grpc.Tools
z nieobsługiwanymi architekturami, zobacz dokumentację integracji kompilacji gRPC.
Limit czasu wywołania gRPC z HttpClient.Timeout
HttpClient jest domyślnie skonfigurowany z limitem czasu 100 sekund. GrpcChannel
Jeśli element jest skonfigurowany do używania , długotrwałe wywołania przesyłania strumieniowego HttpClient
gRPC zostaną anulowane, jeśli nie zostaną ukończone w limicie czasu.
System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
Istnieje kilka sposobów naprawienia tego błędu. Pierwszą z nich jest skonfigurowanie HttpClient.Timeout do większej wartości. Timeout.InfiniteTimeSpan wyłącza limit czasu:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var httpClient = new HttpClient(handler) { Timeout = Timeout.InfiniteTimeSpan };
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpClient = httpClient });
var client = new Greeter.GreeterClient(channel);
Możesz też unikać tworzenia i ustawiania HttpClient
GrpcChannel.HttpHandler
:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greeter.GreeterClient(channel);
W tym dokumencie omówiono często występujące problemy podczas tworzenia aplikacji gRPC na platformie .NET.
Niezgodność między konfiguracją protokołu SSL/TLS klienta i usługi
Szablon gRPC i przykłady używają protokołu Transport Layer Security (TLS) do zabezpieczania usług gRPC domyślnie. Klienci gRPC muszą pomyślnie wywoływać zabezpieczone usługi gRPC przy użyciu bezpiecznego połączenia.
Możesz sprawdzić, czy usługa gRPC platformy ASP.NET Core używa protokołu TLS w dziennikach zapisanych podczas uruchamiania aplikacji. Usługa nasłuchuje w punkcie końcowym 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 platformy .NET Core musi używać https
w adresie serwera, aby wykonywać wywołania z zabezpieczonym połączeniem:
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);
}
Wszystkie implementacje klienta gRPC obsługują protokół TLS. Klienci gRPC z innych języków zwykle wymagają kanału skonfigurowanego za pomocą SslCredentials
polecenia . SslCredentials
Określa certyfikat, którego będzie używać klient, i musi być używany zamiast niezabezpieczonych poświadczeń. Przykłady konfigurowania różnych implementacji klienta gRPC do używania protokołu TLS można znaleźć w temacie gRPC Authentication (Uwierzytelnianie gRPC).
Wywoływanie usługi gRPC z niezaufanym/nieprawidłowym certyfikatem
Klient gRPC platformy .NET wymaga, aby usługa miała zaufany certyfikat. Podczas wywoływania usługi gRPC bez zaufanego certyfikatu jest zwracany następujący komunikat o błędzie:
Nieobsługiwany wyjątek. System.Net.Http.HttpRequestException: Nie można ustanowić połączenia SSL, zobacz wyjątek wewnętrzny. >--- System.Security.Authentication.AuthenticationException: Certyfikat zdalny jest nieprawidłowy zgodnie z procedurą weryfikacji.
Ten błąd może wystąpić, jeśli testujesz aplikację lokalnie, a certyfikat dewelopera ASP.NET Core HTTPS nie jest zaufany. Aby uzyskać instrukcje dotyczące rozwiązania tego problemu, zobacz Ufaj certyfikatowi programistycznemu https platformy ASP.NET Core w systemach Windows i macOS.
Jeśli wywołujesz usługę gRPC na innym komputerze i nie możesz ufać certyfikatowi, można skonfigurować klienta gRPC tak, aby zignorował nieprawidłowy certyfikat. Poniższy kod używa HttpClientHandler.ServerCertificateCustomValidationCallback metody do zezwalania na wywołania bez zaufanego certyfikatu:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
Fabryka klienta gRPC umożliwia wywołania bez zaufanego certyfikatu. ConfigurePrimaryHttpMessageHandler Użyj metody rozszerzenia, aby skonfigurować program obsługi na kliencie:
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
return handler;
});
Ostrzeżenie
Niezaufane certyfikaty powinny być używane tylko podczas tworzenia aplikacji. Aplikacje produkcyjne powinny zawsze używać prawidłowych certyfikatów.
Wywoływanie niezabezpieczonych usług gRPC za pomocą klienta platformy .NET Core
Klient gRPC platformy .NET może wywoływać niezabezpieczone usługi gRPC, określając http
adres serwera. Na przykład GrpcChannel.ForAddress("http://localhost:5000")
.
Istnieją pewne dodatkowe wymagania dotyczące wywoływania niezabezpieczonych usług gRPC w zależności od wersji platformy .NET używanej przez aplikację:
Program .NET 5 lub nowszy wymaga klienta Grpc.Net.Client w wersji 2.32.0 lub nowszej.
Program .NET Core 3.x wymaga dodatkowej konfiguracji. Aplikacja musi ustawić
System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
przełącznik 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);
Przełącznik System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
jest wymagany tylko dla platformy .NET Core 3.x. Nic nie robi na platformie .NET 5 i nie jest wymagane.
Ważne
Niezabezpieczone usługi gRPC muszą być hostowane na porcie tylko http/2. Aby uzyskać więcej informacji, zobacz ASP.NET core negocjacji protokołu.
Nie można uruchomić aplikacji gRPC platformy ASP.NET Core w systemie macOS
Kestrel nie obsługuje protokołu HTTP/2 z protokołem TLS w systemie macOS przed platformą .NET 8. Szablon ASP.NET Core gRPC i przykłady domyślnie używają protokołu TLS. Podczas próby uruchomienia serwera gRPC zostanie wyświetlony następujący komunikat o błędzie:
Nie można powiązać z https://localhost:5001 interfejsem sprzężenia zwrotnego protokołu IPv4: "Protokół HTTP/2 za pośrednictwem protokołu TLS nie jest obsługiwany w systemie macOS z powodu braku obsługi alpn".
Aby obejść ten problem na platformie .NET 7 i starszych wersjach, skonfiguruj Kestrel i klienta gRPC do używania protokołu HTTP/2 bez protokołu TLS. Należy to zrobić tylko podczas opracowywania. Nieużywane protokoły TLS spowodują wysyłanie komunikatów gRPC bez szyfrowania.
Kestrel musi skonfigurować punkt końcowy HTTP/2 bez protokołu TLS w programie Program.cs
:
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>();
});
Po skonfigurowaniu punktu końcowego HTTP/2 bez protokołu TLS punkt końcowy ListenOptions.Protocols musi mieć wartość HttpProtocols.Http2
. HttpProtocols.Http1AndHttp2
Nie można użyć, ponieważ protokół TLS jest wymagany do negocjowania protokołu HTTP/2. Bez protokołu TLS wszystkie połączenia z punktem końcowym domyślnie do protokołu HTTP/1.1 i wywołania gRPC kończą się niepowodzeniem.
Klient gRPC musi być również skonfigurowany tak, aby nie używał protokołu TLS. Aby uzyskać więcej informacji, zobacz Wywoływanie niezabezpieczonych usług gRPC za pomocą klienta platformy .NET Core.
Ostrzeżenie
Protokół HTTP/2 bez protokołu TLS powinien być używany tylko podczas tworzenia aplikacji. Aplikacje produkcyjne powinny zawsze używać zabezpieczeń transportu. Aby uzyskać więcej informacji, zobacz Zagadnienia dotyczące zabezpieczeń w gRPC dla ASP.NET Core.
Zasoby języka C# gRPC nie są kodami wygenerowanymi na podstawie .proto
plików
Generowanie kodu gRPC konkretnych klientów i klas bazowych usługi wymaga odwoływania się do plików protobuf i narzędzi z projektu. Musisz uwzględnić następujące elementy:
.proto
pliki, których chcesz użyć w<Protobuf>
grupie elementów. Zaimportowane.proto
pliki muszą odwoływać się do projektu.- Odwołanie do pakietu narzędzi gRPC Grpc.Tools.
Aby uzyskać więcej informacji na temat generowania zasobów gRPC C#, zobacz usługi gRPC w języku C#.
Aplikacja internetowa ASP.NET Core hostująca usługi gRPC wymaga tylko wygenerowanej klasy bazowej usługi:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
Aplikacja kliencka gRPC wykonująca wywołania gRPC wymaga tylko wygenerowanego konkretnego klienta:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>
Projekty WPF nie mogą wygenerować zasobów gRPC C# z .proto
plików
Projekty WPF mają znany problem uniemożliwiający poprawne działanie generowania kodu gRPC. Wszystkie typy gRPC wygenerowane w projekcie WPF przez odwołanie Grpc.Tools
i .proto
pliki będą tworzyć błędy kompilacji w przypadku użycia:
błąd CS0246: Nie można odnaleźć nazwy typu lub przestrzeni nazw "MyGrpcServices" (czy brakuje dyrektywy using lub odwołania do zestawu?)
Ten problem można obejść, wykonując następujące czynności:
- Utwórz nowy projekt biblioteki klas platformy .NET Core.
- W nowym projekcie dodaj odwołania, aby włączyć generowanie kodu w języku C# z
.proto
plików:- Dodaj następujące odwołania do pakietu:
- Dodaj pliki
.proto
do grupy elementów<Protobuf>
.
- W aplikacji WPF dodaj odwołanie do nowego projektu.
Aplikacja WPF może używać typów wygenerowanych przez gRPC z nowego projektu biblioteki klas.
Wywoływanie usług gRPC hostowanych w podkatalogu
Ostrzeżenie
Wiele narzędzi gRPC innych firm nie obsługuje usług hostowanych w podkatalogach. Rozważ znalezienie sposobu hostowania gRPC jako katalogu głównego.
Składnik ścieżki adresu kanału gRPC jest ignorowany podczas wykonywania wywołań gRPC. Na przykład GrpcChannel.ForAddress("https://localhost:5001/ignored_path")
nie będzie używany ignored_path
podczas routingu wywołań gRPC dla usługi.
Ścieżka adresu jest ignorowana, ponieważ gRPC ma ustandaryzowaną, preskrypcyjną strukturę adresów. Adres gRPC łączy nazwy pakietu, usługi i metody: https://localhost:5001/PackageName.ServiceName/MethodName
.
Istnieją pewne scenariusze, w których aplikacja musi zawierać ścieżkę z wywołaniami gRPC. Na przykład gdy aplikacja gRPC platformy ASP.NET Core jest hostowana w katalogu usług IIS, a katalog musi zostać uwzględniony w żądaniu. Gdy ścieżka jest wymagana, można ją dodać do wywołania gRPC przy użyciu niestandardowego SubdirectoryHandler
określonego poniżej:
/// <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 old = request.RequestUri;
var url = $"{old.Scheme}://{old.Host}:{old.Port}";
url += $"{_subdirectory}{request.RequestUri.AbsolutePath}";
request.RequestUri = new Uri(url, UriKind.Absolute);
return base.SendAsync(request, cancellationToken);
}
}
SubdirectoryHandler
jest używany podczas tworzenia kanału 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" });
Powyższy kod ma następujące działanie:
- Tworzy obiekt
SubdirectoryHandler
ze ścieżką/MyApp
. - Konfiguruje kanał do użycia .
SubdirectoryHandler
- Wywołuje usługę gRPC za pomocą polecenia
SayHelloAsync
. Wywołanie gRPC jest wysyłane do .https://localhost:5001/MyApp/greet.Greeter/SayHello
Alternatywnie fabrykę klienta można skonfigurować SubdirectoryHandler
przy użyciu polecenia AddHttpMessageHandler.
Limit czasu wywołania gRPC z HttpClient.Timeout
HttpClient jest domyślnie skonfigurowany z limitem czasu 100 sekund. GrpcChannel
Jeśli element jest skonfigurowany do używania , długotrwałe wywołania przesyłania strumieniowego HttpClient
gRPC zostaną anulowane, jeśli nie zostaną ukończone w limicie czasu.
System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
Istnieje kilka sposobów naprawienia tego błędu. Pierwszą z nich jest skonfigurowanie HttpClient.Timeout do większej wartości. Timeout.InfiniteTimeSpan wyłącza limit czasu:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var httpClient = new HttpClient(handler) { Timeout = Timeout.InfiniteTimeSpan };
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpClient = httpClient });
var client = new Greeter.GreeterClient(channel);
Możesz też unikać tworzenia i ustawiania HttpClient
GrpcChannel.HttpHandler
:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greeter.GreeterClient(channel);
W tym dokumencie omówiono często występujące problemy podczas tworzenia aplikacji gRPC na platformie .NET.
Niezgodność między konfiguracją protokołu SSL/TLS klienta i usługi
Szablon gRPC i przykłady używają protokołu Transport Layer Security (TLS) do zabezpieczania usług gRPC domyślnie. Klienci gRPC muszą pomyślnie wywoływać zabezpieczone usługi gRPC przy użyciu bezpiecznego połączenia.
Możesz sprawdzić, czy usługa gRPC platformy ASP.NET Core używa protokołu TLS w dziennikach zapisanych podczas uruchamiania aplikacji. Usługa nasłuchuje w punkcie końcowym 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 platformy .NET Core musi używać https
w adresie serwera, aby wykonywać wywołania z zabezpieczonym połączeniem:
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);
}
Wszystkie implementacje klienta gRPC obsługują protokół TLS. Klienci gRPC z innych języków zwykle wymagają kanału skonfigurowanego za pomocą SslCredentials
polecenia . SslCredentials
Określa certyfikat, którego będzie używać klient, i musi być używany zamiast niezabezpieczonych poświadczeń. Przykłady konfigurowania różnych implementacji klienta gRPC do używania protokołu TLS można znaleźć w temacie gRPC Authentication (Uwierzytelnianie gRPC).
Wywoływanie usługi gRPC z niezaufanym/nieprawidłowym certyfikatem
Klient gRPC platformy .NET wymaga, aby usługa miała zaufany certyfikat. Podczas wywoływania usługi gRPC bez zaufanego certyfikatu jest zwracany następujący komunikat o błędzie:
Nieobsługiwany wyjątek. System.Net.Http.HttpRequestException: Nie można ustanowić połączenia SSL, zobacz wyjątek wewnętrzny. >--- System.Security.Authentication.AuthenticationException: Certyfikat zdalny jest nieprawidłowy zgodnie z procedurą weryfikacji.
Ten błąd może wystąpić, jeśli testujesz aplikację lokalnie, a certyfikat dewelopera ASP.NET Core HTTPS nie jest zaufany. Aby uzyskać instrukcje dotyczące rozwiązania tego problemu, zobacz Ufaj certyfikatowi programistycznemu https platformy ASP.NET Core w systemach Windows i macOS.
Jeśli wywołujesz usługę gRPC na innym komputerze i nie możesz ufać certyfikatowi, można skonfigurować klienta gRPC tak, aby zignorował nieprawidłowy certyfikat. Poniższy kod używa HttpClientHandler.ServerCertificateCustomValidationCallback metody do zezwalania na wywołania bez zaufanego certyfikatu:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
Fabryka klienta gRPC umożliwia wywołania bez zaufanego certyfikatu. ConfigurePrimaryHttpMessageHandler Użyj metody rozszerzenia, aby skonfigurować program obsługi na kliencie:
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
return handler;
});
Ostrzeżenie
Niezaufane certyfikaty powinny być używane tylko podczas tworzenia aplikacji. Aplikacje produkcyjne powinny zawsze używać prawidłowych certyfikatów.
Wywoływanie niezabezpieczonych usług gRPC za pomocą klienta platformy .NET Core
Klient gRPC platformy .NET może wywoływać niezabezpieczone usługi gRPC, określając http
adres serwera. Na przykład GrpcChannel.ForAddress("http://localhost:5000")
.
Istnieją pewne dodatkowe wymagania dotyczące wywoływania niezabezpieczonych usług gRPC w zależności od wersji platformy .NET używanej przez aplikację:
Program .NET 5 lub nowszy wymaga klienta Grpc.Net.Client w wersji 2.32.0 lub nowszej.
Program .NET Core 3.x wymaga dodatkowej konfiguracji. Aplikacja musi ustawić
System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
przełącznik 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);
Przełącznik System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
jest wymagany tylko dla platformy .NET Core 3.x. Nic nie robi na platformie .NET 5 i nie jest wymagane.
Ważne
Niezabezpieczone usługi gRPC muszą być hostowane na porcie tylko http/2. Aby uzyskać więcej informacji, zobacz ASP.NET core negocjacji protokołu.
Nie można uruchomić aplikacji gRPC platformy ASP.NET Core w systemie macOS
Kestrel nie obsługuje protokołu HTTP/2 z protokołem TLS w systemie macOS przed platformą .NET 8. Szablon ASP.NET Core gRPC i przykłady domyślnie używają protokołu TLS. Podczas próby uruchomienia serwera gRPC zostanie wyświetlony następujący komunikat o błędzie:
Nie można powiązać z https://localhost:5001 interfejsem sprzężenia zwrotnego protokołu IPv4: "Protokół HTTP/2 za pośrednictwem protokołu TLS nie jest obsługiwany w systemie macOS z powodu braku obsługi alpn".
Aby obejść ten problem na platformie .NET 7 i starszych wersjach, skonfiguruj Kestrel i klienta gRPC do używania protokołu HTTP/2 bez protokołu TLS. Należy to zrobić tylko podczas opracowywania. Nieużywane protokoły TLS spowodują wysyłanie komunikatów gRPC bez szyfrowania.
Kestrel musi skonfigurować punkt końcowy HTTP/2 bez protokołu TLS w programie Program.cs
:
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>();
});
Po skonfigurowaniu punktu końcowego HTTP/2 bez protokołu TLS punkt końcowy ListenOptions.Protocols musi mieć wartość HttpProtocols.Http2
. HttpProtocols.Http1AndHttp2
Nie można użyć, ponieważ protokół TLS jest wymagany do negocjowania protokołu HTTP/2. Bez protokołu TLS wszystkie połączenia z punktem końcowym domyślnie do protokołu HTTP/1.1 i wywołania gRPC kończą się niepowodzeniem.
Klient gRPC musi być również skonfigurowany tak, aby nie używał protokołu TLS. Aby uzyskać więcej informacji, zobacz Wywoływanie niezabezpieczonych usług gRPC za pomocą klienta platformy .NET Core.
Ostrzeżenie
Protokół HTTP/2 bez protokołu TLS powinien być używany tylko podczas tworzenia aplikacji. Aplikacje produkcyjne powinny zawsze używać zabezpieczeń transportu. Aby uzyskać więcej informacji, zobacz Zagadnienia dotyczące zabezpieczeń w gRPC dla ASP.NET Core.
Zasoby języka C# gRPC nie są kodami wygenerowanymi na podstawie .proto
plików
Generowanie kodu gRPC konkretnych klientów i klas bazowych usługi wymaga odwoływania się do plików protobuf i narzędzi z projektu. Musisz uwzględnić następujące elementy:
.proto
pliki, których chcesz użyć w<Protobuf>
grupie elementów. Zaimportowane.proto
pliki muszą odwoływać się do projektu.- Odwołanie do pakietu narzędzi gRPC Grpc.Tools.
Aby uzyskać więcej informacji na temat generowania zasobów gRPC C#, zobacz usługi gRPC w języku C#.
Aplikacja internetowa ASP.NET Core hostująca usługi gRPC wymaga tylko wygenerowanej klasy bazowej usługi:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
Aplikacja kliencka gRPC wykonująca wywołania gRPC wymaga tylko wygenerowanego konkretnego klienta:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>
Projekty WPF nie mogą wygenerować zasobów gRPC C# z .proto
plików
Projekty WPF mają znany problem uniemożliwiający poprawne działanie generowania kodu gRPC. Wszystkie typy gRPC wygenerowane w projekcie WPF przez odwołanie Grpc.Tools
i .proto
pliki będą tworzyć błędy kompilacji w przypadku użycia:
błąd CS0246: Nie można odnaleźć nazwy typu lub przestrzeni nazw "MyGrpcServices" (czy brakuje dyrektywy using lub odwołania do zestawu?)
Ten problem można obejść, wykonując następujące czynności:
- Utwórz nowy projekt biblioteki klas platformy .NET Core.
- W nowym projekcie dodaj odwołania, aby włączyć generowanie kodu w języku C# z
.proto
plików:- Dodaj następujące odwołania do pakietu:
- Dodaj pliki
.proto
do grupy elementów<Protobuf>
.
- W aplikacji WPF dodaj odwołanie do nowego projektu.
Aplikacja WPF może używać typów wygenerowanych przez gRPC z nowego projektu biblioteki klas.
Wywoływanie usług gRPC hostowanych w podkatalogu
Ostrzeżenie
Wiele narzędzi gRPC innych firm nie obsługuje usług hostowanych w podkatalogach. Rozważ znalezienie sposobu hostowania gRPC jako katalogu głównego.
Składnik ścieżki adresu kanału gRPC jest ignorowany podczas wykonywania wywołań gRPC. Na przykład GrpcChannel.ForAddress("https://localhost:5001/ignored_path")
nie będzie używany ignored_path
podczas routingu wywołań gRPC dla usługi.
Ścieżka adresu jest ignorowana, ponieważ gRPC ma ustandaryzowaną, preskrypcyjną strukturę adresów. Adres gRPC łączy nazwy pakietu, usługi i metody: https://localhost:5001/PackageName.ServiceName/MethodName
.
Istnieją pewne scenariusze, w których aplikacja musi zawierać ścieżkę z wywołaniami gRPC. Na przykład gdy aplikacja gRPC platformy ASP.NET Core jest hostowana w katalogu usług IIS, a katalog musi zostać uwzględniony w żądaniu. Gdy ścieżka jest wymagana, można ją dodać do wywołania gRPC przy użyciu niestandardowego SubdirectoryHandler
określonego poniżej:
/// <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 old = request.RequestUri;
var url = $"{old.Scheme}://{old.Host}:{old.Port}";
url += $"{_subdirectory}{request.RequestUri.AbsolutePath}";
request.RequestUri = new Uri(url, UriKind.Absolute);
return base.SendAsync(request, cancellationToken);
}
}
SubdirectoryHandler
jest używany podczas tworzenia kanału 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" });
Powyższy kod ma następujące działanie:
- Tworzy obiekt
SubdirectoryHandler
ze ścieżką/MyApp
. - Konfiguruje kanał do użycia .
SubdirectoryHandler
- Wywołuje usługę gRPC za pomocą polecenia
SayHelloAsync
. Wywołanie gRPC jest wysyłane do .https://localhost:5001/MyApp/greet.Greeter/SayHello
Alternatywnie fabrykę klienta można skonfigurować SubdirectoryHandler
przy użyciu polecenia AddHttpMessageHandler.
Limit czasu wywołania gRPC z HttpClient.Timeout
HttpClient jest domyślnie skonfigurowany z limitem czasu 100 sekund. GrpcChannel
Jeśli element jest skonfigurowany do używania , długotrwałe wywołania przesyłania strumieniowego HttpClient
gRPC zostaną anulowane, jeśli nie zostaną ukończone w limicie czasu.
System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
Istnieje kilka sposobów naprawienia tego błędu. Pierwszą z nich jest skonfigurowanie HttpClient.Timeout do większej wartości. Timeout.InfiniteTimeSpan wyłącza limit czasu:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var httpClient = new HttpClient(handler) { Timeout = Timeout.InfiniteTimeSpan };
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpClient = httpClient });
var client = new Greeter.GreeterClient(channel);
Możesz też unikać tworzenia i ustawiania HttpClient
GrpcChannel.HttpHandler
:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greeter.GreeterClient(channel);