Megosztás a következőn keresztül:


A gRPC hibaelhárítása a .NET-en

Írta: James Newton-King

Note

Ez nem a cikk legújabb verziója. Az aktuális kiadásról a cikk .NET 10-es verziójában olvashat.

Warning

A ASP.NET Core ezen verziója már nem támogatott. További információt a .NET és a .NET Core támogatási szabályzatában talál. A jelen cikk .NET 9-es verzióját lásd az aktuális kiadásért .

Ez a dokumentum a gRPC-alkalmazások .NET-en való fejlesztése során gyakran előforduló problémákat ismerteti.

Eltérés az ügyfél és a szolgáltatás SSL-/TLS-konfigurációja között

A gRPC-sablon és -minták a Transport Layer Security (TLS) használatával biztosítják alapértelmezés szerint a gRPC-szolgáltatásokat. A gRPC-ügyfeleknek biztonságos kapcsolatot kell használniuk a biztonságos gRPC-szolgáltatások sikeres meghívásához.

Ellenőrizheti, hogy a ASP.NET Core gRPC szolgáltatás TLS-t használ-e az alkalmazás indításakor írt naplókban. A szolgáltatás egy HTTPS-végpontot figyel:

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

A .NET-ügyfélnek a kiszolgáló címében kell használnia https a hívások biztonságos kapcsolattal való indításához:

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

Minden gRPC-ügyfél-implementáció támogatja a TLS-t. A más nyelvekről származó gRPC-ügyfelek általában megkövetelik a csatorna konfigurálását SslCredentials. SslCredentials Meghatározza az ügyfél által használandó tanúsítványt, és azt a nem biztonságos hitelesítő adatok helyett kell használni. Példák a különböző gRPC-ügyfél-implementációk TLS használatára való konfigurálására: gRPC-hitelesítés.

gRPC szolgáltatás meghívása nem megbízható/érvénytelen tanúsítvánnyal

A .NET gRPC-ügyfél megköveteli, hogy a szolgáltatás megbízható tanúsítvánnyal rendelkezzen. A rendszer a következő hibaüzenetet adja vissza, ha megbízható tanúsítvány nélkül hív meg egy gRPC-szolgáltatást:

Kezeletlen kivétel. System.Net.Http.HttpRequestException: Az SSL-kapcsolat nem hozható létre, lásd a belső kivételt. >--- System.Security.Authentication.AuthenticationException: A távoli tanúsítvány érvénytelen az érvényesítési eljárásnak megfelelően.

Ez a hiba akkor jelenhet meg, ha helyileg teszteli az alkalmazást, és a ASP.NET Core HTTPS fejlesztési tanúsítvány nem megbízható. A probléma megoldására vonatkozó utasításokért tekintse meg a ASP.NET Core HTTPS fejlesztői tanúsítvány megbízhatóságát Windows és macOS rendszeren.

Ha egy gRPC-szolgáltatást hív meg egy másik gépen, és nem tud megbízni a tanúsítványban, akkor a gRPC-ügyfél konfigurálható úgy, hogy figyelmen kívül hagyja az érvénytelen tanúsítványt. A következő kód a megbízható tanúsítvány nélküli hívások engedélyezésére szolgál HttpClientHandler.ServerCertificateCustomValidationCallback :

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

A gRPC-ügyfél-előállító megbízható tanúsítvány nélkül engedélyezi a hívásokat. ConfigurePrimaryHttpMessageHandler A bővítménymetódus használatával konfigurálja a kezelőt az ügyfélen:


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

Warning

A nem megbízható tanúsítványokat csak az alkalmazásfejlesztés során szabad használni. A gyártásban lévő alkalmazásoknak mindig érvényes tanúsítványokat kell használniuk.

Nem biztonságos gRPC-szolgáltatások hívása .NET-ügyféllel

A .NET gRPC-ügyfél biztonság nélküli gRPC-szolgáltatásokat hívhat meg a kiszolgáló címének http megadásával. Például: GrpcChannel.ForAddress("http://localhost:5000").

Az alkalmazás által használt .NET-verziótól függően további követelmények vonatkoznak a nem biztonságos gRPC-szolgáltatások meghívására:

Important

A nem biztonságos gRPC-szolgáltatásokat http/2-csak porton kell üzemeltetni. További információ: ASP.NET Core protokoll egyeztetése.

Nem indítható el ASP.NET Core gRPC-alkalmazás macOS rendszeren

Kestrel nem támogatja a HTTP/2-t a tLS-sel macOS rendszeren a .NET 8 előtt. A ASP.NET Core gRPC-sablon és -minták alapértelmezés szerint TLS-t használnak. A gRPC-kiszolgáló indításakor a következő hibaüzenet jelenik meg:

Nem lehet csatlakozni https://localhost:5001 az IPv4-visszacsatolási felületen: "A HTTP/2 TLS-en keresztül nem támogatott macOS rendszeren, mert hiányzik az ALPN-támogatás."

A probléma megoldásához a .NET 7 vagy korábbi verzióiban konfigurálja a Kestrel és a gRPC-ügyfelet a HTTP/2 TLS nélküli használatára. Ezt csak a fejlesztés során szabad elvégeznie. A TLS használatának mellőzése esetén a gRPC-üzenetek titkosítás nélkül lesznek elküldve. További információ: ASP.NET Core a .NET 7-ben: Nem indítható el ASP.NET Core gRPC-alkalmazás macOS rendszeren.

A gRPC C#-objektumok nem fájlokból .proto generált kód

A konkrét ügyfelek és a szolgáltatásbázis-osztályok gRPC-kódgenerálásához protobuf fájlokat és eszközöket kell hivatkozni egy projektből. A következőket kell tartalmaznia:

A gRPC C#-eszközök létrehozásával kapcsolatos további információkért lásd a GRPC-szolgáltatásokat a C#-tal.

A gRPC-szolgáltatásokat üzemeltető ASP.NET Core-webalkalmazásnak csak a létrehozott alapszolgáltatás-osztályra van szüksége:

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

A gRPC-hívásokat kezdeményező gRPC-ügyfélalkalmazásnak csak a létrehozott konkrét ügyfélre van szüksége:

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

