Sdílet prostřednictvím


Řešení potíží s gRPC v .NET

Autor: James Newton-King

Poznámka:

Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Upozorňující

Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v tématu .NET a .NET Core Zásady podpory. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Důležité

Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.

Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

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 používají protokol TLS (Transport Layer Security) k zabezpečení služeb gRPC ve výchozím nastavení. Klienti gRPC potřebují k úspěšnému volání zabezpečených služeb gRPC použít zabezpečené připojení.

Můžete ověřit, že služba ASP.NET Core gRPC používá protokol TLS v protokolech zapsaný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í k volání se zabezpečeným připojením použít https na adrese serveru:

var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);

Všechny implementace klienta gRPC podporují protokol TLS. Klienti gRPC z jiných jazyků obvykle vyžadují kanál nakonfigurovaný .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 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ěla 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 neplatný podle ověřovací procedury.

Tato chyba se může zobrazit, pokud testujete aplikaci místně a ASP.NET core vývojový certifikát HTTPS není důvěryhodný. Pokyny k vyřešení tohoto problému najdete v tématu Důvěřovat vývojovému certifikátu ASP.NET Core 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ůžete klienta gRPC nakonfigurovat 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 handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = 
    HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;

var channel = GrpcChannel.ForAddress("https://localhost:5001",
    new GrpcChannelOptions { HttpHandler = handler });
var client = new Greeter.GreeterClient(channel);

Klientská továrna gRPC umožňuje volání bez důvěryhodného certifikátu. ConfigurePrimaryHttpMessageHandler Ke konfiguraci obslužné rutiny v klientovi použijte metodu rozšíření:


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;
    });

Upozorňující

Nedůvěryhodné certifikáty by se měly používat jenom při vývoji aplikací. Produkční aplikace by vždy měly používat platné certifikáty.

Volání nezabezpečených služeb gRPC pomocí klienta .NET Core

Klient .NET gRPC může volat nezabezpečené služby gRPC tak, že specifikuje http adresu serveru. 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 .NET, která aplikace používá:

Důležité

Nezabezpečené služby gRPC musí být hostované pouze na portu HTTP/2. Další informace najdete v tématu ASP.NET vyjednávání protokolu Core.

V systému macOS nejde spustit aplikaci ASP.NET Core gRPC

Kestrel nepodporuje protokol HTTP/2 s protokolem TLS v systému macOS před .NET 8. Šablona ASP.NET Core gRPC a ukázky ve výchozím nastavení používají protokol TLS. Při pokusu o spuštění serveru gRPC se zobrazí následující chybová zpráva:

Nelze vytvořit vazbu na https://localhost:5001 rozhraní zpětné smyčky IPv4: Protokol HTTP/2 přes protokol TLS není v systému macOS podporován kvůli chybějící podpoře ALPN.

Pokud chcete tento problém vyřešit v rozhraní .NET 7 a starších verzích, nakonfigurujte Kestrel klienta gRPC tak, aby používal protokol HTTP/2 bez protokolu TLS. Měli byste to udělat jenom během vývoje. Při použití protokolu TLS se neodesílají zprávy gRPC bez šifrování. Další informace najdete v tématu Asp.Net Core 7.0: V systému macOS nejde spustit aplikaci ASP.NET Core gRPC.

Prostředky gRPC C# nejsou kódem generované ze .proto souborů.

Generování kódu gRPC konkrétních klientů a základních tříd služby vyžaduje protobuf soubory a nástroje, na které se odkazuje z projektu. Musíte zahrnout:

Další informace o generování prostředků gRPC C# najdete v tématu služby gRPC s C#.

Webová aplikace ASP.NET Core hostující služby gRPC potřebuje pouze 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 pouze konkrétního klienta vygenerovaného:

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>

Projekty WPF nemůžou generovat prostředky gRPC C# ze .proto souborů

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 odkazováním Grpc.Tools a .proto soubory při použití vytvoří chyby kompilace:

Chyba CS0246: Typ nebo název oboru názvů MyGrpcServices nebyl nalezen (chybí direktiva using nebo odkaz na sestavení?)

Tento problém můžete obejít takto:

  1. Vytvořte nový projekt knihovny tříd .NET Core.
  2. V novém projektu přidejte odkazy pro povolení generování kódu jazyka C#ze .proto souborů:
  3. V aplikaci WPF přidejte odkaz na nový projekt.

