I'm trying to self register my ASP.NET Core application to Consul registry on startup and deregister it on shutdown.
From here I can gather that calling the http api [put /v1/agent/service/register
] might be the way to go (or maybe not!).
From my app, I thought I'll target the Startup
class, starting with adding the my .json
file
public Startup(IHostingEnvironment env)
{
var builder = new Configuration().AddJsonFile("consulconfig.json");
Configuration = builder.Build();
}
But now, I'm stuck as ConfigureServices
method tells me thats where I add services to the container, and Configure
method is where I configure the Http request pipeline.
Anybody to point me in the right directions, online readings, examples, etc.
First of all I recommend to use Consul.NET to interact with Consul. Using it, a service registration may look like:
var registration = new AgentServiceRegistration
{
Name = "foo",
Port = 4242,
Address = "http://bar"
};
using (var client = new ConsulClient())
{
await client.Agent.ServiceRegister(registration);
}
Now let's integrate this code into ASP.NET Core startup process with help of DI and loose coupling. Read your json file into ConsulOptions
instance (DTO without any logic):
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
services.Configure<ConsulOptions>(Configuration);
}
Encapsulate all Consul-related logic in class ConsulService
accepting ConsulOptions
as a dependency:
public class ConsulService : IDisposable
{
public ConsulService(IOptions<ConsulOptions> optAccessor) { }
public void Register()
{
//possible implementation of synchronous API
client.Agent.ServiceRegister(registration).GetAwaiter().GetResult();
}
}
Add the class itself to the DI container:
services.AddTransient<ConsulService>();
Then create an extention method of IApplicationBuilder
and call it:
public void Configure(IApplicationBuilder app)
{
app.ConsulRegister();
}
In ConsulRegister
implementation we add our hooks on application start/stop:
public static class ApplicationBuilderExtensions
{
public static ConsulService Service { get; set; }
public static IApplicationBuilder ConsulRegister(this IApplicationBuilder app)
{
//design ConsulService class as long-lived or store ApplicationServices instead
Service = app.ApplicationServices.GetService<ConsulService>();
var life = app.ApplicationServices.GetService<IApplicationLifetime>();
life.ApplicationStarted.Register(OnStarted);
life.ApplicationStopping.Register(OnStopping);
return app;
}
private static void OnStarted()
{
Service.Register(); //finally, register the API in Consul
}
}
Locking absence and static fields are OK because the Startup
class is executed exactly once on application start. Don't forget to de-register the API in OnStopping
method!