A WPF-projektek nem tudnak gRPC C#-objektumokat létrehozni fájlokból .proto

A WPF-projektek ismert problémával rendelkeznek, amely megakadályozza a gRPC-kódlétrehozást a megfelelő működésben. A WPF projektben a Grpc.Tools és .proto fájlokra való hivatkozással generált gRPC-típusok fordítási hibákat okoznak a használat során.

CS0246-os hiba: A "MyGrpcServices" típus- vagy névtérnév nem található (hiányzik egy felhasználói irányelv vagy egy szerelvényhivatkozás?)

A problémát a következő módon lehet megkerülni:

  1. Hozzon létre egy új .NET-osztálytárprojektet.
  2. Az új projektben adjon hozzá hivatkozásokat a C#-kód fájlokból való .proto létrehozásának engedélyezéséhez:
  3. A WPF-alkalmazásban adjon hozzá egy hivatkozást az új projekthez.

A WPF-alkalmazás használhatja az új osztálytárprojektből létrehozott gRPC-típusokat.

Alkönyvtárban üzemeltetett gRPC-szolgáltatások meghívása

Warning

Számos külső gRPC-eszköz nem támogatja az alkönyvtárakban üzemeltetett szolgáltatásokat. Fontolja meg a gRPC gyökérkönyvtárként való üzemeltetésének módját.

A gRPC-csatorna címének elérési útösszetevőjét a rendszer figyelmen kívül hagyja a gRPC-hívások során. Nem használható GrpcChannel.ForAddress("https://localhost:5001/ignored_path") például a ignored_path szolgáltatáshoz tartozó gRPC-hívások útválasztása során.

A cím elérési útja figyelmen kívül lesz hagyva, mert a gRPC szabványosított, előíró címstruktúrával rendelkezik. A gRPC-címek egyesítik a csomag, a szolgáltatás és a metódus nevét: https://localhost:5001/PackageName.ServiceName/MethodName.

Vannak olyan esetek, amikor egy alkalmazásnak gRPC-hívásokkal kell tartalmaznia egy elérési utat. Ha például egy ASP.NET Core gRPC-alkalmazást üzemeltetnek egy IIS-címtárban, és a címtárat bele kell foglalni a kérésbe. Ha egy elérési út szükséges, az alábbi egyéni SubdirectoryHandler beállítással adható hozzá a gRPC-híváshoz:

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 a gRPC-csatorna létrehozásakor használatos.

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

Az előző kód:

  • Létrehoz egy SubdirectoryHandler a /MyApp elérési úttal.
  • Konfigurál egy csatornát a SubdirectoryHandler használatára.
  • Meghívja a gRPC szolgáltatást a következővel SayHelloAsync: . A gRPC-hívást a rendszer elküldi a következőnek https://localhost:5001/MyApp/greet.Greeter/SayHello: .

Másik lehetőségként egy ügyfél gyártói is konfigurálható SubdirectoryHandlerAddHttpMessageHandler használatával.

A gRPC-ügyfél konfigurálása HTTP/3 használatára

A .NET gRPC-ügyfél támogatja a HTTP/3-at a .NET 6-os vagy újabb verziójával. Ha a kiszolgáló egy válaszfejlécet alt-svc küld az ügyfélnek, amely azt jelzi, hogy a kiszolgáló támogatja a HTTP/3-at, az ügyfél automatikusan http/3-ra frissíti a kapcsolatot. További információ: HTTP/3 használata a ASP.NET Core Kestrel webkiszolgálóval.

Az A DelegatingHandler használatával kényszerítheti a gRPC-ügyfelet a HTTP/3 használatára. A HTTP/3 kényszerítése elkerüli a kérés frissítésének többletterhelését. A HTTP/3 kényszerítése a következőhöz hasonló kóddal:

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 a gRPC-csatorna létrehozásakor használatos. Az alábbi kód egy olyan csatornát hoz létre, amely Http3Handler használatára van konfigurálva.

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

Másik lehetőségként egy ügyfél gyártói is konfigurálható Http3HandlerAddHttpMessageHandler használatával.

GRPC létrehozása Alpine Linuxon

A Grpc.Tools csomag .NET-típusokat hoz létre a .proto fájlokból egy kötegelt natív bináris, nevű protoc. További lépések szükségesek a gRPC-alkalmazások olyan platformokon való létrehozásához, amelyeket a natív bináris fájlok nem támogatnak, például az Alpine Linuxban Grpc.Tools.

Kód létrehozása előre

Az egyik megoldás a kód idő előtti létrehozása.

  1. Helyezze át a .proto fájlokat és a Grpc.Tools csomaghivatkozást egy új projektbe.
  2. Tegye közzé a projektet NuGet-csomagként, és töltse fel egy NuGet-hírcsatornába.
  3. Frissítse az alkalmazást a NuGet-csomagra való hivatkozáshoz.

Az előző lépésekkel az alkalmazásnak már nem kell buildelést végrehajtania Grpc.Tools , mert a kód előre létrejön.

Natív bináris fájlok testreszabása Grpc.Tools

Grpc.Tools támogatja az egyéni natív bináris fájlok használatát. Ez a funkció lehetővé teszi, hogy a gRPC-eszközök olyan környezetekben fussanak, amelyben a natív bináris fájlok kötegei nem támogatottak.

Készítse el vagy szerezze be a protoc és grpc_csharp_plugin natív binárisokat, és konfigurálja a Grpc.Tools azok használatára. Konfigurálja a natív bináris fájlokat a következő környezeti változók beállításával:

  • PROTOBUF_PROTOC - A protokollpufferek fordítójának teljes elérési útja
  • GRPC_PROTOC_PLUGIN - A grpc_csharp_plugin teljes elérési útja

Az Alpine Linux esetében a közösség biztosít csomagokat a protokollpufferek fordítójához és a gRPC beépülő modulokhoz a következő helyen: 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

A nem támogatott architektúrák használatával Grpc.Tools kapcsolatos további információkért tekintse meg a gRPC buildintegrációs dokumentációját.