Aplikace WPF může používat typy generované gRPC z nového projektu knihovny tříd.

Volání služeb gRPC hostovaných v podadresáři

Upozorňující

Mnoho nástrojů gRPC třetích stran nepodporuje služby hostované v podadresářích. Zvažte nalezení způsobu hostování gRPC jako kořenového adresáře.

Komponenta cesty adresy kanálu gRPC se při volání gRPC ignoruje. Například se nepoužije ignored_path při GrpcChannel.ForAddress("https://localhost:5001/ignored_path") směrování volání gRPC pro službu.

Cesta k adrese se ignoruje, protože gRPC má standardizovanou preskriptivní strukturu adres. Adresa gRPC 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 voláními gRPC. Pokud je například aplikace ASP.NET Core gRPC hostovaná v adresáři služby IIS a adresář musí být součástí požadavku. Je-li požadována cesta, lze ji přidat do volání gRPC pomocí vlastní SubdirectoryHandler zadané níže:

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 se používá při vytvář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 Greeter.GreeterClient(channel);

var reply = await client.SayHelloAsync(
                  new HelloRequest { Name = "GreeterClient" });

Předchozí kód:

  • Vytvoří s SubdirectoryHandler cestou ./MyApp
  • Nakonfiguruje kanál pro použití SubdirectoryHandler.
  • Volá službu gRPC s SayHelloAsync. Volání gRPC je odesláno do https://localhost:5001/MyApp/greet.Greeter/SayHello.

Alternativně lze klientskou továrnu nakonfigurovat SubdirectoryHandler pomocí .AddHttpMessageHandler

Konfigurace klienta gRPC pro použití PROTOKOLU HTTP/3

Klient .NET gRPC podporuje protokol HTTP/3 s .NET 6 nebo novějším. Pokud server odešle klientovi hlavičku alt-svc odpovědi, která označuje, že server podporuje protokol HTTP/3, klient automaticky upgraduje své připojení na HTTP/3. Další informace najdete v tématu Použití protokolu HTTP/3 s webovým serverem ASP.NET CoreKestrel.

Lze DelegatingHandler použít k vynucení použití klienta gRPC pro použití HTTP/3. Vynucení http/3 zabraňuje režii upgradu požadavku. Vynutit HTTP/3 s kódem podobným následujícímu:

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 se používá při vytváření kanálu gRPC. Následující kód vytvoří kanál nakonfigurovaný pro použití 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" });

Alternativně lze klientskou továrnu nakonfigurovat Http3Handler pomocí .AddHttpMessageHandler

Sestavování gRPC v Alpine Linuxu

Balíček Grpc.Tools generuje typy .NET ze .proto souborů pomocí zkompilovaného nativního binárního souboru s názvem protoc. Další kroky jsou potřeba k vytváření aplikací gRPC na platformách, které nejsou podporovány nativními binárními soubory, Grpc.Toolsnapříklad Alpine Linux.

Předem vygenerujte kód.

Jedním z řešení je vygenerovat kód předem.

  1. Přesuňte .proto soubory a odkaz na Grpc.Tools balíček do nového projektu.
  2. Publikujte projekt jako balíček NuGet a nahrajte ho do informačního kanálu NuGet.
  3. Aktualizujte aplikaci tak, aby odkazovat na balíček NuGet.

V předchozích krocích už aplikace nevyžaduje Grpc.Tools sestavení, protože kód se vygeneruje předem.

Přizpůsobení Grpc.Tools nativních binárních souborů

Grpc.Tools podporuje použití vlastních nativních binárních souborů. Tato funkce umožňuje, aby nástroje gRPC běžely v prostředích, ve kterých nejsou podporované nativní binární soubory.

Sestavte nebo získejte protoc nativní grpc_csharp_plugin binární soubory a nakonfigurujte Grpc.Tools je tak, aby je používaly. Nakonfigurujte nativní binární soubory nastavením následujících proměnných prostředí:

  • PROTOBUF_PROTOC – Úplná cesta k kompilátoru vyrovnávacích pamětí protokolu
  • GRPC_PROTOC_PLUGIN - Úplná cesta k grpc_csharp_plugin

