正确使用 Worker Service 并从 Web Api 注册其服务(相同的解决方案)
Correct use of Worker Service and registration of its services from Web Api (same solution)
我正在尝试寻找合适的架构来解决这个问题:
我需要构建一个服务于 REST 控制器的 API。这个 REST 控制器只是访问存储在字典中的值并将它们提供给用户。 Dictionary 数据结构中有什么?有数据是 scraping 外部 api.
的结果
解决方案 1:我没有构建 worker 服务,只构建了我的 API。我的 API 当它启动时将 运行 一个不同的线程异步保持 scraping 外部 API 并将数据保存在这个字典中。
解决方案 2 - 我采用的解决方案是因为我认为更好(如果我错了请纠正我):我构建了一个 Worker Service,它在我的 API 启动时被调用,其作用是抓取外部 API 并将数据保存在字典中。此类数据将由我的 API.
中的控制器提供
所以,首先我不知道我对第一个的选择是否正确。如果是...我在配置 worker 时遇到问题。
Program.cs 我的 API:
public class Program
{
public static void Main(string[] args)
{
var webHost = CreateHostBuilder(args).Build();
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
.Build();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
Startup.cs 我的 API:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddHostedService<Worker>(); //here I register my worker service
}
Program.cs 我的工人:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddSingleton<IScraperService, ScraperService>();
// Inject IHttpClientFactory
services.AddHttpClient();
services.AddHostedService<Worker>();
});
}
我的工人:
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly IScraperService _scraperService;
public Worker(ILogger<Worker> logger, IScraperService scraperService)
{
_logger = logger;
_scraperService = scraperService;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_scraperService.ScrapeObjects();
}
}
}
所以当我的 API 开始时会打电话给工作人员(或至少尝试)但投诉。它说我的工作人员对 IScraperService 的注册一无所知。当然不是..因为我在我的Worker Service项目的ConfigureServices注册了,从来没有调用过,因为我没有自己启动它。
可能的解决方案:在我的 API 启动时注册 ISCraperService (services.AddSingleton();) 是否正确?如果整个错误,请告诉我。谢谢!
让两者一起工作
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) => {
services.AddSingleton<IScraperService, ScraperService>();
// Inject IHttpClientFactory
services.AddHttpClient();
services.AddHostedService<Worker>();
})
.ConfigureWebHostDefaults(webBuilder => {
webBuilder.UseStartup<Startup>();
});
}
启动
public void ConfigureServices(IServiceCollection services) {
services.AddControllers();
//services.AddHostedService<Worker>(); //worker already registered in Main
//...
}
服务容器现在应该知道所有服务。
当主机 运行 时,API 将侦听请求并启动 worker。
public class Worker : BackgroundService {
private readonly ILogger<Worker> _logger;
private readonly IScraperService _scraperService;
public Worker(ILogger<Worker> logger, IScraperService scraperService) {
_logger = logger;
_scraperService = scraperService;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
while (!stoppingToken.IsCancellationRequested) {
await Task.Run(() => _scraperService.ScrapeObjects());
}
}
}
我正在尝试寻找合适的架构来解决这个问题: 我需要构建一个服务于 REST 控制器的 API。这个 REST 控制器只是访问存储在字典中的值并将它们提供给用户。 Dictionary 数据结构中有什么?有数据是 scraping 外部 api.
的结果解决方案 1:我没有构建 worker 服务,只构建了我的 API。我的 API 当它启动时将 运行 一个不同的线程异步保持 scraping 外部 API 并将数据保存在这个字典中。
解决方案 2 - 我采用的解决方案是因为我认为更好(如果我错了请纠正我):我构建了一个 Worker Service,它在我的 API 启动时被调用,其作用是抓取外部 API 并将数据保存在字典中。此类数据将由我的 API.
中的控制器提供所以,首先我不知道我对第一个的选择是否正确。如果是...我在配置 worker 时遇到问题。
Program.cs 我的 API:
public class Program
{
public static void Main(string[] args)
{
var webHost = CreateHostBuilder(args).Build();
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
.Build();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
Startup.cs 我的 API:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddHostedService<Worker>(); //here I register my worker service
}
Program.cs 我的工人:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddSingleton<IScraperService, ScraperService>();
// Inject IHttpClientFactory
services.AddHttpClient();
services.AddHostedService<Worker>();
});
}
我的工人:
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly IScraperService _scraperService;
public Worker(ILogger<Worker> logger, IScraperService scraperService)
{
_logger = logger;
_scraperService = scraperService;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_scraperService.ScrapeObjects();
}
}
}
所以当我的 API 开始时会打电话给工作人员(或至少尝试)但投诉。它说我的工作人员对 IScraperService 的注册一无所知。当然不是..因为我在我的Worker Service项目的ConfigureServices注册了,从来没有调用过,因为我没有自己启动它。
可能的解决方案:在我的 API 启动时注册 ISCraperService (services.AddSingleton();) 是否正确?如果整个错误,请告诉我。谢谢!
让两者一起工作
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) => {
services.AddSingleton<IScraperService, ScraperService>();
// Inject IHttpClientFactory
services.AddHttpClient();
services.AddHostedService<Worker>();
})
.ConfigureWebHostDefaults(webBuilder => {
webBuilder.UseStartup<Startup>();
});
}
启动
public void ConfigureServices(IServiceCollection services) {
services.AddControllers();
//services.AddHostedService<Worker>(); //worker already registered in Main
//...
}
服务容器现在应该知道所有服务。
当主机 运行 时,API 将侦听请求并启动 worker。
public class Worker : BackgroundService {
private readonly ILogger<Worker> _logger;
private readonly IScraperService _scraperService;
public Worker(ILogger<Worker> logger, IScraperService scraperService) {
_logger = logger;
_scraperService = scraperService;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
while (!stoppingToken.IsCancellationRequested) {
await Task.Run(() => _scraperService.ScrapeObjects());
}
}
}