gRPC-hívás időtúllépése innen: HttpClient.Timeout

HttpClient alapértelmezés szerint 100 másodperces időtúllépéssel van konfigurálva. Ha a GrpcChannel úgy van konfigurálva, hogy egy HttpClient-et használjon, a hosszú ideig futó gRPC-streamhívásokat megszakítják, ha nem fejeződnek be az időkorláton belül.

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

Ezt a hibát többféleképpen is kijavíthatja. Az első lépés HttpClient.Timeout nagyobb értékre való konfigurálása. Timeout.InfiniteTimeSpan kikapcsolja az időkorlátot.

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

Másik lehetőségként kerülje HttpClient létrehozását és helyette állítsa be GrpcChannel.HttpHandler-et.

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

Ez a dokumentum a gRPC-alkalmazások .NET-en való fejlesztése során gyakran előforduló problémákat ismerteti.

Eltérés az ügyfél és a szolgáltatás SSL-/TLS-konfigurációja között

A gRPC-sablon és -minták a Transport Layer Security (TLS) használatával biztosítják alapértelmezés szerint a gRPC-szolgáltatásokat. A gRPC-ügyfeleknek biztonságos kapcsolatot kell használniuk a biztonságos gRPC-szolgáltatások sikeres meghívásához.

Ellenőrizheti, hogy a ASP.NET Core gRPC szolgáltatás TLS-t használ-e az alkalmazás indításakor írt naplókban. A szolgáltatás egy HTTPS-végpontot figyel:

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

A .NET-ügyfélnek a kiszolgáló címében kell használnia https a hívások biztonságos kapcsolattal való indításához:

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

Minden gRPC-ügyfél-implementáció támogatja a TLS-t. A más nyelvekről származó gRPC-ügyfelek általában megkövetelik a csatorna konfigurálását SslCredentials. SslCredentials Meghatározza az ügyfél által használandó tanúsítványt, és azt a nem biztonságos hitelesítő adatok helyett kell használni. Példák a különböző gRPC-ügyfél-implementációk TLS használatára való konfigurálására: gRPC-hitelesítés.

gRPC szolgáltatás meghívása nem megbízható/érvénytelen tanúsítvánnyal

A .NET gRPC-ügyfél megköveteli, hogy a szolgáltatás megbízható tanúsítvánnyal rendelkezzen. A rendszer a következő hibaüzenetet adja vissza, ha megbízható tanúsítvány nélkül hív meg egy gRPC-szolgáltatást:

Kezeletlen kivétel. System.Net.Http.HttpRequestException: Az SSL-kapcsolat nem hozható létre, lásd a belső kivételt. >--- System.Security.Authentication.AuthenticationException: A távoli tanúsítvány érvénytelen az érvényesítési eljárásnak megfelelően.

Ez a hiba akkor jelenhet meg, ha helyileg teszteli az alkalmazást, és a ASP.NET Core HTTPS fejlesztési tanúsítvány nem megbízható. A probléma megoldására vonatkozó utasításokért tekintse meg a ASP.NET Core HTTPS fejlesztői tanúsítvány megbízhatóságát Windows és macOS rendszeren.

Ha egy gRPC-szolgáltatást hív meg egy másik gépen, és nem tud megbízni a tanúsítványban, akkor a gRPC-ügyfél konfigurálható úgy, hogy figyelmen kívül hagyja az érvénytelen tanúsítványt. A következő kód a megbízható tanúsítvány nélküli hívások engedélyezésére szolgál HttpClientHandler.ServerCertificateCustomValidationCallback :

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

A gRPC-ügyfél-előállító megbízható tanúsítvány nélkül engedélyezi a hívásokat. ConfigurePrimaryHttpMessageHandler A bővítménymetódus használatával konfigurálja a kezelőt az ügyfélen:

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

        return handler;
    });

Warning

A nem megbízható tanúsítványokat csak az alkalmazásfejlesztés során szabad használni. A gyártásban lévő alkalmazásoknak mindig érvényes tanúsítványokat kell használniuk.

Nem biztonságos gRPC-szolgáltatások hívása .NET-ügyféllel

A .NET gRPC-ügyfél biztonság nélküli gRPC-szolgáltatásokat hívhat meg a kiszolgáló címének http megadásával. Például: GrpcChannel.ForAddress("http://localhost:5000").

Az alkalmazás által használt .NET-verziótól függően további követelmények vonatkoznak a nem biztonságos gRPC-szolgáltatások meghívására:

  • A .NET 5 vagy újabb verziójához a Grpc.Net.Client 2.32.0-s vagy újabb verziója szükséges.

  • A .NET Core 3.x további konfigurációt igényel. Az alkalmazásnak a következőre kell beállítania a System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport kapcsolót 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);
    

A System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport kapcsoló csak a .NET Core 3.x-hez szükséges. Nem tesz semmit a .NET 5-ben, és nem szükséges.

Important

A nem biztonságos gRPC-szolgáltatásokat http/2-csak porton kell üzemeltetni. További információ: ASP.NET Core protokoll egyeztetése.

Nem indítható el ASP.NET Core gRPC-alkalmazás macOS rendszeren

Kestrel nem támogatja a HTTP/2-t a tLS-sel macOS rendszeren a .NET 8 előtt. A ASP.NET Core gRPC-sablon és -minták alapértelmezés szerint TLS-t használnak. A gRPC-kiszolgáló indításakor a következő hibaüzenet jelenik meg:

Nem lehet csatlakozni https://localhost:5001 az IPv4-visszacsatolási felületen: "A HTTP/2 TLS-en keresztül nem támogatott macOS rendszeren, mert hiányzik az ALPN-támogatás."

A probléma megoldásához a .NET 7 vagy korábbi verzióiban konfigurálja a Kestrel és a gRPC-ügyfelet a HTTP/2 TLS nélküli használatára. Ezt csak a fejlesztés során szabad elvégeznie. A TLS használatának mellőzése esetén a gRPC-üzenetek titkosítás nélkül lesznek elküldve.

