簡體   English   中英

如何通過將方法添加到 .netcore 2.1 中的 Startup 來調用作為后台工作程序的方法?

[英]How can I call a method as background worker by adding it into Startup in .netcore 2.1?

我正在使用 Nest 和 C# 創建一個簡單的日志記錄系統。 我有一個日志生成器,用於在blockingcollection 中收集日志。 我還有一個消費者。 但我偶然發現了一個問題。 我如何在啟動時使用我的消費者,或者有什么方法可以創建正在偵聽阻塞集合隊列的后台服務? 它的最佳實踐是什么? 我很困惑如何在應用程序啟動時調用 AsyncConsumer 或消費者。

 public class SimpleLog
    {
        public string Header { get; set; }
        public string LogDate { get; set; }
        public string Sessionid { get; set; }
        public string Userid { get; set; }
        public string Correlationid { get; set; }
        public int Status { get; set; }
        public string UrlQueryString { get; set; }
        public string UrlPath { get; set; }
        public string UrlMethod { get; set; }
        public string Environment { get; set; }
        public string IndexName { get; set; }
        public string IndexType { get; set; }

    }
    public class QuickLog
    {
        private static BlockingCollection<SimpleLog> data = new BlockingCollection<SimpleLog>();


        public static void Producer(SimpleLog pageviewLog)
        {
            data.TryAdd(pageviewLog, TimeSpan.FromSeconds(10));
        }

        public static void Consumer()
        {
            var _client = ElasticConfig.GetClient();
            var logs = new List<SimpleLog>();

            foreach (var item in data.GetConsumingEnumerable())
            {
                logs.Add(item);
            }

            if (logs == null && logs.Count <= 0)
                return;
            var log = logs.FirstOrDefault();

            var response = _client.IndexMany(logs, log.IndexName, log.IndexType);

            if (!response.IsValid)
                throw response.OriginalException;


        }

        public async Task AsyncConsumer()
        {
            var _client = ElasticConfig.GetClient();
            var logs = new List<SimpleLog>();

            foreach (var item in data.GetConsumingEnumerable())
            {
                logs.Add(item);
            }
            if (logs == null && logs.Count <= 0)
                return;
            var log = logs.FirstOrDefault();
            var response = await _client.IndexManyAsync(logs, log.IndexName, log.IndexType).ConfigureAwait(false);

            if (!response.IsValid)
                throw response.OriginalException;

            await Task.Delay(TimeSpan.FromSeconds(10)).ConfigureAwait(false);
        }
    }
    public static class ElasticConfig
    {
        private static IElasticClient _client;
        static ElasticConfig()
        {
            var esurl = LogSettings.Url;
            string[] urls = esurl.Split(',');
            var nodes = new Uri[2];

            for (int i = 0; i < urls.Length; i++)
            {
                nodes.SetValue(new Uri(urls[i]), i);
            }

            var connectionPool = new SniffingConnectionPool(nodes);
            var connectionSettings = new ConnectionSettings(connectionPool).RequestTimeout(
                TimeSpan.FromSeconds(60))
                .PingTimeout(TimeSpan.FromSeconds(60))
                .MaxRetryTimeout(TimeSpan.FromSeconds(60))
                .MaxDeadTimeout(TimeSpan.FromSeconds(60))
                .DeadTimeout(TimeSpan.FromSeconds(60)).DisablePing()
                                .SniffOnConnectionFault(false)
                                .SniffOnStartup(false)
                                .SniffLifeSpan(TimeSpan.FromMinutes(1));
            _client = new ElasticClient(connectionSettings);
        }
        public static IElasticClient GetClient()
        {
            return _client;
        }
    }

IHostedService 是您的解決方案。

您可以創建新類並從此類繼承https://gist.github.com/davidfowl/a7dd5064d9dcf35b6eae1a7953d615e3

那么你的新班級將是這樣的

public class LogService : HostedService
{
    private readonly IServiceScopeFactory _scopeFactory;

    public LogBackgroundService (IServiceScopeFactory scopeFactory)
    {
        _scopeFactory = scopeFactory;
    }

    protected override async Task ExecuteAsync(CancellationToken cancellationToken)
    {
        while (!cancellationToken.IsCancellationRequested)
        {
            await new QuickLog().AsyncConsumer(cancellationToken); 
            await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);
        }
    }
}

最后更新你的 Startup.cs:

services.AddSingleton<IHostedService, LogService>();

不確定您要調用多少次以及確切地調用哪種方法。 如果您想運行一些異步后台作業,您可以使用 IHostedService。 您將需要安裝Microsoft.Extensions.Hosting NuGet 包或Microsoft.AspNetCore.App 元包

用法:

將此行添加到您的Startup.cs

services.AddHostedService<LogBackgroundService>(); //service is instance of IServiceCollection

這是您的后台服務的實現:

public class LogBackgroundService : IHostedService
{

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        await QuickLog.AsyncConsumer(); // or whatever you want to call           
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }
}

行為:

它將運行一次(但 IHostedService 仍將運行。如果您想減少資源消耗,只需在完成后調用StopAsync() )。 如果你想在循環中運行一些東西,你可以實現這個:

while (!cancellationToken.IsCancellationRequested)
{
    await QuickLog.AsyncConsumer();
    await Task.Delay(250, cancellationToken); // you can add this if you want to throttle 
}

附注。 如果您需要在應用程序中運行多個 IHostedServices 而不會相互阻塞,則需要將您的方法包裝到Tasks

public Task StartAsync(CancellationToken cancellationToken)
{
    Task.Run(() =>  QuickLog.AsyncConsumer(), cancellationToken);
 }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM