Layanan pekerja di .NET
Ada banyak alasan untuk membuat layanan jangka panjang seperti:
- Memproses data intensif CPU.
- Mengantrekan item kerja di latar belakang.
- Melakukan operasi berbasis waktu sesuai jadwal.
Pemrosesan layanan latar belakang biasanya tidak melibatkan antarmuka pengguna (UI), tetapi UI dapat dibangun di sekitarnya. Pada hari-hari awal dengan .NET Framework, pengembang Windows dapat membuat Layanan Windows untuk tujuan ini. Sekarang dengan .NET, Anda dapat menggunakan BackgroundService, yang merupakan implementasi dari IHostedService, atau mengimplementasikan milik Anda sendiri.
Dengan .NET, Anda tidak lagi dibatasi untuk Windows. Anda dapat mengembangkan layanan latar belakang lintas platform. Layanan yang dihosting siap untuk pengelogan, konfigurasi, dan injeksi dependensi (DI). Mereka adalah bagian dari rangkaian ekstensi pustaka, yang berarti mereka mendasar untuk semua beban kerja .NET yang berfungsi dengan host generik.
Penting
Menginstal .NET SDK juga menginstal Microsoft.NET.Sdk.Worker
templat dan pekerja. Dengan kata lain, setelah menginstal .NET SDK, Anda dapat membuat pekerja baru dengan menggunakan perintah dotnet new worker . Jika Anda menggunakan Visual Studio, templat disembunyikan hingga ASP.NET opsional dan beban kerja pengembangan web diinstal.
Terminologi
Banyak istilah yang keliru digunakan secara sinonim. Bagian ini mendefinisikan beberapa istilah ini untuk membuat niat mereka dalam artikel ini lebih jelas.
- Layanan Latar Belakang: Jenisnya BackgroundService .
- Layanan yang Dihosting: Implementasi IHostedService, atau itu IHostedService sendiri.
- Layanan jangka panjang: Layanan apa pun yang berjalan terus menerus.
- Layanan Windows: Infrastruktur Windows Service , awalnya .NET Framework-centric tetapi sekarang dapat diakses melalui .NET.
- Layanan Pekerja: Templat Layanan Pekerja.
Templat Layanan Pekerja
Templat Layanan Pekerja tersedia di .NET CLI dan Visual Studio. Untuk informasi selengkapnya, lihat .NET CLI, dotnet new worker
- templat. Templat terdiri dari kelas Program
dan Worker
.
using App.WorkerService;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<Worker>();
IHost host = builder.Build();
host.Run();
Kelas sebelumnya Program
:
- HostApplicationBuilderMembuat .
- AddHostedService Panggilan untuk mendaftarkan
Worker
sebagai layanan yang dihosting. - IHost Membangun dari penyusun.
- Panggilan pada
host
instansRun
, yang menjalankan aplikasi.
Default templat
Templat Pekerja tidak mengaktifkan pengumpulan sampah server (GC) secara default, karena ada banyak faktor yang berperan dalam menentukan kebutuhannya. Semua skenario yang memerlukan layanan jangka panjang harus mempertimbangkan implikasi performa dari default ini. Untuk mengaktifkan server GC, tambahkan simpul ServerGarbageCollection
ke file proyek:
<PropertyGroup>
<ServerGarbageCollection>true</ServerGarbageCollection>
</PropertyGroup>
Pertukaran dan pertimbangan
Aktif | Nonaktif |
---|---|
Manajemen memori yang efisien: Secara otomatis mengklaim kembali memori yang tidak digunakan untuk mencegah kebocoran memori dan mengoptimalkan penggunaan sumber daya. | Peningkatan performa real time: Menghindari potensi jeda atau gangguan yang disebabkan oleh pengumpulan sampah dalam aplikasi yang sensitif terhadap latensi. |
Stabilitas jangka panjang: Membantu mempertahankan performa yang stabil dalam layanan jangka panjang dengan mengelola memori selama periode yang lama. | Efisiensi sumber daya: Dapat menghemat sumber daya CPU dan memori di lingkungan yang dibatasi sumber daya. |
Mengurangi pemeliharaan: Meminimalkan kebutuhan akan manajemen memori manual, menyederhanakan pemeliharaan. | Kontrol memori manual: Menyediakan kontrol terperinci atas memori untuk aplikasi khusus. |
Perilaku yang dapat diprediksi: Berkontribusi pada perilaku aplikasi yang konsisten dan dapat diprediksi. | Cocok untuk proses berumur pendek: Meminimalkan overhead pengumpulan sampah untuk proses berumur pendek atau ephemeral. |
Untuk informasi selengkapnya mengenai pertimbangan performa, lihat Server GC. Untuk informasi selengkapnya tentang mengonfigurasi GC server, lihat Contoh konfigurasi GC server.
Kelas pekerja
Adapun Worker
, templat menyediakan implementasi sederhana.
namespace App.WorkerService;
public sealed class Worker(ILogger<Worker> logger) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await Task.Delay(1_000, stoppingToken);
}
}
}
Kelas sebelumnya Worker
adalah subkelas dari BackgroundService, yang mengimplementasikan IHostedService. BackgroundService adalah abstract class
dan mengharuskan subkelas untuk mengimplementasikan BackgroundService.ExecuteAsync(CancellationToken). Dalam implementasi templat, perulangan ExecuteAsync
sekali per detik, mencatat tanggal dan waktu saat ini hingga proses disinyalir dibatalkan.
File proyek
Templat Pekerja bergantung pada file Sdk
proyek berikut:
<Project Sdk="Microsoft.NET.Sdk.Worker">
Untuk informasi selengkapnya, lihat .NET project SDK.
Paket NuGet
Aplikasi berdasarkan templat Pekerja menggunakan Microsoft.NET.Sdk.Worker
SDK dan memiliki referensi paket eksplisit ke paket Microsoft.Extensions.Hosting .
Kontainer dan kemampuan beradaptasi cloud
Dengan sebagian besar beban kerja .NET modern, kontainer adalah opsi yang layak. Saat membuat layanan jangka panjang dari templat Pekerja di Visual Studio, Anda dapat ikut serta dalam dukungan Docker. Melakukannya membuat Dockerfile yang mengontainerisasi aplikasi .NET Anda. Dockerfile adalah serangkaian instruksi untuk membangun sebuah gambar. Untuk aplikasi .NET, Dockerfile biasanya berada di akar direktori di samping file solusi.
# See https://aka.ms/containerfastmode to understand how Visual Studio uses this
# Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/runtime:8.0@sha256:e6b552fd7a0302e4db30661b16537f7efcdc0b67790a47dbf67a5e798582d3a5 AS base
WORKDIR /app
FROM mcr.microsoft.com/dotnet/sdk:8.0@sha256:35792ea4ad1db051981f62b313f1be3b46b1f45cadbaa3c288cd0d3056eefb83 AS build
WORKDIR /src
COPY ["background-service/App.WorkerService.csproj", "background-service/"]
RUN dotnet restore "background-service/App.WorkerService.csproj"
COPY . .
WORKDIR "/src/background-service"
RUN dotnet build "App.WorkerService.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "App.WorkerService.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "App.WorkerService.dll"]
Langkah-langkah Dockerfile sebelumnya meliputi:
- Mengatur gambar dasar dari
mcr.microsoft.com/dotnet/runtime:8.0
sebagai aliasbase
. - Mengubah direktori kerja ke /app.
build
Mengatur alias darimcr.microsoft.com/dotnet/sdk:8.0
gambar.- Mengubah direktori kerja menjadi /src.
- Menyalin konten dan menerbitkan aplikasi .NET:
- Aplikasi ini diterbitkan menggunakan perintah
dotnet publish
.
- Aplikasi ini diterbitkan menggunakan perintah
- Relayering gambar .NET SDK dari
mcr.microsoft.com/dotnet/runtime:8.0
(base
alias). - Menyalin output build yang diterbitkan dari /publish.
- Menentukan titik masuk, yang mendelegasikan ke
dotnet App.BackgroundService.dll
.
Tip
MCR dalam mcr.microsoft.com
adalah singkatan dari "Microsoft Container Registry", dan merupakan katalog kontainer sindikasi Microsoft dari hub Docker resmi. Artikel katalog kontainer sindikat Microsoft berisi detail tambahan.
Saat Anda menargetkan Docker sebagai strategi penyebaran untuk Layanan Pekerja .NET Anda, ada beberapa pertimbangan dalam file proyek:
<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings>
<RootNamespace>App.WorkerService</RootNamespace>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" />
</ItemGroup>
</Project>
Dalam file proyek sebelumnya, <DockerDefaultTargetOS>
elemen menentukan Linux
sebagai targetnya. Untuk menargetkan kontainer Windows, gunakan Windows
sebagai gantinya. Paket Microsoft.VisualStudio.Azure.Containers.Tools.Targets
NuGet secara otomatis ditambahkan sebagai referensi paket saat dukungan Docker dipilih dari templat.
Untuk informasi selengkapnya tentang Docker dengan .NET, lihat Tutorial: Membuat kontainer aplikasi .NET. Untuk informasi selengkapnya tentang penyebaran ke Azure, lihat Tutorial: Menyebarkan Layanan Pekerja ke Azure.
Penting
Jika Anda ingin memanfaatkan Rahasia Pengguna dengan templat Pekerja, Anda harus secara eksplisit mereferensikan Microsoft.Extensions.Configuration.UserSecrets
paket NuGet.
Ekstensibilitas Layanan yang Dihosting
Antarmuka IHostedService mendefinisikan dua metode:
Kedua metode ini berfungsi sebagai metode siklus hidup - mereka dipanggil selama peristiwa mulai dan berhenti host masing-masing.
Catatan
Saat mengambil alih salah satu StartAsync atau StopAsync metode, Anda harus memanggil dan await
base
metode kelas untuk memastikan layanan dimulai dan/atau dimatikan dengan benar.
Penting
Antarmuka berfungsi sebagai batasan parameter jenis generik pada AddHostedService<THostedService>(IServiceCollection) metode ekstensi, yang berarti hanya implementasi yang diizinkan. Anda bebas menggunakan yang disediakan BackgroundService dengan subkelas, atau mengimplementasikan sendiri sepenuhnya.
Penyelesaian sinyal
Dalam skenario yang paling umum, Anda tidak perlu secara eksplisit memberi sinyal penyelesaian layanan yang dihosting. Ketika host memulai layanan, mereka dirancang untuk berjalan sampai host dihentikan. Namun, dalam beberapa skenario, Anda mungkin perlu memberi sinyal penyelesaian seluruh aplikasi host ketika layanan selesai. Untuk memberi sinyal penyelesaian, pertimbangkan kelas berikut Worker
:
namespace App.SignalCompletionService;
public sealed class Worker(
IHostApplicationLifetime hostApplicationLifetime,
ILogger<Worker> logger) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// TODO: implement single execution logic here.
logger.LogInformation(
"Worker running at: {Time}", DateTimeOffset.Now);
await Task.Delay(1_000, stoppingToken);
// When completed, the entire app host will stop.
hostApplicationLifetime.StopApplication();
}
}
Dalam kode sebelumnya, ExecuteAsync
metode tidak mengulang, dan ketika selesai, IHostApplicationLifetime.StopApplication()metode memanggil .
Penting
Ini akan memberi sinyal kepada host bahwa itu harus berhenti, dan tanpa panggilan ini ke StopApplication
host akan terus berjalan tanpa batas waktu.
Untuk informasi selengkapnya, lihat:
- Host Generik .NET: IHostApplicationLifetime
- Host Generik .NET: Penonaktifan host
- Host Generik .NET: Proses penonaktifan hosting