.Net Core Dockerized WebAPI failing to register with Eureka server

836 Views Asked by At

I have a .Net Core 3.1 WebAPI running as a Docker container + Eureka server running as Docker also. When I run the API from Visual Studio it registers successfully with the Eureka Docker instance and I can see the service in Eureka console. But once I dockerize the API and run it I am getting connection error as below :

fail: Steeltoe.Discovery.Eureka.Transport.EurekaHttpClient[0]
productsapi_1   |       RegisterAsync Failed
productsapi_1   | System.Net.Http.HttpRequestException: Connection refused
productsapi_1   |  ---> System.Net.Sockets.SocketException (111): Connection refused
productsapi_1   |    at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
productsapi_1   |    --- End of inner exception stack trace ---
productsapi_1   |    at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
......
productsapi_1   |    at Steeltoe.Discovery.Eureka.Transport.EurekaHttpClient.RegisterAsync(InstanceInfo info)
productsapi_1   | fail: Steeltoe.Discovery.Eureka.DiscoveryClient[0]
productsapi_1   |       Register Failed
productsapi_1   | System.Net.Http.HttpRequestException: Connection refused
productsapi_1   |  ---> System.Net.Sockets.SocketException (111): Connection refused
productsapi_1   |    at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
productsapi_1   |    --- End of inner exception stack trace ---
productsapi_1   |    at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
.....
productsapi_1   |    at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
productsapi_1   |    at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean 
disposeCts)
productsapi_1   |    at Steeltoe.Discovery.Eureka.Transport.EurekaHttpClient.RegisterAsync(InstanceInfo info)
productsapi_1   |    at Steeltoe.Discovery.Eureka.DiscoveryClient.RegisterAsync()
productsapi_1   | info: Steeltoe.Discovery.Eureka.DiscoveryClient[0]
productsapi_1   |       Registartion fail. HeartBeat not start
productsapi_1   | fail: Steeltoe.Discovery.Eureka.Transport.EurekaHttpClient[0]
productsapi_1   |       DoGetApplicationsAsync Failed
productsapi_1   | System.Net.Http.HttpRequestException: Connection refused
productsapi_1   |  ---> System.Net.Sockets.SocketException (111): Connection refused
.....

This is after running docker-compose up.Eureaka and API containers are both up but the service does not seem to be registering. This is how my WebAPI looks like :

Startup.cs

 public void ConfigureServices(IServiceCollection services)
    {
        .....       
        services.AddDbContext<ApplicationDbContext>(o => o.UseMySql(Configuration.GetConnectionString("mysqlconnection")));
        services.AddDiscoveryClient(Configuration);
    }
    
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {        
       .....
        app.UseHttpsRedirection();
        app.UseRouting();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
        app.UseDiscoveryClient();
    }

Docker compose

version: '3.4'
services:
  productsapi:
    build: .
    ports: 
      - "5050:5000"
    depends_on:
      - eurekaserver
   
  eurekaserver:
    image: steeltoeoss/eureka-server:latest
    ports:
      - '8761:8761'

Appsettings.json

     {
     ...
  "AllowedHosts": "*",
  ...
  "eureka": {
    "client": {
      "shouldRegisterWithEureka": true,
      "serviceUrl": "http://eurekaserver:8761/eureka",
      "ValidateCertificates": false
    },
    "instance": {
      "appName": "ProductService",
      "port": "5050",
      "hostName": "localhost"
    }
  }
}

What am I missing ?

2

There are 2 best solutions below

2
Golide On BEST ANSWER

Finally got it working with this OSS tweak . My appsettings.json now looks like this:

 {
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "mysqlconnection": "server=mysqldata;port=3306;database=ProductsDB;userid=xxxx;password=xxxx;"
  },
  "PaymentsServiceUri": "http://PaymentService/api/payment",
  "spring": {
    "application": {
      "name": "ProductService"
    }
  },
  "eureka": {
    "client": {
      "shouldRegisterWithEureka": true,
      "serviceUrl": "http://eurekaserver:8761/eureka",
      "ValidateCertificates": false,
      "RegistryFetchIntervalSeconds": "15"
    },
    "instance": {
      "appName": "ProductService",
      "port": "5050",
      "hostName": "localhost",
      "LeaseRenewalIntervalInSeconds": "15"
    }
    }
  }
0
Tim On

I think it's most likely that Eureka is not ready to receive requests yet and that is the cause of the connection refused errors. In my experience, it takes 7-15(ish) seconds for Eureka to start. Docker compose will start the containers in dependency order, but does not wait for a ready state on the first before starting the next. There are options to change the startup behavior, or your application can be built to handle transient failures of this nature.

Steeltoe is built to handle this type of failure and will try (every 30 seconds by default) to send a heartbeat to Eureka. If the first request fails (because Eureka isn't up yet), the next should succeed.

The error message you've shared (and the github issue you opened) indicate that you're using Steeltoe 2.1.1, which was released nearly 3 years ago (before .NET Core 3.1). I don't think this is likely to be the root cause of the issue, but I'd strongly recommend using a newer version.