Aracılığıyla paylaş


.NET Generic Host

Bu makalede, Microsoft.Extensions.Hosting NuGet paketinde kullanılabilen bir .NET Genel Konağı yapılandırmaya ve oluşturmaya yönelik çeşitli desenler hakkında bilgi ediniyorsunuz. .NET Genel Ana Bilgisayarı, uygulama başlatma ve yaşam süresi yönetiminden sorumludur. Worker Service şablonları bir .NET Generic Host oluşturur. HostApplicationBuilder Genel Ana Bilgisayar, Konsol uygulamaları gibi diğer .NET uygulama türleriyle de kullanılabilir.

Konak, bir uygulamanın kaynaklarını ve yaşam süresi işlevselliğini kapsülleyen bir nesnedir, örneğin:

  • Bağımlılık enjeksiyonu (DI)
  • Loglama
  • Yapılandırma
  • Uygulama kapatma
  • IHostedService Uygulamalar

Bir ana bilgisayar başlatıldığında, hizmet kapsayıcısının barındırılan hizmetler koleksiyonunda kayıtlı olan her IHostedService uygulamasında IHostedService.StartAsync çağırır. Çalışan hizmet uygulamasında, tüm BackgroundService.ExecuteAsync örneklerini içeren BackgroundService uygulamaların IHostedService yöntemleri çağrılır.

Uygulamanın tüm birbirine bağlı kaynaklarını tek bir nesneye eklemenin temel nedeni yaşam süresi yönetimidir: uygulama başlatma ve düzgün kapatma üzerinde denetim.

Konak oluşturucu seçenekleri

.NET, Genel Ana Bilgisayarı yapılandırmak ve oluşturmak için iki yaklaşım sağlar:

  • IHostApplicationBuilder (Host.CreateApplicationBuilder): .NET 6'da kullanıma sunulan bu yaklaşım doğrusal, özellik tabanlı bir yapılandırma stili kullanır. Hizmetler, yapılandırma ve günlüğe kaydetme, oluşturucu nesnesinde (örneğin, , builder.Servicesbuilder.Configuration) özelliklere doğrudan erişilerek yapılandırılır. Bu yaklaşım yeni projeler için önerilir ve geçerli .NET şablonlarında varsayılandır.

  • IHostBuilder(Host.CreateDefaultBuilder): Bu, yapılandırmanın zincirleme uzantı yöntemleri (örneğin , ConfigureServicesConfigureAppConfiguration) aracılığıyla yapıldığı geleneksel geri çağırma tabanlı yaklaşımdır. Bu eski yaklaşım tam olarak destekleniyor olsa da mevcut kod temelleriyle uyumluluğu korumak için en iyi sonucu sağlar.

Her iki yaklaşım da aynı temel işlevselliği ve varsayılan davranışları sağlar. Modern .NET desenleri ve daha basit yapılandırma koduyla uyumlu olacak yeni projeler seçin IHostApplicationBuilder . IHostBuilder mevcut uygulamaların bakımını yaparken veya üçüncü taraf kitaplıklar geri çağırma tabanlı model gerektirdiğinde kullanın.

Konak ayarlama

Ana bilgisayar genellikle Program sınıfındaki kodla yapılandırılır, oluşturulur ve çalıştırılır. Main yöntemi:

.NET Çalışan Hizmeti şablonları, Genel Konak oluşturmak için aşağıdaki kodu oluşturur:

using Example.WorkerService;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<Worker>();

IHost host = builder.Build();
host.Run();

Çalışan Hizmetleri hakkında daha fazla bilgi için bkz . .NET'te Çalışan Hizmetleri.

Konak oluşturucu ayarları

CreateApplicationBuilder yöntemi:

  • İçerik kökünü GetCurrentDirectory() tarafından döndürülen yola ayarlar.
  • Ana bilgisayar yapılandırmasını şu kaynaktan yüklüyor:
    • DOTNET_ ile önekli ortam değişkenleri.
    • Komut satırı argümanları.
  • Uygulama yapılandırmasını şu kaynaktan yükler:
    • appsettings.json.
    • appsettings. {Environment}.json.
    • Gizli Yönetici, uygulama Development ortamında çalıştırıldığında.
    • Ortam değişkenleri.
    • Komut satırı bağımsız değişkenleri.
  • Aşağıdaki günlük sağlayıcılarını ekler:
    • Konsol
    • Hata Ayıklama
    • Olay Kaynağı
    • EventLog (yalnızca Windows üzerinde çalışırken)
  • Ortam uygun olduğunda kapsam doğrulamayı ve bağımlılık doğrulamayı etkinleştirir.