Pro Alpine Linux existují balíčky poskytované komunitou pro kompilátor vyrovnávací paměti protokolu a moduly plug-in gRPC na adrese 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

Další informace o použití Grpc.Tools s nepodporovanými architekturami najdete v dokumentaci k integraci sestavení gRPC.

Časový limit volání gRPC z HttpClient.Timeout

HttpClient je ve výchozím nastavení nakonfigurovaný časový limit 100 sekund. GrpcChannel Pokud je nakonfigurované použití HttpClient, dlouhotrvající volání streamování gRPC se zruší, pokud se nedokončí v rámci časového limitu.

System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.

Existuje několik způsobů, jak tuto chybu opravit. Prvním je nakonfigurovat HttpClient.Timeout větší hodnotu. Timeout.InfiniteTimeSpan zakáže časový limit:

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);

Alternativně se místo toho vyhněte vytváření a nastavování 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);

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 používají protokol TLS (Transport Layer Security) k zabezpečení služeb gRPC ve výchozím nastavení. Klienti gRPC potřebují k úspěšnému volání zabezpečených služeb gRPC použít zabezpečené připojení.

Můžete ověřit, že služba ASP.NET Core gRPC používá protokol TLS v protokolech zapsaný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í k volání se zabezpečeným připojením použít https na adrese serveru:

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ý .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 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ěla 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 neplatný podle ověřovací procedury.

Tato chyba se může zobrazit, pokud testujete aplikaci místně a ASP.NET core vývojový certifikát HTTPS není důvěryhodný. Pokyny k vyřešení tohoto problému najdete v tématu Důvěřovat vývojovému certifikátu ASP.NET Core 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ůžete klienta gRPC nakonfigurovat 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 handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = 
    HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;

var channel = GrpcChannel.ForAddress("https://localhost:5001",
    new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);

Klientská továrna gRPC umožňuje volání bez důvěryhodného certifikátu. ConfigurePrimaryHttpMessageHandler Ke konfiguraci obslužné rutiny v klientovi použijte metodu rozšíření:

builder.Services
    .AddGrpcClient<Greeter.GreeterClient>(o =>
    {
        o.Address = new Uri("https://localhost:5001");
    })
    .ConfigurePrimaryHttpMessageHandler(() =>
    {
        var handler = new HttpClientHandler();
        handler.ServerCertificateCustomValidationCallback = 
            HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;

        return handler;
    });

Upozorňující

Nedůvěryhodné certifikáty by se měly používat jenom při vývoji aplikací. Produkční aplikace by vždy měly používat platné certifikáty.

Volání nezabezpečených služeb gRPC pomocí klienta .NET Core

Klient .NET gRPC může volat nezabezpečené služby gRPC tak, že specifikuje http adresu serveru. 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 .NET, která aplikace používá:

  • .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.Http2UnencryptedSupport přepínač na true:

    // 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);
    

Přepínač System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport se vyžaduje jenom pro .NET Core 3.x. V .NET 5 nic nedělá a nevyžaduje se.

Důležité

Nezabezpečené služby gRPC musí být hostované pouze na portu HTTP/2. Další informace najdete v tématu ASP.NET vyjednávání protokolu Core.

V systému macOS nejde spustit aplikaci ASP.NET Core gRPC

Kestrel nepodporuje protokol HTTP/2 s protokolem TLS v systému macOS před .NET 8. Šablona ASP.NET Core gRPC a ukázky ve výchozím nastavení používají protokol TLS. Při pokusu o spuštění serveru gRPC se zobrazí následující chybová zpráva:

Nelze vytvořit vazbu na https://localhost:5001 rozhraní zpětné smyčky IPv4: Protokol HTTP/2 přes protokol TLS není v systému macOS podporován kvůli chybějící podpoře ALPN.

Pokud chcete tento problém vyřešit v rozhraní .NET 7 a starších verzích, nakonfigurujte Kestrel klienta gRPC tak, aby používal protokol HTTP/2 bez protokolu TLS. Měli byste to udělat jenom během vývoje. Při použití protokolu TLS se neodesílají zprávy gRPC bez šifrování.

Kestrel musí nakonfigurovat koncový bod HTTP/2 bez protokolu TLS v 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);
});
  • V předchozím kódu nahraďte číslo 5287 portu localhost číslem HTTP portu (nikoli HTTPS) uvedeným v Properties/launchSettings.json projektu služby gRPC.

