【问题标题】:Adding an ASPNET API to an existing Worker Service project将 ASPNET API 添加到现有的 Worker Service 项目
【发布时间】:2020-12-30 00:01:10
【问题描述】:

我目前有一个 dotnet 5.0 Worker Service 项目,该项目托管一个后台服务,该服务定期执行业务线流程。我设法通过在 CreateHostBuilder 方法中设置主机来摸索,这一切都作为 docker 容器中的可执行文件运行良好。

但是,我现在想添加一个 HTTP api / ui,以便我可以公开一个“健康”端点和一些漂亮的网页,它们访问与后台服务相同的进程内内存来执行诸如显示内容之类的操作内存缓存,驱逐缓存条目,手动触发业务流程的运行等,我完全迷失了。

我在想我只是在 ConfigureServices 方法中配置了一个额外的托管服务,该方法绑定到我指定的端口上的 ASPNET razor 项目中定义的类,但经过几次尝试后,我有点不知道如何开始接近这个,更不用说让它真正起作用了:-(。

具体来说,我有一个如下所示的 C# 项目:

MyWorker.csproj

<Project Sdk="Microsoft.NET.Sdk.Worker">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" />
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
    <PackageReference Include="Serilog.Extensions.Hosting" Version="4.0.0-dev-00051" />
    <PackageReference Include="Serilog.Formatting.Compact" Version="1.1.1-dev-00940" />
    <PackageReference Include="Serilog.Sinks.Console" Version="4.0.0-dev-00839" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\MyAppCode\MyAppCode.csproj" />
  </ItemGroup>

</Project>

还有一个如下所示的 Program.cs

        public static void Main(string[] args)
        {

            Program.InitSerilog();
            Program.CreateHostBuilder(args).Build().Run();

        }

        public static void InitSerilog()
        {
            ... do stuff ...
        }

        public static IHostBuilder CreateHostBuilder(string[] args)
        {
            return new HostBuilder()
                // worker service config
                .ConfigureLogging((context, builder) =>
                {
                    builder.SetMinimumLevel(LogLevel.Trace);
                })
                .ConfigureServices(services =>
                {
                    services.AddHostedService<MyAppService>();
                    services.AddSingleton<AppSettings>(
                        serviceProvider => { return Program.CreateAppSettings(); }
                    );
                })
                .UseSerilog();
        }

        private static AppSettings CreateAppSettings()
        {
            ... bind to environment variables and return ...
        }

    }

最后,我现有的后台服务是这样的:

    public sealed class MyAppService: BackgroundService
    {

        public MyAppService(ILogger<MyAppService> logger, AppSettings appSettings)
            : base()
        {
            ... do stuff ...
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            ... keep doing the main business process in a timed loop ...
        }

        #endregion
    }

我找到了很多关于如何将工作服务添加到现有 ASPNET 项目或如何将 ASPNET 项目作为 Windows 服务托管的示例,但没有关于如何将 ASPNET 站点侦听器添加到现有工作人员的示例服务。

我希望喜欢能够做的是在一个新的 c# 项目中构建 web ui / api 并以某种方式将其插入现有的 Program.cs 以便它侦听指定的主要BackgroundService正在运行时的端口,但也许我只是在接近这一切都错了吗?

注意 - 我可能在修补时取消了 CreateHostBuilder 方法中的一些默认“正常工作”魔法,所以如果这是简单的答案,请随时告诉我将其恢复为默认值 :-) .

任何帮助/指针表示赞赏...

【问题讨论】:

    标签: c# asp.net-core .net-core backgroundworker


    【解决方案1】:

    首先,我建议你把你的&lt;Project Sdk="Microsoft.NET.Sdk.Worker"&gt; 变成&lt;Project Sdk="Microsoft.NET.Sdk.Web"&gt;

    然后,将您的 CreateHostBuilder 更改为使用 Startup 类:

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        return new HostBuilder()
            .ConfigureLogging((context, builder) =>
            {
                builder.SetMinimumLevel(LogLevel.Trace);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            })
            .UseSerilog();
    }
    

    在您的Startup 中,您可以同时处理后台和其他服务的配置:

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        
        public IConfiguration Configuration { get; }
        
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddHttpContextAccessor();
            services.AddAuthorization();
    
            // worker service config
            services.AddHostedService<MyAppService>();
            services.AddSingleton<AppSettings>(
                serviceProvider => { return Program.CreateAppSettings(); } // this method could be relocated too
            );
    
            // example for health checks
            services.AddHealthChecks();
        }
    
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                // example for health checks
                endpoints.MapHealthChecks("/health", new HealthCheckOptions
                {
                    Predicate = _ => true,
                    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
                });
            });
        }
    }
    

    【讨论】:

    • 酷,谢谢。这让我走上了正轨——我调整了一些东西,但它基本上让我摆脱了常规。
    猜你喜欢
    • 2019-02-16
    • 2019-05-13
    • 1970-01-01
    • 2013-02-21
    • 2019-01-10
    • 2023-03-15
    • 1970-01-01
    • 2020-11-04
    相关资源
    最近更新 更多