如何使用Consul自行注册服务

时间:2016-09-13 09:58:28

标签: c# asp.net-core microservices consul

我试图self在启动时将我的ASP.NET核心应用程序注册到Consul注册表,并在关机时取消注册。

here我可以收集到调用http api [put /v1/agent/service/register]可能是要走的路(也许不是!)。

从我的应用中,我认为我将定位Startup课程,首先添加我的.json文件

public Startup(IHostingEnvironment env)
{
   var builder = new Configuration().AddJsonFile("consulconfig.json");
   Configuration = builder.Build();
}

但是现在,我被卡住了,因为ConfigureServices方法告诉我这是我向容器添加服务的地方,Configure方法是我配置Http请求管道的地方。

有人指出我正确的方向,在线阅读,例子等。

2 个答案:

答案 0 :(得分:9)

首先我建议使用Consul.NET  与领事互动。使用它,服务注册可能如下所示:

var registration = new AgentServiceRegistration
{
    Name = "foo",
    Port = 4242,
    Address = "http://bar"
};

using (var client = new ConsulClient())
{
    await client.Agent.ServiceRegister(registration);
}

现在让我们在DI和松散耦合的帮助下将此代码集成到ASP.NET Core启动过程中。将您的json文件读入ConsulOptions实例(没有任何逻辑的DTO):

public void ConfigureServices(IServiceCollection services)
{
    services.AddOptions();
    services.Configure<ConsulOptions>(Configuration);
}

将接受ConsulService的{​​{1}}类中与Consul相关的所有逻辑封装为依赖:

ConsulOptions

将类本身添加到DI容器中:

public class ConsulService : IDisposable
{
    public ConsulService(IOptions<ConsulOptions> optAccessor) { }

    public void Register() 
    {
        //possible implementation of synchronous API
        client.Agent.ServiceRegister(registration).GetAwaiter().GetResult();
    }
}

然后创建services.AddTransient<ConsulService>(); 的扩展方法并将其命名为:

IApplicationBuilder

public void Configure(IApplicationBuilder app) { app.ConsulRegister(); } 实现中,我们在应用程序启动/停止时添加了钩子:

ConsulRegister

锁定缺席和静态字段是正常的,因为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 } } 类在应用程序启动时执行一次。不要忘记在Startup方法中注销API!

答案 1 :(得分:1)

Startup.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace WebApplication1
{
    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)
        {
            services.AddConsulConfig(Configuration);
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseConsul();
            app.UseMvc();
        }
    }
}

AppExtensions.cs

using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace WebApplication1
{
    public static class AppExtensions
    {
        public static IServiceCollection AddConsulConfig(this IServiceCollection services, IConfiguration configuration)
        {
            services.AddSingleton<IConsulClient, ConsulClient>(p => new ConsulClient(consulConfig =>
            {
                var address = configuration.GetValue<string>("http://localhost:8500");
                consulConfig.Address = new Uri(address);
            }));
            return services;
        }

        public static IApplicationBuilder UseConsul(this IApplicationBuilder app)
        {
            var consulClient = app.ApplicationServices.GetRequiredService<IConsulClient>();
            var logger = app.ApplicationServices.GetRequiredService<ILoggerFactory>().CreateLogger("AppExtensions");
            var lifetime = app.ApplicationServices.GetRequiredService<IApplicationLifetime>();


            // var uri = new Uri(address);
            // Better approach should be used to set the below settings. I hard coded just to explain.
            var registration = new AgentServiceRegistration()
            {
                ID = $"MyService",
                Name = "WebApplication1",
                Address = "localhost", //$"{uri.Host}",
                Port = 57084  // uri.Port
            };

            logger.LogInformation("Registering with Consul");
            consulClient.Agent.ServiceDeregister(registration.ID).ConfigureAwait(true);
            consulClient.Agent.ServiceRegister(registration).ConfigureAwait(true);

            lifetime.ApplicationStopping.Register(() =>
            {
                logger.LogInformation("Unregistering from Consul");
                consulClient.Agent.ServiceDeregister(registration.ID).ConfigureAwait(true);
            });

            return app;
        }
    }
}

Github repo