Pokud je koncový bod HTTP/2 nakonfigurovaný bez protokolu TLS, musí být parametr ListenOptions.Protocols koncového bodu nastavený na HttpProtocols.Http2hodnotu . HttpProtocols.Http1AndHttp2 nejde použít, protože k vyjednání protokolu HTTP/2 se vyžaduje protokol TLS. Bez protokolu 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 nepoužít protokol TLS. Další informace najdete v tématu Volání nezabezpečených služeb gRPC pomocí klienta .NET Core.

Upozorňující

PROTOKOL HTTP/2 bez protokolu TLS by se měl používat jenom při vývoji 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 C# nejsou kódem generované ze .proto souborů.

Generování kódu gRPC konkrétních klientů a základních tříd služby vyžaduje protobuf soubory a nástroje, na které se odkazuje z projektu. Musíte zahrnout:

Další informace o generování prostředků gRPC C# najdete v tématu služby gRPC s C#.

Webová aplikace ASP.NET Core hostující služby gRPC potřebuje pouze 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 pouze konkrétního klienta vygenerovaného:

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>

Projekty WPF nemůžou generovat prostředky gRPC C# ze .proto souborů

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 odkazováním Grpc.Tools a .proto soubory při použití vytvoří chyby kompilace:

Chyba CS0246: Typ nebo název oboru názvů MyGrpcServices nebyl nalezen (chybí direktiva using nebo odkaz na sestavení?)

Tento problém můžete obejít takto:

  1. Vytvořte nový projekt knihovny tříd .NET Core.
  2. V novém projektu přidejte odkazy pro povolení generování kódu jazyka C#ze .proto souborů:
  3. V aplikaci WPF přidejte odkaz na nový projekt.

Aplikace WPF může používat typy generované gRPC z nového projektu knihovny tříd.

Volání služeb gRPC hostovaných v podadresáři

Upozorňující

Mnoho nástrojů gRPC třetích stran nepodporuje služby hostované v podadresářích. Zvažte nalezení způsobu hostování gRPC jako kořenového adresáře.

Komponenta cesty adresy kanálu gRPC se při volání gRPC ignoruje. Například se nepoužije ignored_path při GrpcChannel.ForAddress("https://localhost:5001/ignored_path") směrování volání gRPC pro službu.

Cesta k adrese se ignoruje, protože gRPC má standardizovanou preskriptivní strukturu adres. Adresa gRPC 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 voláními gRPC. Pokud je například aplikace ASP.NET Core gRPC hostovaná v adresáři služby IIS a adresář musí být součástí požadavku. Je-li požadována cesta, lze ji přidat do volání gRPC pomocí vlastní SubdirectoryHandler zadané níže:

/// <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 se používá při vytvář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ří s SubdirectoryHandler cestou ./MyApp
  • Nakonfiguruje kanál pro použití SubdirectoryHandler.
  • Volá službu gRPC s SayHelloAsync. Volání gRPC je odesláno do https://localhost:5001/MyApp/greet.Greeter/SayHello.

Alternativně lze klientskou továrnu nakonfigurovat SubdirectoryHandler pomocí .AddHttpMessageHandler

Konfigurace klienta gRPC pro použití PROTOKOLU HTTP/3

Klient .NET gRPC podporuje protokol HTTP/3 s .NET 6 nebo novějším. Pokud server odešle klientovi hlavičku alt-svc odpovědi, která označuje, že server podporuje protokol HTTP/3, klient automaticky upgraduje své připojení na HTTP/3. Informace o povolení PROTOKOLU HTTP/3 na serveru najdete v tématu Použití protokolu HTTP/3 s webovým serverem ASP.NET CoreKestrel.

Podpora PROTOKOLU HTTP/3 v .NET 8 je ve výchozím nastavení povolená. Podporu HTTP/3 v .NET 6 a .NET 7 je potřeba povolit prostřednictvím příznaku konfigurace v souboru projektu:

<ItemGroup>
  <RuntimeHostConfigurationOption Include="System.Net.SocketsHttpHandler.Http3Support" Value="true" />
</ItemGroup>

System.Net.SocketsHttpHandler.Http3Support lze také nastavit pomocí AppContext.SetSwitch.

