Memecahkan masalah gRPC pada .NET

Oleh James Newton-King

Catatan

Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.

Penting

Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.

Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.

Dokumen ini membahas masalah yang umumnya dihadapi saat mengembangkan aplikasi gRPC di .NET.

Ketidakcocokan antara konfigurasi SSL/TLS klien dan layanan

Templat dan sampel gRPC menggunakan Keamanan Lapisan Transportasi (TLS) untuk mengamankan layanan gRPC secara default. Klien gRPC perlu menggunakan koneksi aman untuk memanggil layanan gRPC aman dengan sukses.

Anda dapat memverifikasi layanan gRPC ASP.NET Core menggunakan TLS dalam log yang ditulis pada awal aplikasi. Layanan ini akan mendengarkan di titik akhir 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

Klien .NET Core harus menggunakan https alamat server untuk melakukan panggilan dengan koneksi aman:

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

Semua implementasi klien gRPC mendukung TLS. Klien gRPC dari bahasa lain biasanya memerlukan saluran yang dikonfigurasi dengan SslCredentials. SslCredentials menentukan sertifikat yang akan digunakan klien, dan harus digunakan alih-alih kredensial yang tidak aman. Untuk contoh mengonfigurasi berbagai implementasi klien gRPC untuk menggunakan TLS, lihat Autentikasi gRPC.

Memanggil layanan gRPC dengan sertifikat yang tidak tepercaya/tidak valid

Klien .NET gRPC mengharuskan layanan memiliki sertifikat tepercaya. Pesan kesalahan berikut dikembalikan saat memanggil layanan gRPC tanpa sertifikat tepercaya:

Pengecualian tidak dapat ditangani. System.Net.Http.HttpRequestException: Koneksi SSL tidak dapat dibuat, lihat pengecualian dalam. >--- System.Security.Authentication.AuthenticationException: Sertifikat jarak jauh tidak valid sesuai dengan prosedur validasi.

Anda mungkin melihat kesalahan ini jika menguji aplikasi secara lokal dan sertifikat pengembangan ASP.NET Core HTTPS tidak tepercaya. Untuk instruksi untuk memperbaiki masalah ini, lihat Mempercayai sertifikat pengembangan ASP.NET Core HTTPS di Windows dan macOS.

Jika Anda memanggil layanan gRPC di komputer lain dan tidak dapat mempercayai sertifikat, maka klien gRPC dapat dikonfigurasi untuk mengabaikan sertifikat yang tidak valid. Kode berikut menggunakan HttpClientHandler.ServerCertificateCustomValidationCallback untuk mengizinkan panggilan tanpa sertifikat tepercaya:

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

Pabrik klien gRPC memungkinkan panggilan tanpa sertifikat tepercaya. ConfigurePrimaryHttpMessageHandler Gunakan metode ekstensi untuk mengonfigurasi handler pada klien:


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

Peringatan

Sertifikat yang tidak tepercaya hanya boleh digunakan selama pengembangan aplikasi. Aplikasi produksi harus selalu menggunakan sertifikat yang valid.

Memanggil layanan gRPC yang tidak aman dengan klien .NET Core

Klien .NET gRPC dapat memanggil layanan gRPC yang tidak aman dengan menspesifikasikan http di alamat server. Contohnya,GrpcChannel.ForAddress("http://localhost:5000").

Ada beberapa persyaratan tambahan untuk memanggil layanan gRPC yang tidak aman tergantung pada versi .NET yang digunakan aplikasi:

Penting

Layanan gRPC yang tidak aman harus dihosting pada port HTTP/2-saja. Untuk informasi selengkapnya, lihat negosiasi protokol ASP.NET Core.

Tidak dapat memulai aplikasi gRPC ASP.NET Core di macOS

Kestrel tidak mendukung HTTP/2 dengan TLS di macOS sebelum .NET 8. Templat dan sampel gRPC ASP.NET Core menggunakan TLS secara default. Anda akan melihat pesan kesalahan berikut saat mencoba memulai server gRPC:

Tidak dapat mengikat ke https://localhost:5001 pada antarmuka loopback IPv4: 'HTTP/2 melalui TLS tidak didukung di macOS karena dukungan ALPN yang hilang.'.

Untuk mengatasi masalah ini di .NET 7 dan yang lebih lama, konfigurasikan Kestrel dan klien gRPC untuk menggunakan HTTP/2 tanpa TLS. Anda hanya boleh melakukan ini selama pengembangan. Tidak menggunakan TLS akan mengakibatkan pesan gRPC dikirim tanpa enkripsi. Untuk informasi selengkapnya, lihat Asp.Net Core 7.0: Tidak dapat memulai aplikasi gRPC ASP.NET Core di macOS.

aset c# gRPC bukan kode yang dihasilkan dari .proto file

Pembuatan kode gRPC klien konkret dan kelas dasar layanan memerlukan file protobuf dan alat untuk dirujuk dari proyek. Anda harus menyertakan:

  • .proto file yang ingin Anda gunakan dalam <Protobuf> grup item. File yang diimpor .proto harus direferensikan oleh proyek.
  • Referensi paket ke paket peralatan gRPC Grpc.Tools.

Untuk informasi selengkapnya tentang menghasilkan aset C# gRPC, lihat layanan gRPC dengan C#.

Aplikasi web ASP.NET Core yang menghosting layanan gRPC hanya memerlukan kelas dasar layanan yang dihasilkan:

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

