Running a background task in PCF via IHostedService using .net core 2.1

913 views Asked by At

I wanted to peform a background task using https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostedservice?view=aspnetcore-2.1 in .net core 2.1 and needs to host in PCF. When I run locally everything works fine. My implementation of IHostedService is getting called after Startup activites and I am able to terminate the application gracefully via https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.iapplicationlifetime.stopapplication?view=aspnetcore-2.1. But when I host in PCF, I am getting below error

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

I am registering IHostedService like below in my Startup.cs

     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!");
            }

Btw, if i am using generic host https://jmezach.github.io/2017/10/29/having-fun-with-the-.net-core-generic-host/ instead of WebHost, this is working fine. So basically I would like to know whether an IHostedService implementation is having any issue with WebHost in PCF environment(It is working fine locally though). I am using the below packages and targeting a cflinuxfs2 stack. Please let me know what I might be doing wrong.

    <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>

Here is my 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();
1

There are 1 answers

5
Tim On

I tried to recreate this with a basic sample based on what you've provided so far, but this works fine on PCF for me - the error is likely coming from somewhere else in your code