【问题标题】:Running a background task in PCF via IHostedService using .net core 2.1使用 .net core 2.1 通过 IHostedService 在 PCF 中运行后台任务
【发布时间】:2018-11-09 13:59:41
【问题描述】:

我想在 .net core 2.1 中使用 https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostedservice?view=aspnetcore-2.1 执行后台任务,并且需要在 PCF 中托管。当我在本地运行时,一切正常。我的 IHostedService 实现在启动活动之后被调用,我可以通过https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.iapplicationlifetime.stopapplication?view=aspnetcore-2.1 优雅地终止应用程序。但是当我在 PCF 中托管时,我遇到了错误

2018-11-09T18:27:35.359+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [OUT] Finished executing task!
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] Unhandled Exception: System.Net.Sockets.SocketException: Permission denied
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] at System.Net.Sockets.Socket.Bind(EndPoint localEP)
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransport.BindAsync()
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.<>c__DisplayClass22_0`1.<<StartAsync>g__OnBind|0>d.MoveNext()
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] --- End of stack trace from previous location where exception was thrown ---
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindEndpointAsync(ListenOptions endpoint, AddressBindContext context)
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] at Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions.BindAsync(AddressBindContext context)
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] at Microsoft.AspNetCore.Server.Kestrel.Core.AnyIPListenOptions.BindAsync(AddressBindContext context)
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.AddressesStrategy.BindAsync(AddressBindContext context)
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindAsync(IServerAddressesFeature addresses, KestrelServerOptions serverOptions, ILogger logger, Func`2 createBinding)
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.StartAsync[TContext](IHttpApplication`1 application, CancellationToken cancellationToken)
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] at Microsoft.AspNetCore.Hosting.Internal.WebHost.StartAsync(CancellationToken cancellationToken)
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token, String shutdownMessage)
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token)
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] at Microsoft.AspNetCore.Hosting.WebHostExtensions.Run(IWebHost host)
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] at DlqProcessingApp.Program.Main(String[] args) in C:\GitRepos\DeadLetterQueueProcessingTask\Program.cs:line 72
2018-11-09T18:27:35.365+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [ERR] at DlqProcessingApp.Program.<Main>(String[] args)
2018-11-09T18:27:35.381+05:30 [APP/TASK/execute-dlqprcoessing-task/0] [OUT] Exit status 134

我在 Startup.cs 中注册 IHostedService,如下所示

     public class Startup
        {
            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
            }

            public IConfiguration Configuration { get; }

            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {

                 // Add management endpoint services
                services.AddCloudFoundryActuators(Configuration);
                services.AddSingleton<IHostedService, DlqProcessingHostedService>();

My implementation looks like below

    public class DlqProcessingHostedService : IHostedService
        {
            private readonly IApplicationLifetime _appLifetime;

            private readonly ILogger<DlqProcessingHostedService> _logger;

            private readonly IServiceScopeFactory _serviceScopeFactory;

            public DlqProcessingHostedService(IApplicationLifetime appLifetime,
                IServiceScopeFactory serviceScopeFactory,
                ILogger<DlqProcessingHostedService> logger)
            {
                _appLifetime = appLifetime;
                _logger = logger;
                _serviceScopeFactory = serviceScopeFactory;
            }

            public async Task StartAsync(CancellationToken cancellationToken)
            {
                using (var scope = _serviceScopeFactory.CreateScope())
                {
                    var he = scope.ServiceProvider.GetRequiredService<HealthEndpoint>();
                    var worker = scope.ServiceProvider.GetRequiredService<IWorker>();
                    CheckStartupHealth(he);
                    await worker.ProcessDlxMessages();
                }
                _appLifetime.StopApplication();
            }

            public async Task StopAsync(CancellationToken cancellationToken)
            {
                _logger.LogInformation("Finished executing task!");
            }

顺便说一句,如果我使用通用主机 https://jmezach.github.io/2017/10/29/having-fun-with-the-.net-core-generic-host/ 而不是 WebHost,这可以正常工作。所以基本上我想知道 IHostedService 实现是否在 PCF 环境中与 WebHost 有任何问题(虽然它在本地工作正常)。我正在使用以下软件包并针对 cflinuxfs2 堆栈。请让我知道我可能做错了什么。

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

      <PropertyGroup>
        <TargetFramework>netcoreapp2.1</TargetFramework>
        <LangVersion>7.1</LangVersion>
      </PropertyGroup>

      <ItemGroup>
        <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" />
        <PackageReference Include="Steeltoe.Extensions.Configuration.CloudFoundryCore" Version="2.1.1" />
        <PackageReference Include="RabbitMQ.Client" Version="5.1.0" />
        <PackageReference Include="Steeltoe.CloudFoundry.ConnectorCore" Version="2.1.1" />
        <PackageReference Include="Steeltoe.Management.CloudFoundryCore" Version="2.1.1" />
      </ItemGroup>

这是我的 Program.cs

  public class Program
    {
        public static async Task Main(string[] args)

        {

            //var host = new HostBuilder()
            //.ConfigureAppConfiguration((hostContext, config) =>
            //{
            //    var env = hostContext.HostingEnvironment;
            //    config.SetBasePath(Directory.GetCurrentDirectory());
            //    config.AddEnvironmentVariables();
            //    config.AddCommandLine(args);
            //    config.AddJsonFile("appsettings.json", true, false);
            //    config.AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, false);
            //    config.AddCloudFoundry();
            //})
            //.ConfigureServices((hostContext, services) =>
            //{
            //    ConfigureServices(services, hostContext.Configuration);
            //})
            //.ConfigureLogging((hostContext, logBuilder) =>
            //{
            //    logBuilder.ClearProviders();
            //    logBuilder.AddConfiguration(hostContext.Configuration.GetSection("Logging"));
            //    logBuilder.AddDynamicConsole();
            //    if (hostContext.HostingEnvironment.IsDevelopment())
            //    {
            //        logBuilder.AddDebug();
            //    }
            //});
            //await host.RunConsoleAsync();

            BuildWebHost(args).Run();
            Console.WriteLine("Finished executing task!");
        }

        public static IWebHost BuildWebHost(string[] args) =>
           WebHost
           .CreateDefaultBuilder(args)
           .UseStartup<Startup>()
           .ConfigureAppConfiguration((builderContext, config) =>
           {
               config.AddCloudFoundry();
           })
           .ConfigureLogging((hostContext, logBuilder) =>
           {
               logBuilder.ClearProviders();
               logBuilder.AddConfiguration(hostContext.Configuration.GetSection("Logging"));
               logBuilder.AddDynamicConsole();
               if (hostContext.HostingEnvironment.IsDevelopment())
               {
                   logBuilder.AddDebug();
               }
           }).Build();

【问题讨论】:

  • 此错误消息看起来与端口绑定有关 - 你能也分享你的 program.cs 吗?
  • 您要在 CheckStartupHealth 中连接哪个地址?我认为您在本地计算机上以管理员身份运行您的应用程序。你的服务器用户呢?它是否需要许可?

标签: asp.net-core .net-core pcf steeltoe


【解决方案1】:

我尝试根据您目前提供的内容使用基本示例重新创建它,但this 对我来说在 PCF 上运行良好 - 错误可能来自您代码中的其他地方

【讨论】:

  • 感谢您的回复。我的清单看起来像下面的应用程序:-名称:hostedservice 内存:512M disk_quota:1024M 堆栈:cflinuxfs2 buildpacks:-dotnet-core_buildpack_current 实例:0 no-route:true services:-syslog-drain。此外,我正在尝试通过命令 cf run-task hostingservice "dotnet hostsservice.dll "Test2" "Test3"" --name execute-dlqtask 运行该应用程序。我仍然遇到同样的错误。尝试使用您的示例应用
  • 哦,你使用cf run-task 运行有点改变 - 据我所知,在这种情况下没有分配端口,这可以解释为什么你会看到端口绑定错误。你可以尝试这样的事情:github.com/macsux/EFMigrate/blob/master/CFTasksExtensions.cs我们还没有在 Steeltoe 中包含这样的扩展,但是可以使用命令 cf run-task efmigrate './EFMigrate cftask=migrate' 执行该示例
  • 我检查了你的样品。因此,如果通过 cf run-task 启动,我们将跳过 WebHost.Run()。通过 Webhost 运行的主要动机是执行 HealthCheck(因为 CF 执行器仅支持 WebHost)。我发现的另一个解决方法是在不利用 IHostedService 的情况下执行 Startup.cs(Healthcheck + 实际任务)中的所有内容。我担心这是否是一个好方法,因为我在应用程序引导程序中执行所有这些(可能很耗时以创建超时)而不利用 IHostedService。
  • 我不确定我是否真的理解你想要做什么......这可能有助于解释这个应用程序应该完成什么。如果你想要一个包含健康检查的长时间运行的应用程序,它应该使用 WebHost。如果您想要一个应用程序启动、执行然后停止,GenericHost 应该没问题(只要让它记录状态更新)。如果您既想要一个长时间运行的应用程序,又想要一个用于特殊场合的管理任务(如 db migrate),请使用 cf run-task 和上面共享的扩展名
  • 我会说第二个“如果您想要一个应用程序启动、执行然后停止,GenericHost 应该没问题(只要让它记录状态更新)”。除此之外,我想使用 CF 执行器端点执行 HealthCheck,例如“private HealthCheckResult CheckStartupHealth(HealthEndpoint he) { var health = he.Invoke(); return health; }”。这里 HealthEndpoint 我可以通过构造函数注入。但是,如果我使用 GenericHost,这是不可能的
猜你喜欢
  • 2023-03-31
  • 2020-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-20
  • 2021-02-14
  • 1970-01-01
  • 2023-03-20
相关资源
最近更新 更多