Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Dalam artikel ini, Anda mempelajari tentang berbagai pola untuk mengonfigurasi dan membangun Host Generik .NET yang tersedia dalam paket NuGet Microsoft.Extensions.Hosting . Host Generik .NET bertanggung jawab atas startup aplikasi dan manajemen seumur hidup. Templat Layanan Worker membuat Host Generik .NET, HostApplicationBuilder. Host Umum dapat digunakan dengan jenis aplikasi .NET lain, seperti aplikasi Konsol.
Host adalah objek yang mencakup sumber daya dan fungsionalitas masa pakai aplikasi, seperti:
- Injeksi dependensi (DI)
- Pencatatan
- Konfigurasi
- Penonaktifan aplikasi
- Implementasi
IHostedService
Ketika host dimulai, host memanggil IHostedService.StartAsync pada setiap implementasi IHostedService yang terdaftar dalam kumpulan layanan yang dihosting dalam kontainer layanan. Dalam aplikasi layanan pekerja, semua implementasi IHostedService yang berisi instans BackgroundService mendapati metode BackgroundService.ExecuteAsync-nya dipanggil.
Alasan utama untuk menyertakan semua sumber daya aplikasi yang saling bergantung dalam satu objek adalah pengelolaan masa pakai: kontrol atas pengaktifan dan penonaktifan aplikasi dengan baik.
Opsi penyusun host
.NET menyediakan dua pendekatan untuk mengonfigurasi dan membangun Host Generik:
IHostApplicationBuilder (
Host.CreateApplicationBuilder): Diperkenalkan dalam .NET 6, pendekatan ini menggunakan gaya konfigurasi berbasis properti linier. Layanan, konfigurasi, dan pengelogan dikonfigurasi dengan langsung mengakses properti pada objek penyusun (misalnya,builder.Services,builder.Configuration). Pendekatan ini direkomendasikan untuk proyek baru dan merupakan default dalam templat .NET saat ini.IHostBuilder (
Host.CreateDefaultBuilder): Ini adalah pendekatan berbasis panggilan balik tradisional di mana konfigurasi dilakukan melalui metode ekstensi berantai (misalnya,ConfigureServices,ConfigureAppConfiguration). Meskipun didukung penuh, pendekatan warisan ini berfungsi paling baik untuk mempertahankan kompatibilitas dengan basis kode yang ada.
Kedua pendekatan menyediakan fungsionalitas inti dan perilaku default yang sama. Pilih IHostApplicationBuilder agar proyek baru selaras dengan pola .NET modern dan kode konfigurasi yang lebih sederhana. Gunakan IHostBuilder saat mempertahankan aplikasi yang ada atau ketika pustaka pihak ketiga memerlukan pola berbasis panggilan balik.
Menyiapkan host
Host biasanya dikonfigurasi, dibangun, dan dijalankan oleh kode di kelas Program. Metode Main:
- Memanggil metode CreateApplicationBuilder untuk membuat dan mengonfigurasi objek penyusun.
- Panggil Build() untuk membuat instans IHost.
- Panggil Run atau metode RunAsync pada objek host.
Template Layanan Pekerja .NET menghasilkan kode berikut untuk membuat Host Umum:
using Example.WorkerService;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<Worker>();
IHost host = builder.Build();
host.Run();
Untuk informasi selengkapnya tentang Layanan Pekerja, lihat Layanan Pekerja di .NET.
Pengaturan penyusun host
Metode CreateApplicationBuilder:
- Menetapkan akar konten ke jalur yang ditampilkan oleh GetCurrentDirectory().
-
Memuat konfigurasi host dari:
- Variabel lingkungan yang diawali dengan
DOTNET_. - Argumen baris perintah.
- Variabel lingkungan yang diawali dengan
- Memuat konfigurasi aplikasi dari:
- appsettings.json.
- appsettings. {Environment}.json.
- Pengelola Rahasia saat aplikasi berjalan di lingkungan
Development. - Variabel lingkungan.
- Argumen baris perintah.
- Menambahkan penyedia pengelogan berikut:
- Konsol
- Pemecahan Kesalahan
- SumberAcara
- EventLog (hanya saat menjalankan di Windows)
- Mengaktifkan validasi cakupan dan validasi dependensi ketika lingkungan
Development.
HostApplicationBuilder.Services adalah Microsoft.Extensions.DependencyInjection.IServiceCollection instans. Layanan ini digunakan untuk membangun IServiceProvider yang digunakan dalam injeksi dependensi untuk menginisialisasi layanan yang terdaftar.
Layanan yang disediakan oleh kerangka kerja
Saat Anda memanggil IHostBuilder.Build() atau HostApplicationBuilder.Build(), layanan berikut didaftarkan secara otomatis:
Pembangun host berbasis skenario tambahan
Jika Anda membangun untuk web atau menulis aplikasi terdistribusi, Anda mungkin perlu menggunakan pembuat host yang berbeda. Pertimbangkan daftar penyusun host tambahan berikut:
- DistributedApplicationBuilder: Pembangun untuk membuat aplikasi terdistribusi. Untuk informasi selengkapnya, lihat Aspire.
- WebApplicationBuilder: Pengembang untuk aplikasi dan layanan web. Untuk informasi selengkapnya, lihat ASP.NET Core.
-
WebHostBuilder: Pembuat untuk
IWebHost. Untuk informasi selengkapnya, lihat web host ASP.NET Core.
IHostApplicationLifetime
Injeksikan layanan IHostApplicationLifetime ke kelas mana pun untuk menangani tugas setelah pengaktifan dan penonaktifan secara halus. Tiga properti pada antarmuka adalah token pembatalan yang digunakan untuk mendaftarkan metode penanganan aktivitas mulai aplikasi dan penghentian aplikasi. Antarmuka juga mencakup metode StopApplication().
Contoh berikut adalah implementasi IHostedService dan IHostedLifecycleService yang mendaftarkan IHostApplicationLifetime peristiwa:
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace AppLifetime.Example;
public sealed class ExampleHostedService : IHostedService, IHostedLifecycleService
{
private readonly ILogger _logger;
public ExampleHostedService(
ILogger<ExampleHostedService> logger,
IHostApplicationLifetime appLifetime)
{
_logger = logger;
appLifetime.ApplicationStarted.Register(OnStarted);
appLifetime.ApplicationStopping.Register(OnStopping);
appLifetime.ApplicationStopped.Register(OnStopped);
}
Task IHostedLifecycleService.StartingAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("1. StartingAsync has been called.");
return Task.CompletedTask;
}
Task IHostedService.StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("2. StartAsync has been called.");
return Task.CompletedTask;
}
Task IHostedLifecycleService.StartedAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("3. StartedAsync has been called.");
return Task.CompletedTask;
}
private void OnStarted()
{
_logger.LogInformation("4. OnStarted has been called.");
}
private void OnStopping()
{
_logger.LogInformation("5. OnStopping has been called.");
}
Task IHostedLifecycleService.StoppingAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("6. StoppingAsync has been called.");
return Task.CompletedTask;
}
Task IHostedService.StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("7. StopAsync has been called.");
return Task.CompletedTask;
}
Task IHostedLifecycleService.StoppedAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("8. StoppedAsync has been called.");
return Task.CompletedTask;
}
private void OnStopped()
{
_logger.LogInformation("9. OnStopped has been called.");
}
}
Template Layanan Pekerja dapat dimodifikasi untuk menambahkan implementasi ExampleHostedService:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using AppLifetime.Example;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<ExampleHostedService>();
using IHost host = builder.Build();
await host.RunAsync();
Aplikasi akan menulis output sampel berikut:
// Sample output:
// info: AppLifetime.Example.ExampleHostedService[0]
// 1.StartingAsync has been called.
// info: AppLifetime.Example.ExampleHostedService[0]
// 2.StartAsync has been called.
// info: AppLifetime.Example.ExampleHostedService[0]
// 3.StartedAsync has been called.
// info: AppLifetime.Example.ExampleHostedService[0]
// 4.OnStarted has been called.
// info: Microsoft.Hosting.Lifetime[0]
// Application started. Press Ctrl+C to shut down.
// info: Microsoft.Hosting.Lifetime[0]
// Hosting environment: Production
// info: Microsoft.Hosting.Lifetime[0]
// Content root path: ..\app-lifetime\bin\Debug\net8.0
// info: AppLifetime.Example.ExampleHostedService[0]
// 5.OnStopping has been called.
// info: Microsoft.Hosting.Lifetime[0]
// Application is shutting down...
// info: AppLifetime.Example.ExampleHostedService[0]
// 6.StoppingAsync has been called.
// info: AppLifetime.Example.ExampleHostedService[0]
// 7.StopAsync has been called.
// info: AppLifetime.Example.ExampleHostedService[0]
// 8.StoppedAsync has been called.
// info: AppLifetime.Example.ExampleHostedService[0]
// 9.OnStopped has been called.
Output menunjukkan urutan semua dari berbagai peristiwa siklus hidup:
IHostedLifecycleService.StartingAsyncIHostedService.StartAsyncIHostedLifecycleService.StartedAsyncIHostApplicationLifetime.ApplicationStarted
Ketika aplikasi dihentikan, misalnya dengan Ctrl+C, peristiwa berikut dipicu:
IHostApplicationLifetime.ApplicationStoppingIHostedLifecycleService.StoppingAsyncIHostedService.StopAsyncIHostedLifecycleService.StoppedAsyncIHostApplicationLifetime.ApplicationStopped
IHostLifetime
Implementasi IHostLifetime mengontrol kapan host memulai dan berhenti. Implementasi terakhir yang terdaftar akan digunakan.
Microsoft.Extensions.Hosting.Internal.ConsoleLifetime adalah implementasi IHostLifetime default. Untuk informasi selengkapnya tentang mekanisme masa pakai penonaktifan, lihat Penonaktifan host.
Antarmuka IHostLifetime memperkenalkan metode IHostLifetime.WaitForStartAsync yang dipanggil pada awal IHost.StartAsync dan akan menunggu hingga proses selesai sebelum melanjutkan. Ini dapat digunakan untuk menunda startup hingga disinyalir oleh peristiwa eksternal.
Selain itu, antarmuka IHostLifetime mengekspos metode IHostLifetime.StopAsync, yang dipanggil dari IHost.StopAsync yang menandakan bahwa host berhenti dan waktunya untuk berhenti beroperasi.
IHostEnvironment
Injeksikan layanan IHostEnvironment ke dalam kelas untuk mendapatkan informasi tentang pengaturan berikut:
- IHostEnvironment.ApplicationName
- IHostEnvironment.ContentRootFileProvider
- IHostEnvironment.ContentRootPath
- IHostEnvironment.EnvironmentName
Selain itu, layanan ini IHostEnvironment memaparkan kemampuan untuk mengevaluasi lingkungan dengan bantuan metode ekstensi ini:
- HostEnvironmentEnvExtensions.IsDevelopment
- HostEnvironmentEnvExtensions.IsEnvironment
- HostEnvironmentEnvExtensions.IsProduction
- HostEnvironmentEnvExtensions.IsStaging
Konfigurasi host
Konfigurasi host digunakan untuk mengonfigurasi properti implementasi IHostEnvironment.
Konfigurasi host tersedia di HostApplicationBuilderSettings.Configuration properti dan implementasi lingkungan tersedia di IHostApplicationBuilder.Environment properti. Untuk mengonfigurasi host, akses Configuration properti dan panggil salah satu metode ekstensi yang tersedia.
Untuk menambahkan konfigurasi host, pertimbangkan contoh berikut:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
HostApplicationBuilderSettings settings = new()
{
Args = args,
Configuration = new ConfigurationManager(),
ContentRootPath = Directory.GetCurrentDirectory(),
};
settings.Configuration.AddJsonFile("hostsettings.json", optional: true);
settings.Configuration.AddEnvironmentVariables(prefix: "PREFIX_");
settings.Configuration.AddCommandLine(args);
HostApplicationBuilder builder = Host.CreateApplicationBuilder(settings);
using IHost host = builder.Build();
// Application code should start here.
await host.RunAsync();
Kode sebelumnya:
- Mengatur akar konten ke jalur yang ditampilkan oleh GetCurrentDirectory().
- Memuat konfigurasi host dari:
- hostsettings.json.
- Variabel lingkungan yang diawali dengan
PREFIX_. - Argumen baris perintah.
Konfigurasi aplikasi
Konfigurasi aplikasi diakses melalui properti publik IHostApplicationBuilder.Configuration . Properti ini memungkinkan konsumen untuk membaca dari atau membuat perubahan pada konfigurasi yang ada menggunakan metode ekstensi yang tersedia.
Untuk informasi selengkapnya, lihat Konfigurasi di .NET.
Penonaktifan host
Ada beberapa cara untuk menghentikan proses yang dihosting. Paling umum, proses yang dihosting dapat dihentikan dengan cara berikut:
- Jika seseorang tidak memanggil Run atau HostingAbstractionsHostExtensions.WaitForShutdown dan aplikasi keluar secara normal setelah
Mainselesai. - Jika aplikasi mengalami hang.
- Jika aplikasi dimatikan secara paksa menggunakan SIGKILL (atau Ctrl+Z).
Kode hosting tidak bertanggung jawab untuk menangani skenario ini. Pemilik proses perlu menanganinya sama dengan aplikasi lain. Ada beberapa cara lain di mana proses layanan yang dihosting dapat dihentikan:
- Jika
ConsoleLifetimedigunakan (UseConsoleLifetime), ia mendengarkan sinyal berikut dan mencoba menghentikan host dengan anggun. - Jika aplikasi memanggil Environment.Exit.
Logika hosting bawaan menangani skenario ini, khususnya ConsoleLifetime kelas .
ConsoleLifetime mencoba menangani sinyal "shutdown" SIGINT, SIGQUIT, dan SIGTERM untuk memungkinkan aplikasi keluar secara elegan.
Sebelum .NET 6, tidak ada cara bagi kode .NET untuk menangani SIGTERM dengan baik. Untuk mengatasi batasan ini, ConsoleLifetime akan berlangganan ke System.AppDomain.ProcessExit. Saat ProcessExit dimunculkan, ConsoleLifetime akan memberi sinyal ke host untuk berhenti dan memblokir alur ProcessExit, yang menunggu host berhenti.
Handler keluar proses akan memungkinkan kode pembersihan berjalan dalam aplikasi—misalnya, kode IHost.StopAsync dan kode setelah HostingAbstractionsHostExtensions.Run dalam metode Main.
Namun, ada masalah lain dengan pendekatan ini karena SIGTERM bukan satu-satunya cara ProcessExit yang diangkat. SIGTERM juga dinaikkan saat kode aplikasi memanggil Environment.Exit.
Environment.Exit bukanlah cara yang baik untuk mematikan proses dalam model aplikasi Microsoft.Extensions.Hosting. Hal ini memunculkan peristiwa ProcessExit dan kemudian keluar dari proses. Akhir metode Main tidak dijalankan. Utas latar belakang dan latar depan dihentikan, dan finally blok tidak dijalankan.
Karena ConsoleLifetime memblokir ProcessExit saat menunggu host dimatikan, perilaku ini menyebabkan kebuntuan dari Environment.Exit yang juga memblokir menunggu panggilan ke ProcessExit. Selain itu, karena penanganan SIGTERM mencoba mematikan proses dengan baik, ConsoleLifetime akan mengatur ExitCode ke 0, yang mengacaukan kode keluar pengguna yang diteruskan ke Environment.Exit.
Di .NET 6, sinyal POSIX didukung dan ditangani.
ConsoleLifetime menangani SIGTERM dengan baik, dan tidak lagi ikut terlibat ketika Environment.Exit dipanggil.
Petunjuk / Saran
Untuk .NET 6+, ConsoleLifetime tidak lagi memiliki logika untuk menangani skenario Environment.Exit. Aplikasi yang memanggil Environment.Exit dan perlu menjalankan logika pembersihan dapat berlangganan ke ProcessExit dengan sendirinya. Hosting tidak akan lagi mencoba menghentikan host dengan cara yang baik dalam skenario-skenario ini.
Jika aplikasi Anda menggunakan hosting, dan Anda ingin menghentikan host dengan baik, Anda dapat memanggil IHostApplicationLifetime.StopApplication dan bukan Environment.Exit.
Proses penonaktifan hosting
Diagram urutan berikut menunjukkan cara sinyal ditangani secara internal dalam kode hosting. Sebagian besar pengguna tidak perlu memahami proses ini. Tetapi bagi pengembang yang membutuhkan pemahaman mendalam, visual yang baik dapat membantu Anda memulai.
Setelah host dimulai, saat pengguna memanggil Run atau WaitForShutdown, handler didaftarkan untuk IApplicationLifetime.ApplicationStopping. Eksekusi dijeda di WaitForShutdown, menunggu peristiwa ApplicationStopping dijalankan. Metode Main ini tidak segera kembali, dan aplikasi tetap berjalan sampai Run atau WaitForShutdown kembali.
Saat dikirim ke proses, sinyal akan memulai urutan berikut:
- Kontrol mengalir dari
ConsoleLifetimekeApplicationLifetimeuntuk memunculkan peristiwaApplicationStopping. Hal ini memberi sinyalWaitForShutdownAsyncuntuk membuka blokir kode eksekusiMain. Sementara, handler sinyal POSIX mengembalikanCancel = truekarena sinyal POSIX telah ditangani. - Kode eksekusi
Mainmulai dijalankan lagi dan memberi tahu host untukStopAsync(), yang pada gilirannya menghentikan semua layanan yang dihosting, dan melaporkan semua kejadian lain yang telah dihentikan. - Akhirnya,
WaitForShutdownkeluar, memungkinkan kode pembersihan aplikasi apa pun dijalankan, dan metodeMainmengakhiri dengan mulus.
Penonaktifan host dalam skenario server web
Ada berbagai skenario umum lainnya di mana penghentian dengan baik berfungsi pada Kestrel untuk protokol HTTP/1.1 dan HTTP/2, serta bagaimana Anda dapat mengonfigurasinya di lingkungan yang berbeda dengan load balancer untuk mengalihkan lalu lintas dengan lancar. Meskipun konfigurasi server web berada di luar cakupan artikel ini, Anda dapat menemukan informasi selengkapnya tentang Mengonfigurasi opsi untuk dokumentasi server web ASP.NET Core Kestrel.
Ketika Host menerima sinyal matikan (misalnya, Ctrl+C atau StopAsync), Host akan memberi tahu aplikasi dengan memberi sinyal ApplicationStopping. Anda harus berlangganan acara ini jika Anda memiliki operasi jangka panjang yang perlu diselesaikan dengan baik.
Selanjutnya, Host memanggil IServer.StopAsync dengan batas waktu mati yang dapat Anda konfigurasi (default 30s). Kestrel (dan Http.Sys) menutup pengikatan port mereka dan berhenti menerima koneksi baru. Mereka juga menginstruksikan koneksi yang ada untuk berhenti memproses permintaan baru. Untuk HTTP/2 dan HTTP/3, pesan awal GOAWAY dikirim ke klien. Untuk HTTP/1.1, mereka menghentikan perulangan koneksi karena permintaan diproses secara berurutan. IIS berperilaku berbeda, dengan menolak permintaan baru dengan kode status 503.
Permintaan aktif diberi waktu hingga batas waktu penghentian untuk diselesaikan. Jika semuanya selesai sebelum waktu habis, server mengembalikan kontrol ke host lebih cepat. Jika waktu habis, koneksi dan permintaan yang tertunda dibatalkan secara paksa, yang dapat menyebabkan kesalahan dalam log dan kepada klien.
Pertimbangan untuk load balancer
Untuk memastikan transisi klien yang lancar ke tujuan baru saat bekerja dengan load balancer, Anda dapat mengikuti langkah-langkah berikut:
- Munculkan instans baru dan mulai seimbangkan lalu lintas ke instans tersebut (Anda mungkin sudah memiliki beberapa instans untuk tujuan penskalaan).
- Nonaktifkan atau hapus instans lama dalam konfigurasi load balancer sehingga berhenti menerima lalu lintas baru.
- Perintahkan instans lama untuk dimatikan.
- Tunggu hingga selesai dikuras atau waktu habis.
Lihat juga
- Injeksi Ketergantungan di .NET
- Pengelogan dalam .NET
- Konfigurasi di .NET
- Layanan Pekerja .NET
- ASP.NET Core Web Host
- konfigurasi server web ASP.NET Core Kestrel
- Bug host generik harus dibuat di repositori github.com/dotnet/runtime