Aplikasi klien gRPC yang melakukan panggilan gRPC hanya memerlukan klien konkret yang dihasilkan:

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

Proyek WPF tidak dapat menghasilkan aset C# gRPC dari .proto file

Proyek WPF memiliki masalah umum yang mencegah pembuatan kode gRPC bekerja dengan benar. Setiap jenis gRPC yang dihasilkan dalam proyek WPF dengan mereferensikan Grpc.Tools dan .proto file akan membuat kesalahan kompilasi saat digunakan:

kesalahan CS0246: Jenis atau nama namespace layanan 'MyGrpcServices' tidak dapat ditemukan (apakah Anda kehilangan menggunakan direktif atau referensi perakitan?)

Anda dapat mengatasi masalah ini dengan:

  1. Buat proyek pustaka kelas .NET Core baru.
  2. Dalam proyek baru, tambahkan referensi untuk mengaktifkan pembuatan kode C# dari .proto file:
  3. Di aplikasi WPF, tambahkan referensi ke proyek baru.

Aplikasi WPF dapat menggunakan jenis yang dihasilkan gRPC dari proyek pustaka kelas baru.

Memanggil layanan gRPC yang dihosting di sub-direktori

Peringatan

Banyak alat gRPC pihak ketiga tidak mendukung layanan yang dihosting di subdirektori. Pertimbangkan untuk menemukan cara untuk menghosting gRPC sebagai direktori akar.

Komponen jalur alamat saluran gRPC diabaikan saat melakukan panggilan gRPC. Misalnya, GrpcChannel.ForAddress("https://localhost:5001/ignored_path") tidak akan digunakan ignored_path saat merutekan panggilan gRPC untuk layanan.

Jalur alamat diabaikan karena gRPC memiliki struktur alamat preskriptif standar. Alamat gRPC menggabungkan nama paket, layanan, dan metode: https://localhost:5001/PackageName.ServiceName/MethodName.

Ada beberapa skenario saat aplikasi perlu menyertakan jalur dengan panggilan gRPC. Misalnya, ketika aplikasi gRPC ASP.NET Core dihosting di direktori IIS dan direktori perlu disertakan dalam permintaan. Ketika jalur diperlukan, jalur dapat ditambahkan ke panggilan gRPC menggunakan kustom SubdirectoryHandler yang ditentukan di bawah ini:

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 digunakan saat saluran gRPC dibuat.

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

Kode sebelumnya:

  • SubdirectoryHandler Membuat dengan jalur /MyApp.
  • Mengonfigurasi saluran untuk menggunakan SubdirectoryHandler.
  • Memanggil layanan gRPC dengan SayHelloAsync. Panggilan gRPC dikirim ke https://localhost:5001/MyApp/greet.Greeter/SayHello.

Atau, pabrik klien dapat dikonfigurasi dengan menggunakan SubdirectoryHandlerAddHttpMessageHandler.

Mengonfigurasi klien gRPC untuk menggunakan HTTP/3

Klien .NET gRPC mendukung HTTP/3 dengan .NET 6 atau yang lebih baru. Jika server mengirim alt-svc header respons ke klien yang menunjukkan server mendukung HTTP/3, klien akan secara otomatis meningkatkan koneksinya ke HTTP/3. Untuk informasi selengkapnya, lihat Menggunakan HTTP/3 dengan server web ASP.NET CoreKestrel.

DelegatingHandler Dapat digunakan untuk memaksa klien gRPC menggunakan HTTP/3. Memaksa HTTP/3 menghindari overhead peningkatan permintaan. Paksa HTTP/3 dengan kode yang mirip dengan yang berikut ini:

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 digunakan saat saluran gRPC dibuat. Kode berikut membuat saluran yang dikonfigurasi untuk menggunakan 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" });

Atau, pabrik klien dapat dikonfigurasi dengan menggunakan Http3HandlerAddHttpMessageHandler.

Membangun gRPC di Alpine Linux

Paket menghasilkan jenis .NET dari .proto file menggunakan biner asli yang dibundel yang disebut protoc.Grpc.Tools Langkah tambahan diperlukan untuk membangun aplikasi gRPC pada platform yang tidak didukung oleh biner asli di Grpc.Tools, seperti Alpine Linux.

Buat kode sebelumnya

Salah satu solusinya adalah menghasilkan kode sebelumnya.

  1. Pindahkan .proto file dan Grpc.Tools referensi paket ke proyek baru.
  2. Terbitkan proyek sebagai paket NuGet dan unggah ke umpan NuGet.
  3. Perbarui aplikasi untuk mereferensikan paket NuGet.

Dengan langkah-langkah sebelumnya, aplikasi tidak lagi perlu Grpc.Tools dibuat karena kode dihasilkan sebelumnya.

Menyesuaikan Grpc.Tools biner asli

Grpc.Tools mendukung penggunaan biner asli kustom. Fitur ini memungkinkan alat gRPC berjalan di lingkungan yang tidak didukung biner asli bundelnya.

Bangun atau peroleh protoc biner asli dan grpc_csharp_plugin konfigurasikan Grpc.Tools untuk menggunakannya. Konfigurasikan biner asli dengan mengatur variabel lingkungan berikut:

  • PROTOBUF_PROTOC - Jalur lengkap ke pengkompilasi buffer protokol
  • GRPC_PROTOC_PLUGIN - Jalur lengkap ke grpc_csharp_plugin