Kestrel HTTP/2-végpontot kell konfigurálnia TLS nélkül a következőben 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);
});
  • Az előző kódban cserélje le a localhost portszámot 5287 a HTTP gRPC szolgáltatásprojektben HTTPS megadott (nem Properties/launchSettings.json) portszámra.

Ha egy HTTP/2-végpont TLS nélkül van konfigurálva, a végpont ListenOptions.Protokolljait a következőre HttpProtocols.Http2kell állítani: . HttpProtocols.Http1AndHttp2 nem használható, mert a HTTP/2 egyeztetéséhez TLS szükséges. TLS nélkül a végponthoz való összes kapcsolat alapértelmezés szerint HTTP/1.1, és a gRPC-hívások sikertelenek.

A gRPC-ügyfelet úgy is konfigurálnia kell, hogy ne használja a TLS-t. További információ: Nem biztonságos gRPC-szolgáltatások meghívása .NET-ügyféllel.

Warning

A HTTP/2 TLS nélkül csak az alkalmazásfejlesztés során használható. Az éles alkalmazásoknak mindig az átviteli biztonságot kell használniuk. További információkért tekintse meg a ASP.NET Core-ra vonatkozó gRPC biztonsági szempontjait.

A gRPC C#-objektumok nem fájlokból .proto generált kód

A konkrét ügyfelek és a szolgáltatásbázis-osztályok gRPC-kódgenerálásához protobuf fájlokat és eszközöket kell hivatkozni egy projektből. A következőket kell tartalmaznia:

A gRPC C#-eszközök létrehozásával kapcsolatos további információkért lásd a GRPC-szolgáltatásokat a C#-tal.

A gRPC-szolgáltatásokat üzemeltető ASP.NET Core-webalkalmazásnak csak a létrehozott alapszolgáltatás-osztályra van szüksége:

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

A gRPC-hívásokat kezdeményező gRPC-ügyfélalkalmazásnak csak a létrehozott konkrét ügyfélre van szüksége:

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

A WPF-projektek nem tudnak gRPC C#-objektumokat létrehozni fájlokból .proto

A WPF-projektek ismert problémával rendelkeznek, amely megakadályozza a gRPC-kódlétrehozást a megfelelő működésben. A WPF projektben a Grpc.Tools és .proto fájlokra való hivatkozással generált gRPC-típusok fordítási hibákat okoznak a használat során.

CS0246-os hiba: A "MyGrpcServices" típus- vagy névtérnév nem található (hiányzik egy felhasználói irányelv vagy egy szerelvényhivatkozás?)

A problémát a következő módon lehet megkerülni:

  1. Hozzon létre egy új .NET-osztálytárprojektet.
  2. Az új projektben adjon hozzá hivatkozásokat a C#-kód fájlokból való .proto létrehozásának engedélyezéséhez:
  3. A WPF-alkalmazásban adjon hozzá egy hivatkozást az új projekthez.

A WPF-alkalmazás használhatja az új osztálytárprojektből létrehozott gRPC-típusokat.

Alkönyvtárban üzemeltetett gRPC-szolgáltatások meghívása

Warning

Számos külső gRPC-eszköz nem támogatja az alkönyvtárakban üzemeltetett szolgáltatásokat. Fontolja meg a gRPC gyökérkönyvtárként való üzemeltetésének módját.

A gRPC-csatorna címének elérési útösszetevőjét a rendszer figyelmen kívül hagyja a gRPC-hívások során. Nem használható GrpcChannel.ForAddress("https://localhost:5001/ignored_path") például a ignored_path szolgáltatáshoz tartozó gRPC-hívások útválasztása során.

A cím elérési útja figyelmen kívül lesz hagyva, mert a gRPC szabványosított, előíró címstruktúrával rendelkezik. A gRPC-címek egyesítik a csomag, a szolgáltatás és a metódus nevét: https://localhost:5001/PackageName.ServiceName/MethodName.

Vannak olyan esetek, amikor egy alkalmazásnak gRPC-hívásokkal kell tartalmaznia egy elérési utat. Ha például egy ASP.NET Core gRPC-alkalmazást üzemeltetnek egy IIS-címtárban, és a címtárat bele kell foglalni a kérésbe. Ha egy elérési út szükséges, az alábbi egyéni SubdirectoryHandler beállítással adható hozzá a gRPC-híváshoz:

/// <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 a gRPC-csatorna létrehozásakor használatos.

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

Az előző kód:

  • Létrehoz egy SubdirectoryHandler a /MyApp elérési úttal.
  • Konfigurál egy csatornát a SubdirectoryHandler használatára.
  • Meghívja a gRPC szolgáltatást a következővel SayHelloAsync: . A gRPC-hívást a rendszer elküldi a következőnek https://localhost:5001/MyApp/greet.Greeter/SayHello: .

Másik lehetőségként egy ügyfél gyártói is konfigurálható SubdirectoryHandlerAddHttpMessageHandler használatával.

A gRPC-ügyfél konfigurálása HTTP/3 használatára

A .NET gRPC-ügyfél támogatja a HTTP/3-at a .NET 6-os vagy újabb verziójával. Ha a kiszolgáló egy válaszfejlécet alt-svc küld az ügyfélnek, amely azt jelzi, hogy a kiszolgáló támogatja a HTTP/3-at, az ügyfél automatikusan http/3-ra frissíti a kapcsolatot. A HTTP/3 kiszolgálón való engedélyezéséről további információt a HTTP/3 használata a ASP.NET Core Kestrel webkiszolgálóval című témakörben talál.

A .NET 8 HTTP/3 támogatása alapértelmezés szerint engedélyezve van. A .NET 6 és a .NET 7 HTTP/3 támogatását a projektfájlban található konfigurációs jelzővel kell engedélyezni:

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

System.Net.SocketsHttpHandler.Http3Support AppContext.SetSwitch használatával is beállítható.

Az A DelegatingHandler használatával kényszerítheti a gRPC-ügyfelet a HTTP/3 használatára. A HTTP/3 kényszerítése elkerüli a kérés frissítésének többletterhelését. A HTTP/3 kényszerítése a következőhöz hasonló kóddal:

/// <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 a gRPC-csatorna létrehozásakor használatos. Az alábbi kód egy olyan csatornát hoz létre, amely Http3Handler használatára van konfigurálva.

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

Másik lehetőségként egy ügyfél gyártói is konfigurálható Http3HandlerAddHttpMessageHandler használatával.

GRPC létrehozása Alpine Linuxon

A Grpc.Tools csomag .NET-típusokat hoz létre a .proto fájlokból egy kötegelt natív bináris, nevű protoc. További lépések szükségesek a gRPC-alkalmazások olyan platformokon való létrehozásához, amelyeket a natív bináris fájlok nem támogatnak, például az Alpine Linuxban Grpc.Tools.

Kód létrehozása előre

Az egyik megoldás a kód idő előtti létrehozása.

  1. Helyezze át a .proto fájlokat és a Grpc.Tools csomaghivatkozást egy új projektbe.
  2. Tegye közzé a projektet NuGet-csomagként, és töltse fel egy NuGet-hírcsatornába.
  3. Frissítse az alkalmazást a NuGet-csomagra való hivatkozáshoz.

Az előző lépésekkel az alkalmazásnak már nem kell buildelést végrehajtania Grpc.Tools , mert a kód előre létrejön.

Natív bináris fájlok testreszabása Grpc.Tools

Grpc.Tools támogatja az egyéni natív bináris fájlok használatát. Ez a funkció lehetővé teszi, hogy a gRPC-eszközök olyan környezetekben fussanak, amelyben a natív bináris fájlok kötegei nem támogatottak.

Készítse el vagy szerezze be a protoc és grpc_csharp_plugin natív binárisokat, és konfigurálja a Grpc.Tools azok használatára. Konfigurálja a natív bináris fájlokat a következő környezeti változók beállításával:

  • PROTOBUF_PROTOC - A protokollpufferek fordítójának teljes elérési útja
  • GRPC_PROTOC_PLUGIN - A grpc_csharp_plugin teljes elérési útja

Az Alpine Linux esetében a közösség biztosít csomagokat a protokollpufferek fordítójához és a gRPC beépülő modulokhoz a következő helyen: 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

A nem támogatott architektúrák használatával Grpc.Tools kapcsolatos további információkért tekintse meg a gRPC buildintegrációs dokumentációját.

gRPC-hívás időtúllépése innen: HttpClient.Timeout

HttpClient alapértelmezés szerint 100 másodperces időtúllépéssel van konfigurálva. Ha a GrpcChannel úgy van konfigurálva, hogy egy HttpClient-et használjon, a hosszú ideig futó gRPC-streamhívásokat megszakítják, ha nem fejeződnek be az időkorláton belül.

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

Ezt a hibát többféleképpen is kijavíthatja. Az első lépés HttpClient.Timeout nagyobb értékre való konfigurálása. Timeout.InfiniteTimeSpan kikapcsolja az időkorlátot.

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

Másik lehetőségként kerülje HttpClient létrehozását és helyette állítsa be GrpcChannel.HttpHandler-et.

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

Ez a dokumentum a gRPC-alkalmazások .NET-en való fejlesztése során gyakran előforduló problémákat ismerteti.

Eltérés az ügyfél és a szolgáltatás SSL-/TLS-konfigurációja között

A gRPC-sablon és -minták a Transport Layer Security (TLS) használatával biztosítják alapértelmezés szerint a gRPC-szolgáltatásokat. A gRPC-ügyfeleknek biztonságos kapcsolatot kell használniuk a biztonságos gRPC-szolgáltatások sikeres meghívásához.

Ellenőrizheti, hogy a ASP.NET Core gRPC szolgáltatás TLS-t használ-e az alkalmazás indításakor írt naplókban. A szolgáltatás egy HTTPS-végpontot figyel:

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

A .NET-ügyfélnek a kiszolgáló címében kell használnia https a hívások biztonságos kapcsolattal való indításához:

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

Minden gRPC-ügyfél-implementáció támogatja a TLS-t. A más nyelvekről származó gRPC-ügyfelek általában megkövetelik a csatorna konfigurálását SslCredentials. SslCredentials Meghatározza az ügyfél által használandó tanúsítványt, és azt a nem biztonságos hitelesítő adatok helyett kell használni. Példák a különböző gRPC-ügyfél-implementációk TLS használatára való konfigurálására: gRPC-hitelesítés.

gRPC szolgáltatás meghívása nem megbízható/érvénytelen tanúsítvánnyal

A .NET gRPC-ügyfél megköveteli, hogy a szolgáltatás megbízható tanúsítvánnyal rendelkezzen. A rendszer a következő hibaüzenetet adja vissza, ha megbízható tanúsítvány nélkül hív meg egy gRPC-szolgáltatást:

Kezeletlen kivétel. System.Net.Http.HttpRequestException: Az SSL-kapcsolat nem hozható létre, lásd a belső kivételt. >--- System.Security.Authentication.AuthenticationException: A távoli tanúsítvány érvénytelen az érvényesítési eljárásnak megfelelően.

Ez a hiba akkor jelenhet meg, ha helyileg teszteli az alkalmazást, és a ASP.NET Core HTTPS fejlesztési tanúsítvány nem megbízható. A probléma megoldására vonatkozó utasításokért tekintse meg a ASP.NET Core HTTPS fejlesztői tanúsítvány megbízhatóságát Windows és macOS rendszeren.

Ha egy gRPC-szolgáltatást hív meg egy másik gépen, és nem tud megbízni a tanúsítványban, akkor a gRPC-ügyfél konfigurálható úgy, hogy figyelmen kívül hagyja az érvénytelen tanúsítványt. A következő kód a megbízható tanúsítvány nélküli hívások engedélyezésére szolgál HttpClientHandler.ServerCertificateCustomValidationCallback :

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

A gRPC-ügyfél-előállító megbízható tanúsítvány nélkül engedélyezi a hívásokat. ConfigurePrimaryHttpMessageHandler A bővítménymetódus használatával konfigurálja a kezelőt az ügyfélen:

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

        return handler;
    });

Warning

A nem megbízható tanúsítványokat csak az alkalmazásfejlesztés során szabad használni. A gyártásban lévő alkalmazásoknak mindig érvényes tanúsítványokat kell használniuk.