HostApplicationBuilder.Services bir Microsoft.Extensions.DependencyInjection.IServiceCollection örnektir. Bu hizmetler, bağımlılık enjeksiyonuyla kullanılan ve kayıtlı hizmetleri çözümlemek için kullanılan bir IServiceProvider inşa etmek amacıyla kullanılır.

Çerçeve tarafından sağlanan hizmetler

IHostBuilder.Build() veya HostApplicationBuilder.Build() çağrısını yaptığınızda, aşağıdaki hizmetler otomatik olarak kaydedilir:

Ek senaryo tabanlı ana bilgisayar oluşturucuları

Web için oluşturuyorsanız veya dağıtılmış bir uygulama yazıyorsanız, farklı bir konak oluşturucu kullanmanız gerekebilir. Aşağıdaki ek konak oluşturucuları listesini göz önünde bulundurun:

IHostApplicationLifetime

IHostApplicationLifetime hizmetini, başlatma sonrası ve zarif kapatma görevlerini yönetmek için herhangi bir sınıfa ekleyin. Arabirimdeki üç özellik, uygulama başlatma ve uygulama durdurma olay işleyicisi yöntemlerini kaydetmek için kullanılan iptal belirteçleridir. Arabirim ayrıca bir StopApplication() yöntemi içerir.

Aşağıdaki örnek, olayları kaydeden IHostedService bir IHostedLifecycleService ve IHostApplicationLifetime uygulamasıdır:

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

Çalışan Hizmeti şablonu, ExampleHostedService implementasyonunu eklemek için değiştirilebilir.

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

Uygulama aşağıdaki örnek çıkışı yazacak:

// 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.

Çıktı, çeşitli yaşam döngüsü olaylarının tümünün sırasını gösterir:

  1. IHostedLifecycleService.StartingAsync
  2. IHostedService.StartAsync
  3. IHostedLifecycleService.StartedAsync
  4. IHostApplicationLifetime.ApplicationStarted

Uygulama durdurulduğunda, örneğin Ctrl+C ile, aşağıdaki olaylar tetiklenir:

  1. IHostApplicationLifetime.ApplicationStopping
  2. IHostedLifecycleService.StoppingAsync
  3. IHostedService.StopAsync
  4. IHostedLifecycleService.StoppedAsync
  5. IHostApplicationLifetime.ApplicationStopped

IHostLifetime

IHostLifetime implementasyonu, konağın ne zaman başlayacağını ve ne zaman duracağını kontrol eder. Kaydedilen son uygulama kullanılır. Microsoft.Extensions.Hosting.Internal.ConsoleLifetime varsayılan IHostLifetime uygulamadır. Kapatmanın yaşam süresi işleyişi hakkında daha fazla bilgi için bkz Ana bilgisayar kapatma.

IHostLifetime Arabirimi, IHostLifetime.WaitForStartAsync yöntemini ortaya koyar. Bu yöntem, başlangıçta çağrılır ve devam etmeden önce IHost.StartAsync tamamlanana kadar bekler. Bu, bir dış olay tarafından sinyal alınana kadar başlatmayı geciktirmek için kullanılabilir.

Ayrıca, IHostLifetime arabirimi IHostLifetime.StopAsync yöntemini kullanıma sunar ve bu yöntem, konağın durmak üzere olduğunu ve kapatma zamanının geldiğini belirtmek için IHost.StopAsync tarafından çağrılır.

IHostEnvironment

IHostEnvironment Aşağıdaki ayarlar hakkında bilgi almak için hizmeti bir sınıfa ekleyin:

Ayrıca hizmet, IHostEnvironment şu uzantı yöntemlerinin yardımıyla ortamı değerlendirme özelliğini kullanıma sunar:

Sunucu yapılandırması

Ana bilgisayar yapılandırması, IHostEnvironment uygulamasının özelliklerini yapılandırmak için kullanılır.

Sunucu yapılandırması HostApplicationBuilderSettings.Configuration özelliğinde ve çevre uygulaması IHostApplicationBuilder.Environment özelliğinde kullanılabilir. Konağı yapılandırmak için Configuration özelliğine erişin ve kullanılabilir uzantı yöntemlerinden herhangi birini çağırın.

Konak yapılandırması eklemek için aşağıdaki örneği göz önünde bulundurun:

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