Untuk Alpine Linux, ada paket yang disediakan komunitas untuk kompiler buffer protokol dan plugin gRPC di https://pkgs.alpinelinux.org/.

# Build or install the binaries for your architecture.

# e.g. 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

Untuk informasi selengkapnya tentang penggunaan Grpc.Tools dengan arsitektur yang tidak didukung, lihat dokumentasi integrasi build gRPC.

Dokumen ini membahas masalah yang umumnya dihadapi saat mengembangkan aplikasi gRPC di .NET.

Ketidakcocokan antara konfigurasi SSL/TLS klien dan layanan

Templat dan sampel gRPC menggunakan Keamanan Lapisan Transportasi (TLS) untuk mengamankan layanan gRPC secara default. Klien gRPC perlu menggunakan koneksi aman untuk memanggil layanan gRPC aman dengan sukses.

Anda dapat memverifikasi layanan gRPC ASP.NET Core menggunakan TLS dalam log yang ditulis pada awal aplikasi. Layanan ini akan mendengarkan di titik akhir 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

Klien .NET Core harus menggunakan https alamat server untuk melakukan panggilan dengan koneksi aman:

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

Semua implementasi klien gRPC mendukung TLS. Klien gRPC dari bahasa lain biasanya memerlukan saluran yang dikonfigurasi dengan SslCredentials. SslCredentials menentukan sertifikat yang akan digunakan klien, dan harus digunakan alih-alih kredensial yang tidak aman. Untuk contoh mengonfigurasi berbagai implementasi klien gRPC untuk menggunakan TLS, lihat Autentikasi gRPC.

Memanggil layanan gRPC dengan sertifikat yang tidak tepercaya/tidak valid

Klien .NET gRPC mengharuskan layanan memiliki sertifikat tepercaya. Pesan kesalahan berikut dikembalikan saat memanggil layanan gRPC tanpa sertifikat tepercaya:

Pengecualian tidak dapat ditangani. System.Net.Http.HttpRequestException: Koneksi SSL tidak dapat dibuat, lihat pengecualian dalam. >--- System.Security.Authentication.AuthenticationException: Sertifikat jarak jauh tidak valid sesuai dengan prosedur validasi.

Anda mungkin melihat kesalahan ini jika menguji aplikasi secara lokal dan sertifikat pengembangan ASP.NET Core HTTPS tidak tepercaya. Untuk instruksi untuk memperbaiki masalah ini, lihat Mempercayai sertifikat pengembangan ASP.NET Core HTTPS di Windows dan macOS.

Jika Anda memanggil layanan gRPC di komputer lain dan tidak dapat mempercayai sertifikat, maka klien gRPC dapat dikonfigurasi untuk mengabaikan sertifikat yang tidak valid. Kode berikut menggunakan HttpClientHandler.ServerCertificateCustomValidationCallback untuk mengizinkan panggilan tanpa sertifikat tepercaya:

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

Pabrik klien gRPC memungkinkan panggilan tanpa sertifikat tepercaya. ConfigurePrimaryHttpMessageHandler Gunakan metode ekstensi untuk mengonfigurasi handler pada klien:

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

        return handler;
    });

Peringatan

Sertifikat yang tidak tepercaya hanya boleh digunakan selama pengembangan aplikasi. Aplikasi produksi harus selalu menggunakan sertifikat yang valid.

Memanggil layanan gRPC yang tidak aman dengan klien .NET Core

Klien .NET gRPC dapat memanggil layanan gRPC yang tidak aman dengan menspesifikasikan http di alamat server. Contohnya,GrpcChannel.ForAddress("http://localhost:5000").

Ada beberapa persyaratan tambahan untuk memanggil layanan gRPC yang tidak aman tergantung pada versi .NET yang digunakan aplikasi:

  • .NET 5 atau yang lebih baru memerlukan Grpc.Net.Client versi 2.32.0 atau yang lebih baru.

  • .NET Core 3.x memerlukan konfigurasi tambahan. Aplikasi harus mengatur sakelar System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport ke 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);
    

Sakelar System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport hanya diperlukan untuk .NET Core 3.x. Ini tidak melakukan apa pun di .NET 5 dan tidak diperlukan.

Penting

Layanan gRPC yang tidak aman harus dihosting pada port HTTP/2-saja. Untuk informasi selengkapnya, lihat negosiasi protokol ASP.NET Core.

Tidak dapat memulai aplikasi gRPC ASP.NET Core di macOS

Kestrel tidak mendukung HTTP/2 dengan TLS di macOS sebelum .NET 8. Templat dan sampel gRPC ASP.NET Core menggunakan TLS secara default. Anda akan melihat pesan kesalahan berikut saat mencoba memulai server gRPC:

Tidak dapat mengikat ke https://localhost:5001 pada antarmuka loopback IPv4: 'HTTP/2 melalui TLS tidak didukung di macOS karena dukungan ALPN yang hilang.'.

Untuk mengatasi masalah ini di .NET 7 dan yang lebih lama, konfigurasikan Kestrel dan klien gRPC untuk menggunakan HTTP/2 tanpa TLS. Anda hanya boleh melakukan ini selama pengembangan. Tidak menggunakan TLS akan mengakibatkan pesan gRPC dikirim tanpa enkripsi.