Lze DelegatingHandler použít k vynucení použití klienta gRPC pro použití HTTP/3. Vynucení http/3 zabraňuje režii upgradu požadavku. Vynutit HTTP/3 s kódem podobným následujícímu:

/// <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 se používá při vytváření kanálu gRPC. Následující kód vytvoří kanál nakonfigurovaný pro použití 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" });

Alternativně lze klientskou továrnu nakonfigurovat Http3Handler pomocí .AddHttpMessageHandler

Sestavování gRPC v Alpine Linuxu

Balíček Grpc.Tools generuje typy .NET ze .proto souborů pomocí zkompilovaného nativního binárního souboru s názvem protoc. Další kroky jsou potřeba k vytváření aplikací gRPC na platformách, které nejsou podporovány nativními binárními soubory, Grpc.Toolsnapříklad Alpine Linux.

Předem vygenerujte kód.

Jedním z řešení je vygenerovat kód předem.

  1. Přesuňte .proto soubory a odkaz na Grpc.Tools balíček do nového projektu.
  2. Publikujte projekt jako balíček NuGet a nahrajte ho do informačního kanálu NuGet.
  3. Aktualizujte aplikaci tak, aby odkazovat na balíček NuGet.

V předchozích krocích už aplikace nevyžaduje Grpc.Tools sestavení, protože kód se vygeneruje předem.

Přizpůsobení Grpc.Tools nativních binárních souborů

Grpc.Tools podporuje použití vlastních nativních binárních souborů. Tato funkce umožňuje, aby nástroje gRPC běžely v prostředích, ve kterých nejsou podporované nativní binární soubory.

Sestavte nebo získejte protoc nativní grpc_csharp_plugin binární soubory a nakonfigurujte Grpc.Tools je tak, aby je používaly. Nakonfigurujte nativní binární soubory nastavením následujících proměnných prostředí:

  • PROTOBUF_PROTOC – Úplná cesta k kompilátoru vyrovnávacích pamětí protokolu
  • GRPC_PROTOC_PLUGIN - Úplná cesta k grpc_csharp_plugin

Pro Alpine Linux existují balíčky poskytované komunitou pro kompilátor vyrovnávací paměti protokolu a moduly plug-in gRPC na adrese 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

Další informace o použití Grpc.Tools s nepodporovanými architekturami najdete v dokumentaci k integraci sestavení gRPC.

Časový limit volání gRPC z HttpClient.Timeout

HttpClient je ve výchozím nastavení nakonfigurovaný časový limit 100 sekund. GrpcChannel Pokud je nakonfigurované použití HttpClient, dlouhotrvající volání streamování gRPC se zruší, pokud se nedokončí v rámci časového limitu.

System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.

Existuje několik způsobů, jak tuto chybu opravit. Prvním je nakonfigurovat HttpClient.Timeout větší hodnotu. Timeout.InfiniteTimeSpan zakáže časový limit:

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);

Alternativně se místo toho vyhněte vytváření a nastavování 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);

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 používají protokol TLS (Transport Layer Security) k zabezpečení služeb gRPC ve výchozím nastavení. Klienti gRPC potřebují k úspěšnému volání zabezpečených služeb gRPC použít zabezpečené připojení.

Můžete ověřit, že služba ASP.NET Core gRPC používá protokol TLS v protokolech zapsaný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í k volání se zabezpečeným připojením použít https na adrese serveru:

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ý .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 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ěla 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 neplatný podle ověřovací procedury.

Tato chyba se může zobrazit, pokud testujete aplikaci místně a ASP.NET core vývojový certifikát HTTPS není důvěryhodný. Pokyny k vyřešení tohoto problému najdete v tématu Důvěřovat vývojovému certifikátu ASP.NET Core 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ůžete klienta gRPC nakonfigurovat 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 handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = 
    HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;

var channel = GrpcChannel.ForAddress("https://localhost:5001",
    new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);

Klientská továrna gRPC umožňuje volání bez důvěryhodného certifikátu. ConfigurePrimaryHttpMessageHandler Ke konfiguraci obslužné rutiny v klientovi použijte metodu rozšíření:

services
    .AddGrpcClient<Greeter.GreeterClient>(o =>
    {
        o.Address = new Uri("https://localhost:5001");
    })
    .ConfigurePrimaryHttpMessageHandler(() =>
    {
        var handler = new HttpClientHandler();
        handler.ServerCertificateCustomValidationCallback = 
            HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;

        return handler;
    });

Upozorňující

Nedůvěryhodné certifikáty by se měly používat jenom při vývoji aplikací. Produkční aplikace by vždy měly používat platné certifikáty.

Volání nezabezpečených služeb gRPC pomocí klienta .NET Core

Klient .NET gRPC může volat nezabezpečené služby gRPC tak, že specifikuje http adresu serveru. 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 .NET, která aplikace používá:

  • .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.Http2UnencryptedSupport přepínač na true:

    // 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);
    

Přepínač System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport se vyžaduje jenom pro .NET Core 3.x. V .NET 5 nic nedělá a nevyžaduje se.

Důležité

Nezabezpečené služby gRPC musí být hostované pouze na portu HTTP/2. Další informace najdete v tématu ASP.NET vyjednávání protokolu Core.

V systému macOS nejde spustit aplikaci ASP.NET Core gRPC

Kestrel nepodporuje protokol HTTP/2 s protokolem TLS v systému macOS před .NET 8. Šablona ASP.NET Core gRPC a ukázky ve výchozím nastavení používají protokol TLS. Při pokusu o spuštění serveru gRPC se zobrazí následující chybová zpráva:

Nelze vytvořit vazbu na https://localhost:5001 rozhraní zpětné smyčky IPv4: Protokol HTTP/2 přes protokol TLS není v systému macOS podporován kvůli chybějící podpoře ALPN.

Pokud chcete tento problém vyřešit v rozhraní .NET 7 a starších verzích, nakonfigurujte Kestrel klienta gRPC tak, aby používal protokol HTTP/2 bez protokolu TLS. Měli byste to udělat jenom během vývoje. Při použití protokolu TLS se neodesílají zprávy gRPC bez šifrování.

Kestrel musí nakonfigurovat koncový bod HTTP/2 bez protokolu TLS v 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>();
        });

Pokud je koncový bod HTTP/2 nakonfigurovaný bez protokolu TLS, musí být parametr ListenOptions.Protocols koncového bodu nastavený na HttpProtocols.Http2hodnotu . HttpProtocols.Http1AndHttp2 nejde použít, protože k vyjednání protokolu HTTP/2 se vyžaduje protokol TLS. Bez protokolu 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 nepoužít protokol TLS. Další informace najdete v tématu Volání nezabezpečených služeb gRPC pomocí klienta .NET Core.

Upozorňující

PROTOKOL HTTP/2 bez protokolu TLS by se měl používat jenom při vývoji 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 C# nejsou kódem generované ze .proto souborů.

Generování kódu gRPC konkrétních klientů a základních tříd služby vyžaduje protobuf soubory a nástroje, na které se odkazuje z projektu. Musíte zahrnout:

Další informace o generování prostředků gRPC C# najdete v tématu služby gRPC s C#.

Webová aplikace ASP.NET Core hostující služby gRPC potřebuje pouze 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 pouze konkrétního klienta vygenerovaného:

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>

Projekty WPF nemůžou generovat prostředky gRPC C# ze .proto souborů

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 odkazováním Grpc.Tools a .proto soubory při použití vytvoří chyby kompilace:

Chyba CS0246: Typ nebo název oboru názvů MyGrpcServices nebyl nalezen (chybí direktiva using nebo odkaz na sestavení?)

Tento problém můžete obejít takto:

  1. Vytvořte nový projekt knihovny tříd .NET Core.
  2. V novém projektu přidejte odkazy pro povolení generování kódu jazyka C#ze .proto souborů:
  3. V aplikaci WPF přidejte odkaz na nový projekt.

Aplikace WPF může používat typy generované gRPC z nového projektu knihovny tříd.

Volání služeb gRPC hostovaných v podadresáři

Upozorňující

Mnoho nástrojů gRPC třetích stran nepodporuje služby hostované v podadresářích. Zvažte nalezení způsobu hostování gRPC jako kořenového adresáře.

Komponenta cesty adresy kanálu gRPC se při volání gRPC ignoruje. Například se nepoužije ignored_path při GrpcChannel.ForAddress("https://localhost:5001/ignored_path") směrování volání gRPC pro službu.