Nem biztonságos gRPC-szolgáltatások hívása .NET-ügyféllel

A .NET gRPC-ügyfél biztonság nélküli gRPC-szolgáltatásokat hívhat meg a kiszolgáló címének http megadásával. Például: GrpcChannel.ForAddress("http://localhost:5000").

Az alkalmazás által használt .NET-verziótól függően további követelmények vonatkoznak a nem biztonságos gRPC-szolgáltatások meghívására:

  • A .NET 5 vagy újabb verziójához a Grpc.Net.Client 2.32.0-s vagy újabb verziója szükséges.

  • A .NET Core 3.x további konfigurációt igényel. Az alkalmazásnak a következőre kell beállítania a System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport kapcsolót 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);
    

A System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport kapcsoló csak a .NET Core 3.x-hez szükséges. Nem tesz semmit a .NET 5-ben, és nem szükséges.

Important

A nem biztonságos gRPC-szolgáltatásokat http/2-csak porton kell üzemeltetni. További információ: ASP.NET Core protokoll egyeztetése.

Nem indítható el ASP.NET Core gRPC-alkalmazás macOS rendszeren

Kestrel nem támogatja a HTTP/2-t a tLS-sel macOS rendszeren a .NET 8 előtt. A ASP.NET Core gRPC-sablon és -minták alapértelmezés szerint TLS-t használnak. A gRPC-kiszolgáló indításakor a következő hibaüzenet jelenik meg:

Nem lehet csatlakozni https://localhost:5001 az IPv4-visszacsatolási felületen: "A HTTP/2 TLS-en keresztül nem támogatott macOS rendszeren, mert hiányzik az ALPN-támogatás."

A probléma megoldásához a .NET 7 vagy korábbi verzióiban konfigurálja a Kestrel és a gRPC-ügyfelet a HTTP/2 TLS nélküli használatára. Ezt csak a fejlesztés során szabad elvégeznie. A TLS használatának mellőzése esetén a gRPC-üzenetek titkosítás nélkül lesznek elküldve.

Kestrel HTTP/2-végpontot kell konfigurálnia TLS nélkül a következőben 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>();
        });

Ha egy HTTP/2-végpont TLS nélkül van konfigurálva, a végpont ListenOptions.Protokolljait a következőre HttpProtocols.Http2kell állítani: . HttpProtocols.Http1AndHttp2 nem használható, mert a HTTP/2 egyeztetéséhez TLS szükséges. TLS nélkül a végponthoz való összes kapcsolat alapértelmezés szerint HTTP/1.1, és a gRPC-hívások sikertelenek.

A gRPC-ügyfelet úgy is konfigurálnia kell, hogy ne használja a TLS-t. További információ: Nem biztonságos gRPC-szolgáltatások meghívása .NET-ügyféllel.

Warning

A HTTP/2 TLS nélkül csak az alkalmazásfejlesztés során használható. Az éles alkalmazásoknak mindig az átviteli biztonságot kell használniuk. További információkért tekintse meg a ASP.NET Core-ra vonatkozó gRPC biztonsági szempontjait.

A gRPC C#-objektumok nem fájlokból .proto generált kód

A konkrét ügyfelek és a szolgáltatásbázis-osztályok gRPC-kódgenerálásához protobuf fájlokat és eszközöket kell hivatkozni egy projektből. A következőket kell tartalmaznia:

A gRPC C#-eszközök létrehozásával kapcsolatos további információkért lásd a GRPC-szolgáltatásokat a C#-tal.

A gRPC-szolgáltatásokat üzemeltető ASP.NET Core-webalkalmazásnak csak a létrehozott alapszolgáltatás-osztályra van szüksége:

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

A gRPC-hívásokat kezdeményező gRPC-ügyfélalkalmazásnak csak a létrehozott konkrét ügyfélre van szüksége:

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

A WPF-projektek nem tudnak gRPC C#-objektumokat létrehozni fájlokból .proto

A WPF-projektek ismert problémával rendelkeznek, amely megakadályozza a gRPC-kódlétrehozást a megfelelő működésben. A WPF projektben a Grpc.Tools és .proto fájlokra való hivatkozással generált gRPC-típusok fordítási hibákat okoznak a használat során.

CS0246-os hiba: A "MyGrpcServices" típus- vagy névtérnév nem található (hiányzik egy felhasználói irányelv vagy egy szerelvényhivatkozás?)

A problémát a következő módon lehet megkerülni:

  1. Hozzon létre egy új .NET-osztálytárprojektet.
  2. Az új projektben adjon hozzá hivatkozásokat a C#-kód fájlokból való .proto létrehozásának engedélyezéséhez:
  3. A WPF-alkalmazásban adjon hozzá egy hivatkozást az új projekthez.

A WPF-alkalmazás használhatja az új osztálytárprojektből létrehozott gRPC-típusokat.

Alkönyvtárban üzemeltetett gRPC-szolgáltatások meghívása

Warning

Számos külső gRPC-eszköz nem támogatja az alkönyvtárakban üzemeltetett szolgáltatásokat. Fontolja meg a gRPC gyökérkönyvtárként való üzemeltetésének módját.

A gRPC-csatorna címének elérési útösszetevőjét a rendszer figyelmen kívül hagyja a gRPC-hívások során. Nem használható GrpcChannel.ForAddress("https://localhost:5001/ignored_path") például a ignored_path szolgáltatáshoz tartozó gRPC-hívások útválasztása során.

A cím elérési útja figyelmen kívül lesz hagyva, mert a gRPC szabványosított, előíró címstruktúrával rendelkezik. A gRPC-címek egyesítik a csomag, a szolgáltatás és a metódus nevét: https://localhost:5001/PackageName.ServiceName/MethodName.

Vannak olyan esetek, amikor egy alkalmazásnak gRPC-hívásokkal kell tartalmaznia egy elérési utat. Ha például egy ASP.NET Core gRPC-alkalmazást üzemeltetnek egy IIS-címtárban, és a címtárat bele kell foglalni a kérésbe. Ha egy elérési út szükséges, az alábbi egyéni SubdirectoryHandler beállítással adható hozzá a gRPC-híváshoz:

/// <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 a gRPC-csatorna létrehozásakor használatos.

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

Az előző kód:

  • Létrehoz egy SubdirectoryHandler a /MyApp elérési úttal.
  • Konfigurál egy csatornát a SubdirectoryHandler használatára.
  • Meghívja a gRPC szolgáltatást a következővel SayHelloAsync: . A gRPC-hívást a rendszer elküldi a következőnek https://localhost:5001/MyApp/greet.Greeter/SayHello: .

Másik lehetőségként egy ügyfél gyártói is konfigurálható SubdirectoryHandlerAddHttpMessageHandler használatával.

gRPC-hívás időtúllépése innen: HttpClient.Timeout

HttpClient alapértelmezés szerint 100 másodperces időtúllépéssel van konfigurálva. Ha a GrpcChannel úgy van konfigurálva, hogy egy HttpClient-et használjon, a hosszú ideig futó gRPC-streamhívásokat megszakítják, ha nem fejeződnek be az időkorláton belül.

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

Ezt a hibát többféleképpen is kijavíthatja. Az első lépés HttpClient.Timeout nagyobb értékre való konfigurálása. Timeout.InfiniteTimeSpan kikapcsolja az időkorlátot.

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

Másik lehetőségként kerülje HttpClient létrehozását és helyette állítsa be GrpcChannel.HttpHandler-et.

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

Ez a dokumentum a gRPC-alkalmazások .NET-en való fejlesztése során gyakran előforduló problémákat ismerteti.

Eltérés az ügyfél és a szolgáltatás SSL-/TLS-konfigurációja között

A gRPC-sablon és -minták a Transport Layer Security (TLS) használatával biztosítják alapértelmezés szerint a gRPC-szolgáltatásokat. A gRPC-ügyfeleknek biztonságos kapcsolatot kell használniuk a biztonságos gRPC-szolgáltatások sikeres meghívásához.

Ellenőrizheti, hogy a ASP.NET Core gRPC szolgáltatás TLS-t használ-e az alkalmazás indításakor írt naplókban. A szolgáltatás egy HTTPS-végpontot figyel:

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

A .NET-ügyfélnek a kiszolgáló címében kell használnia https a hívások biztonságos kapcsolattal való indításához:

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

Minden gRPC-ügyfél-implementáció támogatja a TLS-t. A más nyelvekről származó gRPC-ügyfelek általában megkövetelik a csatorna konfigurálását SslCredentials. SslCredentials Meghatározza az ügyfél által használandó tanúsítványt, és azt a nem biztonságos hitelesítő adatok helyett kell használni. Példák a különböző gRPC-ügyfél-implementációk TLS használatára való konfigurálására: gRPC-hitelesítés.

gRPC szolgáltatás meghívása nem megbízható/érvénytelen tanúsítvánnyal

A .NET gRPC-ügyfél megköveteli, hogy a szolgáltatás megbízható tanúsítvánnyal rendelkezzen. A rendszer a következő hibaüzenetet adja vissza, ha megbízható tanúsítvány nélkül hív meg egy gRPC-szolgáltatást:

Kezeletlen kivétel. System.Net.Http.HttpRequestException: Az SSL-kapcsolat nem hozható létre, lásd a belső kivételt. >--- System.Security.Authentication.AuthenticationException: A távoli tanúsítvány érvénytelen az érvényesítési eljárásnak megfelelően.

Ez a hiba akkor jelenhet meg, ha helyileg teszteli az alkalmazást, és a ASP.NET Core HTTPS fejlesztési tanúsítvány nem megbízható. A probléma megoldására vonatkozó utasításokért tekintse meg a ASP.NET Core HTTPS fejlesztői tanúsítvány megbízhatóságát Windows és macOS rendszeren.

Ha egy gRPC-szolgáltatást hív meg egy másik gépen, és nem tud megbízni a tanúsítványban, akkor a gRPC-ügyfél konfigurálható úgy, hogy figyelmen kívül hagyja az érvénytelen tanúsítványt. A következő kód a megbízható tanúsítvány nélküli hívások engedélyezésére szolgál HttpClientHandler.ServerCertificateCustomValidationCallback :

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

A gRPC-ügyfél-előállító megbízható tanúsítvány nélkül engedélyezi a hívásokat. ConfigurePrimaryHttpMessageHandler A bővítménymetódus használatával konfigurálja a kezelőt az ügyfélen:

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

        return handler;
    });

Warning

A nem megbízható tanúsítványokat csak az alkalmazásfejlesztés során szabad használni. A gyártásban lévő alkalmazásoknak mindig érvényes tanúsítványokat kell használniuk.

Nem biztonságos gRPC-szolgáltatások hívása .NET-ügyféllel

A .NET gRPC-ügyfél biztonság nélküli gRPC-szolgáltatásokat hívhat meg a kiszolgáló címének http megadásával. Például: GrpcChannel.ForAddress("http://localhost:5000").

Az alkalmazás által használt .NET-verziótól függően további követelmények vonatkoznak a nem biztonságos gRPC-szolgáltatások meghívására:

  • A .NET 5 vagy újabb verziójához a Grpc.Net.Client 2.32.0-s vagy újabb verziója szükséges.

  • A .NET Core 3.x további konfigurációt igényel. Az alkalmazásnak a következőre kell beállítania a System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport kapcsolót 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);
    

A System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport kapcsoló csak a .NET Core 3.x-hez szükséges. Nem tesz semmit a .NET 5-ben, és nem szükséges.

Important

A nem biztonságos gRPC-szolgáltatásokat http/2-csak porton kell üzemeltetni. További információ: ASP.NET Core protokoll egyeztetése.

Nem indítható el ASP.NET Core gRPC-alkalmazás macOS rendszeren

Kestrel nem támogatja a HTTP/2-t a tLS-sel macOS rendszeren a .NET 8 előtt. A ASP.NET Core gRPC-sablon és -minták alapértelmezés szerint TLS-t használnak. A gRPC-kiszolgáló indításakor a következő hibaüzenet jelenik meg:

Nem lehet csatlakozni https://localhost:5001 az IPv4-visszacsatolási felületen: "A HTTP/2 TLS-en keresztül nem támogatott macOS rendszeren, mert hiányzik az ALPN-támogatás."

A probléma megoldásához a .NET 7 vagy korábbi verzióiban konfigurálja a Kestrel és a gRPC-ügyfelet a HTTP/2 TLS nélküli használatára. Ezt csak a fejlesztés során szabad elvégeznie. A TLS használatának mellőzése esetén a gRPC-üzenetek titkosítás nélkül lesznek elküldve.

Kestrel HTTP/2-végpontot kell konfigurálnia TLS nélkül a következőben 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>();
        });

Ha egy HTTP/2-végpont TLS nélkül van konfigurálva, a végpont ListenOptions.Protokolljait a következőre HttpProtocols.Http2kell állítani: . HttpProtocols.Http1AndHttp2 nem használható, mert a HTTP/2 egyeztetéséhez TLS szükséges. TLS nélkül a végponthoz való összes kapcsolat alapértelmezés szerint HTTP/1.1, és a gRPC-hívások sikertelenek.

A gRPC-ügyfelet úgy is konfigurálnia kell, hogy ne használja a TLS-t. További információ: Nem biztonságos gRPC-szolgáltatások meghívása .NET-ügyféllel.

Warning

A HTTP/2 TLS nélkül csak az alkalmazásfejlesztés során használható. Az éles alkalmazásoknak mindig az átviteli biztonságot kell használniuk. További információkért tekintse meg a ASP.NET Core-ra vonatkozó gRPC biztonsági szempontjait.

A gRPC C#-objektumok nem fájlokból .proto generált kód

A konkrét ügyfelek és a szolgáltatásbázis-osztályok gRPC-kódgenerálásához protobuf fájlokat és eszközöket kell hivatkozni egy projektből. A következőket kell tartalmaznia:

A gRPC C#-eszközök létrehozásával kapcsolatos további információkért lásd a GRPC-szolgáltatásokat a C#-tal.

A gRPC-szolgáltatásokat üzemeltető ASP.NET Core-webalkalmazásnak csak a létrehozott alapszolgáltatás-osztályra van szüksége:

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

A gRPC-hívásokat kezdeményező gRPC-ügyfélalkalmazásnak csak a létrehozott konkrét ügyfélre van szüksége:

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

A WPF-projektek nem tudnak gRPC C#-objektumokat létrehozni fájlokból .proto

A WPF-projektek ismert problémával rendelkeznek, amely megakadályozza a gRPC-kódlétrehozást a megfelelő működésben. A WPF projektben a Grpc.Tools és .proto fájlokra való hivatkozással generált gRPC-típusok fordítási hibákat okoznak a használat során.

CS0246-os hiba: A "MyGrpcServices" típus- vagy névtérnév nem található (hiányzik egy felhasználói irányelv vagy egy szerelvényhivatkozás?)

A problémát a következő módon lehet megkerülni:

  1. Hozzon létre egy új .NET-osztálytárprojektet.
  2. Az új projektben adjon hozzá hivatkozásokat a C#-kód fájlokból való .proto létrehozásának engedélyezéséhez:
  3. A WPF-alkalmazásban adjon hozzá egy hivatkozást az új projekthez.

A WPF-alkalmazás használhatja az új osztálytárprojektből létrehozott gRPC-típusokat.

Alkönyvtárban üzemeltetett gRPC-szolgáltatások meghívása

Warning

Számos külső gRPC-eszköz nem támogatja az alkönyvtárakban üzemeltetett szolgáltatásokat. Fontolja meg a gRPC gyökérkönyvtárként való üzemeltetésének módját.

A gRPC-csatorna címének elérési útösszetevőjét a rendszer figyelmen kívül hagyja a gRPC-hívások során. Nem használható GrpcChannel.ForAddress("https://localhost:5001/ignored_path") például a ignored_path szolgáltatáshoz tartozó gRPC-hívások útválasztása során.

A cím elérési útja figyelmen kívül lesz hagyva, mert a gRPC szabványosított, előíró címstruktúrával rendelkezik. A gRPC-címek egyesítik a csomag, a szolgáltatás és a metódus nevét: https://localhost:5001/PackageName.ServiceName/MethodName.

Vannak olyan esetek, amikor egy alkalmazásnak gRPC-hívásokkal kell tartalmaznia egy elérési utat. Ha például egy ASP.NET Core gRPC-alkalmazást üzemeltetnek egy IIS-címtárban, és a címtárat bele kell foglalni a kérésbe. Ha egy elérési út szükséges, az alábbi egyéni SubdirectoryHandler beállítással adható hozzá a gRPC-híváshoz:

/// <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 a gRPC-csatorna létrehozásakor használatos.

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

Az előző kód:

  • Létrehoz egy SubdirectoryHandler a /MyApp elérési úttal.
  • Konfigurál egy csatornát a SubdirectoryHandler használatára.
  • Meghívja a gRPC szolgáltatást a következővel SayHelloAsync: . A gRPC-hívást a rendszer elküldi a következőnek https://localhost:5001/MyApp/greet.Greeter/SayHello: .

Másik lehetőségként egy ügyfél gyártói is konfigurálható SubdirectoryHandlerAddHttpMessageHandler használatával.

gRPC-hívás időtúllépése innen: HttpClient.Timeout

HttpClient alapértelmezés szerint 100 másodperces időtúllépéssel van konfigurálva. Ha a GrpcChannel úgy van konfigurálva, hogy egy HttpClient-et használjon, a hosszú ideig futó gRPC-streamhívásokat megszakítják, ha nem fejeződnek be az időkorláton belül.

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

Ezt a hibát többféleképpen is kijavíthatja. Az első lépés HttpClient.Timeout nagyobb értékre való konfigurálása. Timeout.InfiniteTimeSpan kikapcsolja az időkorlátot.

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

Másik lehetőségként kerülje HttpClient létrehozását és helyette állítsa be GrpcChannel.HttpHandler-et.

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