Kestrel harus mengonfigurasi titik akhir HTTP/2 tanpa TLS di 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);
});
  • Dalam kode sebelumnya, ganti nomor port localhost dengan HTTP nomor 5287 port (bukan HTTPS) yang ditentukan dalam dalam Properties/launchSettings.json proyek layanan gRPC.

Ketika titik akhir HTTP/2 dikonfigurasi tanpa TLS, ListenOptions.Protocols titik akhir harus diatur ke HttpProtocols.Http2. HttpProtocols.Http1AndHttp2 tidak dapat digunakan karena TLS diperlukan untuk menegosiasikan HTTP/2. Tanpa TLS, semua koneksi ke titik akhir default ke HTTP/1.1, dan panggilan gRPC gagal.

Klien gRPC juga harus dikonfigurasi untuk tidak menggunakan TLS. Untuk informasi selengkapnya, lihat Memanggil layanan gRPC yang tidak aman dengan klien .NET Core.

Peringatan

HTTP/2 tanpa TLS hanya boleh digunakan selama pengembangan aplikasi. Aplikasi produksi harus selalu menggunakan keamanan transportasi. Untuk informasi selengkapnya, lihat Pertimbangan keamanan di gRPC untuk ASP.NET Core.

aset c# gRPC bukan kode yang dihasilkan dari .proto file

Pembuatan kode gRPC klien konkret dan kelas dasar layanan memerlukan file protobuf dan alat untuk dirujuk dari proyek. Anda harus menyertakan:

  • .proto file yang ingin Anda gunakan dalam <Protobuf> grup item. File yang diimpor .proto harus direferensikan oleh proyek.
  • Referensi paket ke paket peralatan gRPC Grpc.Tools.

Untuk informasi selengkapnya tentang menghasilkan aset C# gRPC, lihat layanan gRPC dengan C#.

Aplikasi web ASP.NET Core yang menghosting layanan gRPC hanya memerlukan kelas dasar layanan yang dihasilkan:

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

Aplikasi klien gRPC yang melakukan panggilan gRPC hanya memerlukan klien konkret yang dihasilkan:

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

Proyek WPF tidak dapat menghasilkan aset C# gRPC dari .proto file

Proyek WPF memiliki masalah umum yang mencegah pembuatan kode gRPC bekerja dengan benar. Setiap jenis gRPC yang dihasilkan dalam proyek WPF dengan mereferensikan Grpc.Tools dan .proto file akan membuat kesalahan kompilasi saat digunakan:

kesalahan CS0246: Jenis atau nama namespace layanan 'MyGrpcServices' tidak dapat ditemukan (apakah Anda kehilangan menggunakan direktif atau referensi perakitan?)

Anda dapat mengatasi masalah ini dengan:

  1. Buat proyek pustaka kelas .NET Core baru.
  2. Dalam proyek baru, tambahkan referensi untuk mengaktifkan pembuatan kode C# dari .proto file:
  3. Di aplikasi WPF, tambahkan referensi ke proyek baru.

Aplikasi WPF dapat menggunakan jenis yang dihasilkan gRPC dari proyek pustaka kelas baru.

Memanggil layanan gRPC yang dihosting di sub-direktori

Peringatan

Banyak alat gRPC pihak ketiga tidak mendukung layanan yang dihosting di subdirektori. Pertimbangkan untuk menemukan cara untuk menghosting gRPC sebagai direktori akar.

Komponen jalur alamat saluran gRPC diabaikan saat melakukan panggilan gRPC. Misalnya, GrpcChannel.ForAddress("https://localhost:5001/ignored_path") tidak akan digunakan ignored_path saat merutekan panggilan gRPC untuk layanan.

Jalur alamat diabaikan karena gRPC memiliki struktur alamat preskriptif standar. Alamat gRPC menggabungkan nama paket, layanan, dan metode: https://localhost:5001/PackageName.ServiceName/MethodName.

Ada beberapa skenario saat aplikasi perlu menyertakan jalur dengan panggilan gRPC. Misalnya, ketika aplikasi gRPC ASP.NET Core dihosting di direktori IIS dan direktori perlu disertakan dalam permintaan. Ketika jalur diperlukan, jalur dapat ditambahkan ke panggilan gRPC menggunakan kustom SubdirectoryHandler yang ditentukan di bawah ini:

/// <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 digunakan saat saluran gRPC dibuat.

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

Kode sebelumnya:

  • SubdirectoryHandler Membuat dengan jalur /MyApp.
  • Mengonfigurasi saluran untuk menggunakan SubdirectoryHandler.
  • Memanggil layanan gRPC dengan SayHelloAsync. Panggilan gRPC dikirim ke https://localhost:5001/MyApp/greet.Greeter/SayHello.

Atau, pabrik klien dapat dikonfigurasi dengan menggunakan SubdirectoryHandlerAddHttpMessageHandler.

Mengonfigurasi klien gRPC untuk menggunakan HTTP/3

Klien .NET gRPC mendukung HTTP/3 dengan .NET 6 atau yang lebih baru. Jika server mengirim alt-svc header respons ke klien yang menunjukkan server mendukung HTTP/3, klien akan secara otomatis meningkatkan koneksinya ke HTTP/3. Untuk informasi tentang cara mengaktifkan HTTP/3 di server, lihat Menggunakan HTTP/3 dengan server web ASP.NET CoreKestrel.

Dukungan HTTP/3 di .NET 8 diaktifkan secara default. Dukungan HTTP/3 di .NET 6 dan .NET 7 perlu diaktifkan melalui bendera konfigurasi dalam file proyek:

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

