Как я могу вызвать метод в качестве фонового работника, добавив его в автозагрузку в .netcore 2.1? - PullRequest
0 голосов
/ 18 февраля 2020

Я создаю простую систему регистрации с помощью Nest и C#. У меня есть производитель журналов для сбора журналов внутри blockingcollection. Также у меня есть потребитель. Но я столкнулся с проблемой. Как я могу использовать мой потребитель при запуске или есть какой-нибудь способ создать фоновый сервис, который прослушивал очередь 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;
        }
    }

Ответы [ 2 ]

2 голосов
/ 18 февраля 2020

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>();
2 голосов
/ 18 февраля 2020

Не уверен, сколько раз и какой именно метод вы хотите вызвать. Если вы хотите запустить некоторые асинхронные фоновые задания, вы можете использовать IHostedService. Вам потребуется установить Microsoft.Extensions.Hosting пакет NuGet или Microsoft.AspNetCore.App metapackage .

Использование:

Добавить эту строку в ваш 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(), когда это будет сделано). Если вы хотите запустить что-то в al oop, вы можете реализовать это:

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

PS. Если вам нужно запустить несколько приложений IHostedServices в вашем приложении, не блокируя друг друга, вам нужно будет обернуть свои методы в Tasks:

public Task StartAsync(CancellationToken cancellationToken)
{
    Task.Run(() =>  QuickLog.AsyncConsumer(), cancellationToken);
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...