Yukarıdaki kod:

  • İçerik kökünü, GetCurrentDirectory() tarafından döndürülen yola ayarlar.
  • Konak yapılandırmasını şu kaynaktan yükler:
    • hostsettings.json.
    • Önekli PREFIX_ ortam değişkenleri.
    • Komut satırı bağımsız değişkenleri.

Uygulama yapılandırması

Uygulama yapılandırmasına ortak IHostApplicationBuilder.Configuration özellik üzerinden erişilir. Bu özellik, kullanılabilir uzantı yöntemlerini kullanarak tüketicilerin mevcut yapılandırmadan okumasına veya bu yapılandırmada değişiklik yapmasına olanak tanır.

Daha fazla bilgi için bkz . .NET'te yapılandırma.

Ana bilgisayar kapatma

Barındırılan bir işlemin durdurulmasının çeşitli yolları vardır. En yaygın olarak, barındırılan bir işlem aşağıdaki yollarla durdurulabilir:

Barındırma kodu bu senaryoların işlenmesinden sorumlu değildir. İşlemin sahibinin diğer tüm uygulamalarla aynı şekilde işlem yapması gerekir. Barındırılan bir hizmet işleminin durdurulabilmesinin birkaç yolu daha vardır:

  • Eğer ConsoleLifetime kullanılırsa (UseConsoleLifetime), aşağıdaki sinyalleri dinler ve konağı düzgün bir şekilde durdurmaya çalışır.
    • SIGINT (veya Ctrl+C).
    • SIGQUIT (veya Windows'ta Ctrl+BREAK, Unix'te Ctrl+\).
    • SIGTERM (gibi docker stopdiğer uygulamalar tarafından gönderilir).
  • Uygulama tarafından çağrılırsa Environment.Exit.

Yerleşik barındırma mantığı, özellikle ConsoleLifetime sınıfını, bu senaryoları işler. ConsoleLifetime uygulamaya düzgün bir çıkış sağlamak için SIGINT, SIGQUIT ve SIGTERM "kapatma" sinyallerini işlemeye çalışır.

.NET 6'nın öncesinde .NET kodunun SIGTERM'yi düzgün bir şekilde işlemesi için bir yol yoktu. Bu sınırlamayı geçici olarak çözmek için ConsoleLifetime, System.AppDomain.ProcessExit öğesine abone olur. ProcessExit yükseltildiğinde, ConsoleLifetime konağa durması ve ProcessExit iş parçacığını engellemesi için sinyal verir, konağın durmasını bekler.

İşlem çıkış işleyicisi, uygulamadaki temizleme kodunun çalıştırılmasına izin verir—örneğin IHost.StopAsync ve HostingAbstractionsHostExtensions.Run yönteminden sonraki kodlarda Main.

Başka sorunlar da vardı çünkü ProcessExit'nin tetiklenmesinde kullanılan tek yöntem SIGTERM değildi. Uygulama kodu Environment.Exit ile birlikte çağrıldığında SIGTERM etkinleştirilir. Environment.Exit uygulama modelindeki Microsoft.Extensions.Hosting bir işlemi kapatmanın zarif bir yolu değildir. Olayı ProcessExit olarak tetikler ve ardından süreçten çıkar. yönteminin Main sonu yürütülmüyor. Arka plan ve ön plan iş parçacıkları sonlandırılır ve finally bloklar yürütülmez.

ConsoleLifetime Konağın kapanmasını beklerken engellenen ProcessExit, Environment.Exit'ün ProcessExit çağrısını bekleyen bloklar nedeniyle kilitlenmelere yol açtı. Ayrıca, SIGTERM işlemi süreci düzgün bir şekilde kapatmaya çalıştığından, ConsoleLifetime'yi ExitCode olarak ayarlayacak ve bu da kullanıcının Environment.Exit'e geçirilen çıkış kodunu geçersiz kılacaktır.

.NET 6'da POSIX sinyalleri desteklenir ve işlenir. SIGTERM'yi ConsoleLifetime düzgün bir şekilde işler ve çağrıldığında Environment.Exit artık dahil olmaz.

İpucu

.NET 6+ için artık ConsoleLifetime senaryoyla Environment.Exitbaşa çıkabilecek mantığı yoktur. Kendi temizleme mantığını gerçekleştirmesi gereken ve Environment.Exit çağıran uygulamalar, ProcessExit'e abone olabilir. Barındırma artık bu senaryolarda konağı düzgün bir şekilde durdurmayı denemeyecektir.

Uygulamanız barındırma kullanıyorsa ve konağı düzgün bir şekilde durdurmak istiyorsanız, IHostApplicationLifetime.StopApplication öğesini Environment.Exit yerine çağırabilirsiniz.

Barındırma kapatma işlemi

Aşağıdaki sıralı diyagram, sinyallerin barındırma kodunda dahili olarak nasıl işleneceğini gösterir. Kullanıcıların çoğunun bu işlemi anlaması gerekmez. Ancak derin bir anlayışa ihtiyacı olan geliştiriciler için iyi bir görsel kullanmaya başlamanıza yardımcı olabilir.

Konak başlatıldıktan sonra, bir kullanıcı Run veya WaitForShutdown çağırdığında, IApplicationLifetime.ApplicationStopping için bir işleyici kaydedilir. Yürütme WaitForShutdown içinde duraklatıldı ve ApplicationStopping olayının gerçekleşmesi bekleniyor. Main yöntemi hemen geri dönmez ve uygulama, Run veya WaitForShutdown dönene kadar çalışmaya devam eder.

İşleme bir sinyal gönderildiğinde aşağıdaki sırayı başlatır:

Barındırma kapatma dizisi diyagramı.

  1. Denetim, ApplicationStopping olayını tetiklemek için ConsoleLifetime'dan ApplicationLifetime'e ilerler. Bu, yürütme kodunun engelini kaldırmaya işaret eder WaitForShutdownAsyncMain . Bu arada, POSIX sinyali işlendiği için POSIX sinyal işleyicisi Cancel = true değeri ile döner.
  2. Main Yürütme kodu yeniden yürütülmeye başlar ve konağa StopAsync() öğesini bildirmesi için talimat verir, bu da barındırılan tüm hizmetleri durdurur ve durdurulan diğer olayları tetikler.
  3. Son olarak, WaitForShutdown çıkışlar, herhangi bir uygulama temizleme kodunun yürütülmesine ve yöntemin Main düzgün bir şekilde çıkabilmesine olanak sağlar.

Web sunucusu senaryolarında sunucu kapatma

Kestrel'de hem HTTP/1.1 hem de HTTP/2 protokolleri için düzgün kapanma işleminin nasıl çalıştığı ve yük dengeleyici ile farklı ortamlarda trafiği kesintisiz bir şekilde azaltmak için nasıl yapılandırılabileceği konusunda çeşitli yaygın senaryolar bulunmaktadır. Web sunucusu yapılandırması bu makalenin kapsamı dışında olsa da, ASP.NET Core Kestrel web sunucusu belgeleri için seçenekleri yapılandırma hakkında daha fazla bilgi bulabilirsiniz.

Konak bir kapatma sinyali aldığında (örneğin, Ctrl+C veya StopAsync), ApplicationStoppingsinyali göndererek uygulamaya bildirir. Uzun süreli işlemlerinizin düzgün bir şekilde tamamlanması gerekiyorsa, bu olaya abone olmalısınız.

Ardından, Sunucu, yapılandırabileceğiniz bir kapatma zaman aşımı (varsayılan 30 saniye) ile IServer.StopAsync çağırır. Kestrel (ve Http.Sys) bağlantı noktası bağlamalarını kapatır ve yeni bağlantıları kabul etmeyi durdurur. Ayrıca geçerli bağlantılara yeni istekleri işlemeyi durdurmalarını söyler. HTTP/2 ve HTTP/3 için istemciye bir ön GOAWAY ileti gönderilir. HTTP/1.1 için, istekler sırayla işlendiği için bağlantı döngüsünü durdurur. IIS, 503 durum koduyla yeni istekleri reddederek farklı davranır.

Etkin isteklerin kapatma zaman aşımı tamamlanana kadar süresi vardır. Bunların tümü zaman aşımından önce tamamlanırsa, sunucu denetimi daha erken ana bilgisayara döndürür. Zaman aşımı süresi dolarsa bekleyen bağlantılar ve istekler zorla durdurularak günlüklerde ve istemcilerde hatalara neden olabilir.

Yük dengeleyici ile ilgili dikkat edilmesi gerekenler

Yük dengeleyiciyle çalışırken istemcilerin yeni bir hedefe sorunsuz geçişini sağlamak için şu adımları izleyebilirsiniz:

  • Yeni örneği açın ve trafiği dengelemeye başlayın (ölçeklendirme amacıyla zaten çeşitli örnekleriniz olabilir).
  • Yeni trafik almayı durdurması için yük dengeleyici yapılandırmasındaki eski örneği devre dışı bırakın veya kaldırın.
  • Eski örneğe kapatılması için sinyal verin.
  • Boşalmasını veya süre dolmasını bekleyin.

Ayrıca bkz.