System.Net.SocketsHttpHandler.Http3Support juga dapat diatur menggunakan AppContext.SetSwitch.

DelegatingHandler Dapat digunakan untuk memaksa klien gRPC menggunakan HTTP/3. Memaksa HTTP/3 menghindari overhead peningkatan permintaan. Paksa HTTP/3 dengan kode yang mirip dengan yang berikut ini:

/// <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 digunakan saat saluran gRPC dibuat. Kode berikut membuat saluran yang dikonfigurasi untuk menggunakan 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" });

Atau, pabrik klien dapat dikonfigurasi dengan menggunakan Http3HandlerAddHttpMessageHandler.

Membangun gRPC di Alpine Linux

Paket menghasilkan jenis .NET dari .proto file menggunakan biner asli yang dibundel yang disebut protoc.Grpc.Tools Langkah tambahan diperlukan untuk membangun aplikasi gRPC pada platform yang tidak didukung oleh biner asli di Grpc.Tools, seperti Alpine Linux.

Buat kode sebelumnya

Salah satu solusinya adalah menghasilkan kode sebelumnya.

  1. Pindahkan .proto file dan Grpc.Tools referensi paket ke proyek baru.
  2. Terbitkan proyek sebagai paket NuGet dan unggah ke umpan NuGet.
  3. Perbarui aplikasi untuk mereferensikan paket NuGet.

Dengan langkah-langkah sebelumnya, aplikasi tidak lagi perlu Grpc.Tools dibuat karena kode dihasilkan sebelumnya.

Menyesuaikan Grpc.Tools biner asli

Grpc.Tools mendukung penggunaan biner asli kustom. Fitur ini memungkinkan alat gRPC berjalan di lingkungan yang tidak didukung biner asli bundelnya.

Bangun atau peroleh protoc biner asli dan grpc_csharp_plugin konfigurasikan Grpc.Tools untuk menggunakannya. Konfigurasikan biner asli dengan mengatur variabel lingkungan berikut:

  • PROTOBUF_PROTOC - Jalur lengkap ke pengkompilasi buffer protokol
  • GRPC_PROTOC_PLUGIN - Jalur lengkap ke grpc_csharp_plugin

Untuk Alpine Linux, ada paket yang disediakan komunitas untuk kompiler buffer protokol dan plugin gRPC di https://pkgs.alpinelinux.org/.

# Build or install the binaries for your architecture.

# e.g. 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

Untuk informasi selengkapnya tentang penggunaan Grpc.Tools dengan arsitektur yang tidak didukung, lihat dokumentasi integrasi build gRPC.

Dokumen ini membahas masalah yang umumnya dihadapi saat mengembangkan aplikasi gRPC di .NET.

Ketidakcocokan antara konfigurasi SSL/TLS klien dan layanan

Templat dan sampel gRPC menggunakan Keamanan Lapisan Transportasi (TLS) untuk mengamankan layanan gRPC secara default. Klien gRPC perlu menggunakan koneksi aman untuk memanggil layanan gRPC aman dengan sukses.

Anda dapat memverifikasi layanan gRPC ASP.NET Core menggunakan TLS dalam log yang ditulis pada awal aplikasi. Layanan ini akan mendengarkan di titik akhir 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

Klien .NET Core harus menggunakan https alamat server untuk melakukan panggilan dengan koneksi aman:

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

Semua implementasi klien gRPC mendukung TLS. Klien gRPC dari bahasa lain biasanya memerlukan saluran yang dikonfigurasi dengan SslCredentials. SslCredentials menentukan sertifikat yang akan digunakan klien, dan harus digunakan alih-alih kredensial yang tidak aman. Untuk contoh mengonfigurasi berbagai implementasi klien gRPC untuk menggunakan TLS, lihat Autentikasi gRPC.

Memanggil layanan gRPC dengan sertifikat yang tidak tepercaya/tidak valid

Klien .NET gRPC mengharuskan layanan memiliki sertifikat tepercaya. Pesan kesalahan berikut dikembalikan saat memanggil layanan gRPC tanpa sertifikat tepercaya:

Pengecualian tidak dapat ditangani. System.Net.Http.HttpRequestException: Koneksi SSL tidak dapat dibuat, lihat pengecualian dalam. >--- System.Security.Authentication.AuthenticationException: Sertifikat jarak jauh tidak valid sesuai dengan prosedur validasi.

Anda mungkin melihat kesalahan ini jika menguji aplikasi secara lokal dan sertifikat pengembangan ASP.NET Core HTTPS tidak tepercaya. Untuk instruksi untuk memperbaiki masalah ini, lihat Mempercayai sertifikat pengembangan ASP.NET Core HTTPS di Windows dan macOS.

Jika Anda memanggil layanan gRPC di komputer lain dan tidak dapat mempercayai sertifikat, maka klien gRPC dapat dikonfigurasi untuk mengabaikan sertifikat yang tidak valid. Kode berikut menggunakan HttpClientHandler.ServerCertificateCustomValidationCallback untuk mengizinkan panggilan tanpa sertifikat tepercaya:

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

Pabrik klien gRPC memungkinkan panggilan tanpa sertifikat tepercaya. ConfigurePrimaryHttpMessageHandler Gunakan metode ekstensi untuk mengonfigurasi handler pada klien:

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

        return handler;
    });

Peringatan

