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.
Peringatan
Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan .NET dan .NET Core. 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:
- .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
ketrue
. Untuk informasi selengkapnya, lihat Asp.Net Core 3.x: Memanggil layanan gRPC yang tidak aman dengan klien .NET:
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:
- Buat proyek pustaka kelas .NET Core baru.
- Dalam proyek baru, tambahkan referensi untuk mengaktifkan pembuatan kode C# dari
.proto
file:- Tambahkan referensi paket berikut:
- Tambahkan file
.proto
ke grup item<Protobuf>
.
- 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 kehttps://localhost:5001/MyApp/greet.Greeter/SayHello
.
Atau, pabrik klien dapat dikonfigurasi dengan menggunakan SubdirectoryHandler
AddHttpMessageHandler.
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 Http3Handler
AddHttpMessageHandler.
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.
- Pindahkan
.proto
file danGrpc.Tools
referensi paket ke proyek baru. - Terbitkan proyek sebagai paket NuGet dan unggah ke umpan NuGet.
- 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 protokolGRPC_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.
# 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.
batas waktu panggilan gRPC dari HttpClient.Timeout
HttpClient dikonfigurasi dengan batas waktu 100 detik secara default. GrpcChannel
Jika dikonfigurasi untuk menggunakan HttpClient
panggilan streaming gRPC yang berjalan lama dibatalkan jika tidak selesai dalam batas waktu habis.
System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
Ada beberapa cara untuk memperbaiki kesalahan ini. Yang pertama adalah mengonfigurasi HttpClient.Timeout ke nilai yang lebih besar. Timeout.InfiniteTimeSpan menonaktifkan batas waktu:
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);
Atau, hindari membuat HttpClient
dan mengatur GrpcChannel.HttpHandler
sebagai gantinya:
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);
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
ketrue
:// 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
nomor5287
port (bukanHTTPS
) yang ditentukan dalam dalamProperties/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:
- Buat proyek pustaka kelas .NET Core baru.
- Dalam proyek baru, tambahkan referensi untuk mengaktifkan pembuatan kode C# dari
.proto
file:- Tambahkan referensi paket berikut:
- Tambahkan file
.proto
ke grup item<Protobuf>
.
- 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 kehttps://localhost:5001/MyApp/greet.Greeter/SayHello
.
Atau, pabrik klien dapat dikonfigurasi dengan menggunakan SubdirectoryHandler
AddHttpMessageHandler.
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 Http3Handler
AddHttpMessageHandler.
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.
- Pindahkan
.proto
file danGrpc.Tools
referensi paket ke proyek baru. - Terbitkan proyek sebagai paket NuGet dan unggah ke umpan NuGet.
- 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 protokolGRPC_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.
# 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.
batas waktu panggilan gRPC dari HttpClient.Timeout
HttpClient dikonfigurasi dengan batas waktu 100 detik secara default. GrpcChannel
Jika dikonfigurasi untuk menggunakan HttpClient
panggilan streaming gRPC yang berjalan lama dibatalkan jika tidak selesai dalam batas waktu habis.
System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
Ada beberapa cara untuk memperbaiki kesalahan ini. Yang pertama adalah mengonfigurasi HttpClient.Timeout ke nilai yang lebih besar. Timeout.InfiniteTimeSpan menonaktifkan batas waktu:
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);
Atau, hindari membuat HttpClient
dan mengatur GrpcChannel.HttpHandler
sebagai gantinya:
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);
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
ketrue
:// 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:
- Buat proyek pustaka kelas .NET Core baru.
- Dalam proyek baru, tambahkan referensi untuk mengaktifkan pembuatan kode C# dari
.proto
file:- Tambahkan referensi paket berikut:
- Tambahkan file
.proto
ke grup item<Protobuf>
.
- 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 kehttps://localhost:5001/MyApp/greet.Greeter/SayHello
.
Atau, pabrik klien dapat dikonfigurasi dengan menggunakan SubdirectoryHandler
AddHttpMessageHandler.
batas waktu panggilan gRPC dari HttpClient.Timeout
HttpClient dikonfigurasi dengan batas waktu 100 detik secara default. GrpcChannel
Jika dikonfigurasi untuk menggunakan HttpClient
panggilan streaming gRPC yang berjalan lama dibatalkan jika tidak selesai dalam batas waktu habis.
System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
Ada beberapa cara untuk memperbaiki kesalahan ini. Yang pertama adalah mengonfigurasi HttpClient.Timeout ke nilai yang lebih besar. Timeout.InfiniteTimeSpan menonaktifkan batas waktu:
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);
Atau, hindari membuat HttpClient
dan mengatur GrpcChannel.HttpHandler
sebagai gantinya:
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);
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
ketrue
:// 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:
- Buat proyek pustaka kelas .NET Core baru.
- Dalam proyek baru, tambahkan referensi untuk mengaktifkan pembuatan kode C# dari
.proto
file:- Tambahkan referensi paket berikut:
- Tambahkan file
.proto
ke grup item<Protobuf>
.
- 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 kehttps://localhost:5001/MyApp/greet.Greeter/SayHello
.
Atau, pabrik klien dapat dikonfigurasi dengan menggunakan SubdirectoryHandler
AddHttpMessageHandler.
batas waktu panggilan gRPC dari HttpClient.Timeout
HttpClient dikonfigurasi dengan batas waktu 100 detik secara default. GrpcChannel
Jika dikonfigurasi untuk menggunakan HttpClient
panggilan streaming gRPC yang berjalan lama dibatalkan jika tidak selesai dalam batas waktu habis.
System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
Ada beberapa cara untuk memperbaiki kesalahan ini. Yang pertama adalah mengonfigurasi HttpClient.Timeout ke nilai yang lebih besar. Timeout.InfiniteTimeSpan menonaktifkan batas waktu:
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);
Atau, hindari membuat HttpClient
dan mengatur GrpcChannel.HttpHandler
sebagai gantinya:
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);
ASP.NET Core