[英]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.