Sertifikat yang tidak tepercaya hanya boleh digunakan selama pengembangan aplikasi. Aplikasi produksi harus selalu menggunakan sertifikat yang valid.

Memanggil layanan gRPC yang tidak aman dengan klien .NET Core

Klien .NET gRPC dapat memanggil layanan gRPC yang tidak aman dengan menspesifikasikan http di alamat server. Contohnya,GrpcChannel.ForAddress("http://localhost:5000").

Ada beberapa persyaratan tambahan untuk memanggil layanan gRPC yang tidak aman tergantung pada versi .NET yang digunakan aplikasi:

  • .NET 5 atau yang lebih baru memerlukan Grpc.Net.Client versi 2.32.0 atau yang lebih baru.

  • .NET Core 3.x memerlukan konfigurasi tambahan. Aplikasi harus mengatur sakelar System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport ke 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);
    

Sakelar System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport hanya diperlukan untuk .NET Core 3.x. Ini tidak melakukan apa pun di .NET 5 dan tidak diperlukan.

Penting

Layanan gRPC yang tidak aman harus dihosting pada port HTTP/2-saja. Untuk informasi selengkapnya, lihat negosiasi protokol ASP.NET Core.

Tidak dapat memulai aplikasi gRPC ASP.NET Core di macOS

Kestrel tidak mendukung HTTP/2 dengan TLS di macOS sebelum .NET 8. Templat dan sampel gRPC ASP.NET Core menggunakan TLS secara default. Anda akan melihat pesan kesalahan berikut saat mencoba memulai server gRPC:

Tidak dapat mengikat ke https://localhost:5001 pada antarmuka loopback IPv4: 'HTTP/2 melalui TLS tidak didukung di macOS karena dukungan ALPN yang hilang.'.

Untuk mengatasi masalah ini di .NET 7 dan yang lebih lama, konfigurasikan Kestrel dan klien gRPC untuk menggunakan HTTP/2 tanpa TLS. Anda hanya boleh melakukan ini selama pengembangan. Tidak menggunakan TLS akan mengakibatkan pesan gRPC dikirim tanpa enkripsi.

Kestrel harus mengonfigurasi titik akhir HTTP/2 tanpa TLS di 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>();
        });

Ketika titik akhir HTTP/2 dikonfigurasi tanpa TLS, ListenOptions.Protocols titik akhir harus diatur ke HttpProtocols.Http2. HttpProtocols.Http1AndHttp2 tidak dapat digunakan karena TLS diperlukan untuk menegosiasikan HTTP/2. Tanpa TLS, semua koneksi ke titik akhir default ke HTTP/1.1, dan panggilan gRPC gagal.

Klien gRPC juga harus dikonfigurasi untuk tidak menggunakan TLS. Untuk informasi selengkapnya, lihat Memanggil layanan gRPC yang tidak aman dengan klien .NET Core.

Peringatan

HTTP/2 tanpa TLS hanya boleh digunakan selama pengembangan aplikasi. Aplikasi produksi harus selalu menggunakan keamanan transportasi. Untuk informasi selengkapnya, lihat Pertimbangan keamanan di gRPC untuk ASP.NET Core.

aset c# gRPC bukan kode yang dihasilkan dari .proto file

Pembuatan kode gRPC klien konkret dan kelas dasar layanan memerlukan file protobuf dan alat untuk dirujuk dari proyek. Anda harus menyertakan:

  • .proto file yang ingin Anda gunakan dalam <Protobuf> grup item. File yang diimpor .proto harus direferensikan oleh proyek.
  • Referensi paket ke paket peralatan gRPC Grpc.Tools.

Untuk informasi selengkapnya tentang menghasilkan aset C# gRPC, lihat layanan gRPC dengan C#.

Aplikasi web ASP.NET Core yang menghosting layanan gRPC hanya memerlukan kelas dasar layanan yang dihasilkan:

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

Aplikasi klien gRPC yang melakukan panggilan gRPC hanya memerlukan klien konkret yang dihasilkan:

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

Proyek WPF tidak dapat menghasilkan aset C# gRPC dari .proto file

Proyek WPF memiliki masalah umum yang mencegah pembuatan kode gRPC bekerja dengan benar. Setiap jenis gRPC yang dihasilkan dalam proyek WPF dengan mereferensikan Grpc.Tools dan .proto file akan membuat kesalahan kompilasi saat digunakan:

kesalahan CS0246: Jenis atau nama namespace layanan 'MyGrpcServices' tidak dapat ditemukan (apakah Anda kehilangan menggunakan direktif atau referensi perakitan?)

Anda dapat mengatasi masalah ini dengan:

  1. Buat proyek pustaka kelas .NET Core baru.
  2. Dalam proyek baru, tambahkan referensi untuk mengaktifkan pembuatan kode C# dari .proto file:
  3. Di aplikasi WPF, tambahkan referensi ke proyek baru.

Aplikasi WPF dapat menggunakan jenis yang dihasilkan gRPC dari proyek pustaka kelas baru.

Memanggil layanan gRPC yang dihosting di sub-direktori

Peringatan

Banyak alat gRPC pihak ketiga tidak mendukung layanan yang dihosting di subdirektori. Pertimbangkan untuk menemukan cara untuk menghosting gRPC sebagai direktori akar.

Komponen jalur alamat saluran gRPC diabaikan saat melakukan panggilan gRPC. Misalnya, GrpcChannel.ForAddress("https://localhost:5001/ignored_path") tidak akan digunakan ignored_path saat merutekan panggilan gRPC untuk layanan.

Jalur alamat diabaikan karena gRPC memiliki struktur alamat preskriptif standar. Alamat gRPC menggabungkan nama paket, layanan, dan metode: https://localhost:5001/PackageName.ServiceName/MethodName.

Ada beberapa skenario saat aplikasi perlu menyertakan jalur dengan panggilan gRPC. Misalnya, ketika aplikasi gRPC ASP.NET Core dihosting di direktori IIS dan direktori perlu disertakan dalam permintaan. Ketika jalur diperlukan, jalur dapat ditambahkan ke panggilan gRPC menggunakan kustom SubdirectoryHandler yang ditentukan di bawah ini:

/// <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 digunakan saat saluran gRPC dibuat.

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

Kode sebelumnya:

  • SubdirectoryHandler Membuat dengan jalur /MyApp.
  • Mengonfigurasi saluran untuk menggunakan SubdirectoryHandler.
  • Memanggil layanan gRPC dengan SayHelloAsync. Panggilan gRPC dikirim ke https://localhost:5001/MyApp/greet.Greeter/SayHello.

Atau, pabrik klien dapat dikonfigurasi dengan menggunakan SubdirectoryHandlerAddHttpMessageHandler.

Dokumen ini membahas masalah yang umumnya dihadapi saat mengembangkan aplikasi gRPC di .NET.

Ketidakcocokan antara konfigurasi SSL/TLS klien dan layanan

Templat dan sampel gRPC menggunakan Keamanan Lapisan Transportasi (TLS) untuk mengamankan layanan gRPC secara default. Klien gRPC perlu menggunakan koneksi aman untuk memanggil layanan gRPC aman dengan sukses.

Anda dapat memverifikasi layanan gRPC ASP.NET Core menggunakan TLS dalam log yang ditulis pada awal aplikasi. Layanan ini akan mendengarkan di titik akhir 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

Klien .NET Core harus menggunakan https alamat server untuk melakukan panggilan dengan koneksi aman:

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

Semua implementasi klien gRPC mendukung TLS. Klien gRPC dari bahasa lain biasanya memerlukan saluran yang dikonfigurasi dengan SslCredentials. SslCredentials menentukan sertifikat yang akan digunakan klien, dan harus digunakan alih-alih kredensial yang tidak aman. Untuk contoh mengonfigurasi berbagai implementasi klien gRPC untuk menggunakan TLS, lihat Autentikasi gRPC.

Memanggil layanan gRPC dengan sertifikat yang tidak tepercaya/tidak valid

Klien .NET gRPC mengharuskan layanan memiliki sertifikat tepercaya. Pesan kesalahan berikut dikembalikan saat memanggil layanan gRPC tanpa sertifikat tepercaya:

Pengecualian tidak dapat ditangani. System.Net.Http.HttpRequestException: Koneksi SSL tidak dapat dibuat, lihat pengecualian dalam. >--- System.Security.Authentication.AuthenticationException: Sertifikat jarak jauh tidak valid sesuai dengan prosedur validasi.

Anda mungkin melihat kesalahan ini jika menguji aplikasi secara lokal dan sertifikat pengembangan ASP.NET Core HTTPS tidak tepercaya. Untuk instruksi untuk memperbaiki masalah ini, lihat Mempercayai sertifikat pengembangan ASP.NET Core HTTPS di Windows dan macOS.

Jika Anda memanggil layanan gRPC di komputer lain dan tidak dapat mempercayai sertifikat, maka klien gRPC dapat dikonfigurasi untuk mengabaikan sertifikat yang tidak valid. Kode berikut menggunakan HttpClientHandler.ServerCertificateCustomValidationCallback untuk mengizinkan panggilan tanpa sertifikat tepercaya:

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

Pabrik klien gRPC memungkinkan panggilan tanpa sertifikat tepercaya. ConfigurePrimaryHttpMessageHandler Gunakan metode ekstensi untuk mengonfigurasi handler pada klien:

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

        return handler;
    });

Peringatan

Sertifikat yang tidak tepercaya hanya boleh digunakan selama pengembangan aplikasi. Aplikasi produksi harus selalu menggunakan sertifikat yang valid.

Memanggil layanan gRPC yang tidak aman dengan klien .NET Core

Klien .NET gRPC dapat memanggil layanan gRPC yang tidak aman dengan menspesifikasikan http di alamat server. Contohnya,GrpcChannel.ForAddress("http://localhost:5000").

Ada beberapa persyaratan tambahan untuk memanggil layanan gRPC yang tidak aman tergantung pada versi .NET yang digunakan aplikasi:

  • .NET 5 atau yang lebih baru memerlukan Grpc.Net.Client versi 2.32.0 atau yang lebih baru.

  • .NET Core 3.x memerlukan konfigurasi tambahan. Aplikasi harus mengatur sakelar System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport ke 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);
    

Sakelar System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport hanya diperlukan untuk .NET Core 3.x. Ini tidak melakukan apa pun di .NET 5 dan tidak diperlukan.

Penting

Layanan gRPC yang tidak aman harus dihosting pada port HTTP/2-saja. Untuk informasi selengkapnya, lihat negosiasi protokol ASP.NET Core.

Tidak dapat memulai aplikasi gRPC ASP.NET Core di macOS