Cesta k adrese se ignoruje, protože gRPC má standardizovanou preskriptivní strukturu adres. Adresa gRPC 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 voláními gRPC. Pokud je například aplikace ASP.NET Core gRPC hostovaná v adresáři služby IIS a adresář musí být součástí požadavku. Je-li požadována cesta, lze ji přidat do volání gRPC pomocí vlastní SubdirectoryHandler zadané níže:

/// <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 se používá při vytvář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ří s SubdirectoryHandler cestou ./MyApp
  • Nakonfiguruje kanál pro použití SubdirectoryHandler.
  • Volá službu gRPC s SayHelloAsync. Volání gRPC je odesláno do https://localhost:5001/MyApp/greet.Greeter/SayHello.

Alternativně lze klientskou továrnu nakonfigurovat SubdirectoryHandler pomocí .AddHttpMessageHandler

Časový limit volání gRPC z HttpClient.Timeout

HttpClient je ve výchozím nastavení nakonfigurovaný časový limit 100 sekund. GrpcChannel Pokud je nakonfigurované použití HttpClient, dlouhotrvající volání streamování gRPC se zruší, pokud se nedokončí v rámci časového limitu.

System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.

Existuje několik způsobů, jak tuto chybu opravit. Prvním je nakonfigurovat HttpClient.Timeout větší hodnotu. Timeout.InfiniteTimeSpan zakáže časový limit:

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);

Alternativně se místo toho vyhněte vytváření a nastavování 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);

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 používají protokol TLS (Transport Layer Security) k zabezpečení služeb gRPC ve výchozím nastavení. Klienti gRPC potřebují k úspěšnému volání zabezpečených služeb gRPC použít zabezpečené připojení.

Můžete ověřit, že služba ASP.NET Core gRPC používá protokol TLS v protokolech zapsaný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í k volání se zabezpečeným připojením použít https na adrese serveru:

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ý .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 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ěla 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 neplatný podle ověřovací procedury.

Tato chyba se může zobrazit, pokud testujete aplikaci místně a ASP.NET core vývojový certifikát HTTPS není důvěryhodný. Pokyny k vyřešení tohoto problému najdete v tématu Důvěřovat vývojovému certifikátu ASP.NET Core 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ůžete klienta gRPC nakonfigurovat 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 handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = 
    HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;

var channel = GrpcChannel.ForAddress("https://localhost:5001",
    new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);

Klientská továrna gRPC umožňuje volání bez důvěryhodného certifikátu. ConfigurePrimaryHttpMessageHandler Ke konfiguraci obslužné rutiny v klientovi použijte metodu rozšíření:

services
    .AddGrpcClient<Greeter.GreeterClient>(o =>
    {
        o.Address = new Uri("https://localhost:5001");
    })
    .ConfigurePrimaryHttpMessageHandler(() =>
    {
        var handler = new HttpClientHandler();
        handler.ServerCertificateCustomValidationCallback = 
            HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;

        return handler;
    });

Upozorňující

Nedůvěryhodné certifikáty by se měly používat jenom při vývoji aplikací. Produkční aplikace by vždy měly používat platné certifikáty.

Volání nezabezpečených služeb gRPC pomocí klienta .NET Core

Klient .NET gRPC může volat nezabezpečené služby gRPC tak, že specifikuje http adresu serveru. 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 .NET, která aplikace používá:

  • .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.Http2UnencryptedSupport přepínač na true:

    // 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);
    

Přepínač System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport se vyžaduje jenom pro .NET Core 3.x. V .NET 5 nic nedělá a nevyžaduje se.

Důležité

Nezabezpečené služby gRPC musí být hostované pouze na portu HTTP/2. Další informace najdete v tématu ASP.NET vyjednávání protokolu Core.

V systému macOS nejde spustit aplikaci ASP.NET Core gRPC

Kestrel nepodporuje protokol HTTP/2 s protokolem TLS v systému macOS před .NET 8. Šablona ASP.NET Core gRPC a ukázky ve výchozím nastavení používají protokol TLS. Při pokusu o spuštění serveru gRPC se zobrazí následující chybová zpráva:

Nelze vytvořit vazbu na https://localhost:5001 rozhraní zpětné smyčky IPv4: Protokol HTTP/2 přes protokol TLS není v systému macOS podporován kvůli chybějící podpoře ALPN.

Pokud chcete tento problém vyřešit v rozhraní .NET 7 a starších verzích, nakonfigurujte Kestrel klienta gRPC tak, aby používal protokol HTTP/2 bez protokolu TLS. Měli byste to udělat jenom během vývoje. Při použití protokolu TLS se neodesílají zprávy gRPC bez šifrování.

Kestrel musí nakonfigurovat koncový bod HTTP/2 bez protokolu TLS v 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>();
        });

Pokud je koncový bod HTTP/2 nakonfigurovaný bez protokolu TLS, musí být parametr ListenOptions.Protocols koncového bodu nastavený na HttpProtocols.Http2hodnotu . HttpProtocols.Http1AndHttp2 nejde použít, protože k vyjednání protokolu HTTP/2 se vyžaduje protokol TLS. Bez protokolu 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 nepoužít protokol TLS. Další informace najdete v tématu Volání nezabezpečených služeb gRPC pomocí klienta .NET Core.

Upozorňující

PROTOKOL HTTP/2 bez protokolu TLS by se měl používat jenom při vývoji 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 C# nejsou kódem generované ze .proto souborů.

Generování kódu gRPC konkrétních klientů a základních tříd služby vyžaduje protobuf soubory a nástroje, na které se odkazuje z projektu. Musíte zahrnout:

Další informace o generování prostředků gRPC C# najdete v tématu služby gRPC s C#.

Webová aplikace ASP.NET Core hostující služby gRPC potřebuje pouze 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 pouze konkrétního klienta vygenerovaného:

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>

Projekty WPF nemůžou generovat prostředky gRPC C# ze .proto souborů

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 odkazováním Grpc.Tools a .proto soubory při použití vytvoří chyby kompilace:

Chyba CS0246: Typ nebo název oboru názvů MyGrpcServices nebyl nalezen (chybí direktiva using nebo odkaz na sestavení?)

Tento problém můžete obejít takto:

  1. Vytvořte nový projekt knihovny tříd .NET Core.
  2. V novém projektu přidejte odkazy pro povolení generování kódu jazyka C#ze .proto souborů:
  3. V aplikaci WPF přidejte odkaz na nový projekt.

Aplikace WPF může používat typy generované gRPC z nového projektu knihovny tříd.

Volání služeb gRPC hostovaných v podadresáři

Upozorňující

Mnoho nástrojů gRPC třetích stran nepodporuje služby hostované v podadresářích. Zvažte nalezení způsobu hostování gRPC jako kořenového adresáře.

Komponenta cesty adresy kanálu gRPC se při volání gRPC ignoruje. Například se nepoužije ignored_path při GrpcChannel.ForAddress("https://localhost:5001/ignored_path") směrování volání gRPC pro službu.

Cesta k adrese se ignoruje, protože gRPC má standardizovanou preskriptivní strukturu adres. Adresa gRPC 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 voláními gRPC. Pokud je například aplikace ASP.NET Core gRPC hostovaná v adresáři služby IIS a adresář musí být součástí požadavku. Je-li požadována cesta, lze ji přidat do volání gRPC pomocí vlastní SubdirectoryHandler zadané níže:

/// <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 se používá při vytvář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ří s SubdirectoryHandler cestou ./MyApp
  • Nakonfiguruje kanál pro použití SubdirectoryHandler.
  • Volá službu gRPC s SayHelloAsync. Volání gRPC je odesláno do https://localhost:5001/MyApp/greet.Greeter/SayHello.

Alternativně lze klientskou továrnu nakonfigurovat SubdirectoryHandler pomocí .AddHttpMessageHandler

Časový limit volání gRPC z HttpClient.Timeout

HttpClient je ve výchozím nastavení nakonfigurovaný časový limit 100 sekund. GrpcChannel Pokud je nakonfigurované použití HttpClient, dlouhotrvající volání streamování gRPC se zruší, pokud se nedokončí v rámci časového limitu.

System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.

Existuje několik způsobů, jak tuto chybu opravit. Prvním je nakonfigurovat HttpClient.Timeout větší hodnotu. Timeout.InfiniteTimeSpan zakáže časový limit:

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);

Alternativně se místo toho vyhněte vytváření a nastavování 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);