Kestrel tidak mendukung HTTP/2 dengan TLS di macOS sebelum .NET 8. Templat dan sampel gRPC ASP.NET Core menggunakan TLS secara default. Anda akan melihat pesan kesalahan berikut saat mencoba memulai server gRPC:

Tidak dapat mengikat ke https://localhost:5001 pada antarmuka loopback IPv4: 'HTTP/2 melalui TLS tidak didukung di macOS karena dukungan ALPN yang hilang.'.

Untuk mengatasi masalah ini di .NET 7 dan yang lebih lama, konfigurasikan Kestrel dan klien gRPC untuk menggunakan HTTP/2 tanpa TLS. Anda hanya boleh melakukan ini selama pengembangan. Tidak menggunakan TLS akan mengakibatkan pesan gRPC dikirim tanpa enkripsi.

Kestrel harus mengonfigurasi titik akhir HTTP/2 tanpa TLS di 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>();
        });

Ketika titik akhir HTTP/2 dikonfigurasi tanpa TLS, ListenOptions.Protocols titik akhir harus diatur ke HttpProtocols.Http2. HttpProtocols.Http1AndHttp2 tidak dapat digunakan karena TLS diperlukan untuk menegosiasikan HTTP/2. Tanpa TLS, semua koneksi ke titik akhir default ke HTTP/1.1, dan panggilan gRPC gagal.

Klien gRPC juga harus dikonfigurasi untuk tidak menggunakan TLS. Untuk informasi selengkapnya, lihat Memanggil layanan gRPC yang tidak aman dengan klien .NET Core.

Peringatan

HTTP/2 tanpa TLS hanya boleh digunakan selama pengembangan aplikasi. Aplikasi produksi harus selalu menggunakan keamanan transportasi. Untuk informasi selengkapnya, lihat Pertimbangan keamanan di gRPC untuk ASP.NET Core.

aset c# gRPC bukan kode yang dihasilkan dari .proto file

Pembuatan kode gRPC klien konkret dan kelas dasar layanan memerlukan file protobuf dan alat untuk dirujuk dari proyek. Anda harus menyertakan:

  • .proto file yang ingin Anda gunakan dalam <Protobuf> grup item. File yang diimpor .proto harus direferensikan oleh proyek.
  • Referensi paket ke paket peralatan gRPC Grpc.Tools.

Untuk informasi selengkapnya tentang menghasilkan aset C# gRPC, lihat layanan gRPC dengan C#.

Aplikasi web ASP.NET Core yang menghosting layanan gRPC hanya memerlukan kelas dasar layanan yang dihasilkan:

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

Aplikasi klien gRPC yang melakukan panggilan gRPC hanya memerlukan klien konkret yang dihasilkan:

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

Proyek WPF tidak dapat menghasilkan aset C# gRPC dari .proto file

Proyek WPF memiliki masalah umum yang mencegah pembuatan kode gRPC bekerja dengan benar. Setiap jenis gRPC yang dihasilkan dalam proyek WPF dengan mereferensikan Grpc.Tools dan .proto file akan membuat kesalahan kompilasi saat digunakan:

kesalahan CS0246: Jenis atau nama namespace layanan 'MyGrpcServices' tidak dapat ditemukan (apakah Anda kehilangan menggunakan direktif atau referensi perakitan?)

Anda dapat mengatasi masalah ini dengan:

  1. Buat proyek pustaka kelas .NET Core baru.
  2. Dalam proyek baru, tambahkan referensi untuk mengaktifkan pembuatan kode C# dari .proto file:
  3. Di aplikasi WPF, tambahkan referensi ke proyek baru.

Aplikasi WPF dapat menggunakan jenis yang dihasilkan gRPC dari proyek pustaka kelas baru.

Memanggil layanan gRPC yang dihosting di sub-direktori

Peringatan

Banyak alat gRPC pihak ketiga tidak mendukung layanan yang dihosting di subdirektori. Pertimbangkan untuk menemukan cara untuk menghosting gRPC sebagai direktori akar.

Komponen jalur alamat saluran gRPC diabaikan saat melakukan panggilan gRPC. Misalnya, GrpcChannel.ForAddress("https://localhost:5001/ignored_path") tidak akan digunakan ignored_path saat merutekan panggilan gRPC untuk layanan.

Jalur alamat diabaikan karena gRPC memiliki struktur alamat preskriptif standar. Alamat gRPC menggabungkan nama paket, layanan, dan metode: https://localhost:5001/PackageName.ServiceName/MethodName.

Ada beberapa skenario saat aplikasi perlu menyertakan jalur dengan panggilan gRPC. Misalnya, ketika aplikasi gRPC ASP.NET Core dihosting di direktori IIS dan direktori perlu disertakan dalam permintaan. Ketika jalur diperlukan, jalur dapat ditambahkan ke panggilan gRPC menggunakan kustom SubdirectoryHandler yang ditentukan di bawah ini:

/// <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 digunakan saat saluran gRPC dibuat.

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

Kode sebelumnya:

  • SubdirectoryHandler Membuat dengan jalur /MyApp.
  • Mengonfigurasi saluran untuk menggunakan SubdirectoryHandler.
  • Memanggil layanan gRPC dengan SayHelloAsync. Panggilan gRPC dikirim ke https://localhost:5001/MyApp/greet.Greeter/SayHello.

Atau, pabrik klien dapat dikonfigurasi dengan menggunakan SubdirectoryHandlerAddHttpMessageHandler.