public AgentServiceCheck CheckTtl() { var check = new AgentServiceCheck { TTL = TimeSpan.FromSeconds(5) }; return check; }
public static IApplicationBuilder UseConsulRegisterService(this IApplicationBuilder app, IHostingEnvironment env) { var loggerFactory = app.ApplicationServices.GetService <ILoggerFactory>(); var lifetime = app.ApplicationServices.GetService <IApplicationLifetime>(); var consul = app.ApplicationServices.GetRequiredService <IConsulClient>(); var serviceDiscoveryOptions = app.ApplicationServices.GetService <IOptions <ServiceDiscoveryOptions> >().Value; var logger = loggerFactory.CreateLogger("ServiceDiscoveryBuilder"); if (string.IsNullOrWhiteSpace(serviceDiscoveryOptions.ServiceName)) { throw new ArgumentException("Service Name must be configured", nameof(serviceDiscoveryOptions.ServiceName)); } IEnumerable <Uri> addresses = null; if (serviceDiscoveryOptions.Endpoints != null && serviceDiscoveryOptions.Endpoints.Length > 0) { logger.LogInformation($"Using {serviceDiscoveryOptions.Endpoints.Length} configured endpoints for service registration."); addresses = serviceDiscoveryOptions.Endpoints.Select(p => new Uri(p)); } else { logger.LogInformation($"Trying to use server.Features to figure out the service endpoints for service registration."); var features = app.Properties["server.Features"] as FeatureCollection;//server.Features 只有在使用 kestrel托管服务时,才可用 addresses = features.Get <IServerAddressesFeature>() .Addresses.Select(p => new Uri(p)); } logger.LogInformation($"Found {addresses.Count()} endpoints:{string.Join(",", addresses.Select(p => p.OriginalString))}."); foreach (var address in addresses) { var serviceId = $"{serviceDiscoveryOptions.ServiceName}_{address.Host}:{address.Port}"; logger.LogInformation($"Registering service {serviceId} for address {address}."); var serviceChecks = new List <AgentServiceCheck>(); //强制必须配置HealthCheckTemplate,否则不向Consul注册服务 if (!string.IsNullOrWhiteSpace(serviceDiscoveryOptions.HealthCheckTemplate)) { var healthCheckUri = new Uri(address, serviceDiscoveryOptions.HealthCheckTemplate).OriginalString; var serviceCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(1), Interval = TimeSpan.FromSeconds(30), HTTP = healthCheckUri }; if (env.IsDevelopment()) { serviceCheck.DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(30); serviceCheck.Interval = TimeSpan.FromSeconds(30); } serviceChecks.Add(serviceCheck); logger.LogInformation($"Adding healthcheck for service {serviceId},checking {healthCheckUri}"); var registration = new AgentServiceRegistration() { Checks = serviceChecks.ToArray(), Address = address.Host, ID = serviceId, Name = serviceDiscoveryOptions.ServiceName, Port = address.Port }; consul.Agent.ServiceRegister(registration).GetAwaiter().GetResult(); lifetime.ApplicationStopping.Register(() => { consul.Agent.ServiceDeregister(registration.ID).GetAwaiter().GetResult(); }); } } return(app); }
/// <summary> /// 注册服务 /// </summary> /// <param name="serviceId">服务id</param> /// <param name="serviceName">服务名</param> /// <param name="serviceAddress">服务地址</param> /// <param name="servicePort">服务端口</param> /// <param name="check">健康检查</param> /// <param name="checks"></param> /// <param name="enableTagOverride"></param> /// <param name="tags"></param> /// <param name="meta"></param> /// <param name="ct"></param> /// <returns></returns> public OrzConsulClient ServiceRegister(string serviceId, string serviceName, string serviceAddress, int servicePort, AgentServiceCheck check = null, AgentServiceCheck[] checks = null, bool enableTagOverride = false, string[] tags = null, IDictionary <string, string> meta = null, CancellationToken ct = default(CancellationToken)) { var asr = new AgentServiceRegistration { ID = serviceId, Name = serviceName, Address = serviceAddress, Port = servicePort, Check = check, Checks = checks, EnableTagOverride = enableTagOverride, Tags = tags, Meta = meta, }; return(ServiceRegister(asr, ct)); }
public static string UseConsul(this IApplicationBuilder app) { using (var scope = app.ApplicationServices.CreateScope()) { var consulOptions = scope.ServiceProvider.GetService <IOptions <ConsulOptions> >(); var fabioOptions = scope.ServiceProvider.GetService <IOptions <FabioOptions> >(); var enabled = consulOptions.Value.enabled; var consulEnabled = Environment.GetEnvironmentVariable("CONSUL_ENABLED")?.ToLowerInvariant(); if (!string.IsNullOrWhiteSpace(consulEnabled)) { enabled = consulEnabled == "true" || consulEnabled == "1"; } if (!enabled) { return(string.Empty); } var address = consulOptions.Value.address; if (string.IsNullOrWhiteSpace(address)) { throw new ArgumentException("Consul address can not be empty.", nameof(consulOptions.Value.pingEndpoint)); } var uniqueId = Guid.NewGuid(); var client = scope.ServiceProvider.GetService <IConsulClient>(); var serviceName = consulOptions.Value.service; var serviceId = $"{serviceName}:{uniqueId}"; var port = consulOptions.Value.port; var pingEndpoint = consulOptions.Value.pingEndpoint; var pingInterval = consulOptions.Value.pingInterval <= 0 ? 5 : consulOptions.Value.pingInterval; var removeAfterInterval = consulOptions.Value.removeAfterInterval <= 0 ? 10 : consulOptions.Value.removeAfterInterval; var registration = new AgentServiceRegistration { Name = serviceName, ID = serviceId, Address = address, Port = port, //Tags = null Tags = fabioOptions.Value.Enabled ? GetFabioTags(serviceName, fabioOptions.Value.Service) : null }; if (consulOptions.Value.pingEnabled)// || fabioOptions.Value.Enabled) { var scheme = address.StartsWith("http", StringComparison.InvariantCultureIgnoreCase) ? string.Empty : "http://"; var check = new AgentServiceCheck { Interval = TimeSpan.FromSeconds(pingInterval), DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(removeAfterInterval), HTTP = $"{scheme}{address}{(port > 0 ? $":{port}" : string.Empty)}/{pingEndpoint}" }; registration.Checks = new[] { check }; } client.Agent.ServiceRegister(registration); return(serviceId); } }
/// <summary> /// use Consul /// 使用consul /// The default health check interface format is http://host:port/HealthCheck /// 默认的健康检查接口格式是 http://host:port/HealthCheck /// </summary> /// <param name="app"></param> /// <returns></returns> public static IApplicationBuilder UseConsul(this IApplicationBuilder app) { IConsulClient consul = app.ApplicationServices.GetRequiredService <IConsulClient>(); IApplicationLifetime appLife = app.ApplicationServices.GetRequiredService <IApplicationLifetime>(); IOptions <ServiceDiscoveryOptions> serviceOptions = app.ApplicationServices.GetRequiredService <IOptions <ServiceDiscoveryOptions> >(); var features = app.Properties["server.Features"] as FeatureCollection; //http://+:80 if (!int.TryParse(features.Get <IServerAddressesFeature>().Addresses.FirstOrDefault()?.Split(':')[2], out int port)) { port = 80; } Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine($"command get host: {HostIpV4Address}"); Console.WriteLine($"real port: {port}"); if (string.IsNullOrEmpty(HostIpV4Address)) { if (!string.IsNullOrWhiteSpace(serviceOptions.Value.SelfAddress)) { var addressTemp = serviceOptions.Value.SelfAddress.Split(':'); HostIpV4Address = addressTemp[0]; Console.WriteLine($"config host: {addressTemp[0]}"); port = int.Parse(addressTemp[1]); Console.WriteLine($"config ort: {addressTemp[1]}"); } else { HostIpV4Address = "localhost"; Console.WriteLine($"config host: {HostIpV4Address}"); } } var serviceId = $"{serviceOptions.Value.ServiceName}_{HostIpV4Address}:{port}"; var httpCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(1), Interval = TimeSpan.FromSeconds(30), HTTP = $"{Uri.UriSchemeHttp}://{HostIpV4Address}:{port}/HealthCheck", }; var registration = new AgentServiceRegistration() { Checks = new[] { httpCheck }, Address = HostIpV4Address.ToString(), ID = serviceId, Name = serviceOptions.Value.ServiceName, Port = port }; consul.Agent.ServiceRegister(registration).GetAwaiter().GetResult(); // 服务应用停止后发注册RestApi服务,停止后不通知consul剔除 //appLife.ApplicationStopping.Register(() => //{ // consul.Agent.ServiceDeregister(serviceId).GetAwaiter().GetResult(); //}); Console.WriteLine($"健康检查服务:{httpCheck.HTTP}"); app.Map("/HealthCheck", s => { s.Run(async context => { await context.Response.WriteAsync("ok"); }); }); return(app); }
/// <summary> /// 使用Consul /// </summary> /// <param name="app"></param> /// <returns></returns> public static IApplicationBuilder UseConsul(this IApplicationBuilder app) { //控制反转获取配置文件 //var config = app.ApplicationServices.GetRequiredService<IConfiguration>().GetSection("Consul"); //获取配置节点 //var section = configuration.GetSection("Consul"); //获取配置 var config = app.ApplicationServices.GetRequiredService <IOptions <ConsulSetting> >().Value; //获取服务地址 Uri server = new Uri(config.server); //获取健康检查地址 string health = config.health;//section.GetValue<string>("health"); //获取服务名 string name = config.name; //section.GetValue<string>("name"); //获取程序运行生命 var life = app.ApplicationServices.GetRequiredService <IHostApplicationLifetime>(); //创建配置客户端 var client = new ConsulClient(option => { option.Address = server; }); //服务检查 var check = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(3), //服务启动多久后注册 Interval = TimeSpan.FromSeconds(10), //心跳检查时间 HTTP = $"{config.host}{health}", //健康检查地址 Timeout = TimeSpan.FromSeconds(15) }; //向Consul注册服务 var register = new AgentServiceRegistration() { Checks = new[] { check }, ID = $"{Guid.NewGuid()}", Address = server.Host, Port = server.Port, Name = name, Tags = new[] { $"{name}" } }; //代理注册服务 client.Agent.ServiceRegister(register).Wait(); //程序停止时、取消注册服务 life.ApplicationStopping.Register(() => { client.Agent.ServiceDeregister(register.ID).Wait(); }); return(app); }
/// <summary> /// 添加Consul的注册以及健康检查到pipeline /// </summary> /// <param name="builder"></param> /// <param name="options"></param> /// <param name="consulClient"></param> /// <param name="applicationLifetime"></param> /// <returns></returns> public static IApplicationBuilder UseConsulServiceDiscoveryAndHealthCheck(this IApplicationBuilder builder, ServiceDiscoveryAndHealthCheckOptions options, IConsulClient consulClient, IHostApplicationLifetime applicationLifetime, ILogger <IStartup> logger, IHostEnvironment env, string iisExternalPort) { IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName()); var address = ipHost.AddressList.GetLocalIPv4().MapToIPv4().ToString(); if (options.ServiceName.IsNullOrEmpty()) { options.ServiceName = env.ApplicationName; } AgentServiceRegistration registration = null; try { var serviceId = $"{options.ServiceName}_{address}:{iisExternalPort}"; var httpCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(options.HealthCheckOptions.DeregisterTimeout), Interval = TimeSpan.FromSeconds(options.HealthCheckOptions.Interval), HTTP = new Uri(new Uri($"{options.Schema}://{address}:{iisExternalPort}"), "HealthCheck").OriginalString }; registration = new AgentServiceRegistration() { Checks = new[] { httpCheck }, Address = address, ID = serviceId, Name = options.ServiceName, Port = int.Parse(iisExternalPort), }; consulClient.Agent.ServiceRegister(registration).GetAwaiter().GetResult(); applicationLifetime.ApplicationStopping.Register(() => { consulClient.Agent.ServiceDeregister(serviceId).GetAwaiter().GetResult(); }); } catch (Exception e) { if (!env.IsDevelopment()) { logger.LogCritical(e, "服务发现注册失败,请检查当前服务发现配置{registration}", registration); } else { logger.LogWarning("服务注册失败"); } } builder.Map("/HealthCheck", (x) => { x.UseMiddleware <HealthCheckMiddleware>(); }); return(builder); }
public static async Task <bool> RegsterService(string consulAgentUrl, string name, string tags, string address, int port, int inerval, string httpcheck, string tcpCheck) { bool statusCode; TimeSpan? nullable; string str; string str1; TimeSpan? nullable1; TimeSpan? nullable2; ConsulClient consulClient = new ConsulClient((ConsulClientConfiguration config) => config.Address = new Uri(consulAgentUrl)); try { IAgentEndpoint agent = consulClient.Agent; AgentServiceRegistration agentServiceRegistration = new AgentServiceRegistration() { Address = address, ID = name, Name = name, Port = port }; AgentServiceRegistration agentServiceRegistration1 = agentServiceRegistration; string str2 = tags; char[] chrArray = new char[] { ',' }; agentServiceRegistration1.Tags = str2.Split(chrArray); AgentServiceRegistration agentServiceRegistration2 = agentServiceRegistration; AgentServiceCheck agentServiceCheck = new AgentServiceCheck(); AgentServiceCheck agentServiceCheck1 = agentServiceCheck; if (!string.IsNullOrEmpty(httpcheck)) { str = httpcheck; } else { str = null; } agentServiceCheck1.HTTP = str; AgentServiceCheck agentServiceCheck2 = agentServiceCheck; if (!string.IsNullOrEmpty(tcpCheck)) { str1 = tcpCheck; } else { str1 = null; } agentServiceCheck2.TCP = str1; AgentServiceCheck agentServiceCheck3 = agentServiceCheck; if (!string.IsNullOrEmpty(httpcheck) || !string.IsNullOrEmpty(tcpCheck)) { nullable1 = new TimeSpan?(TimeSpan.FromSeconds((double)inerval)); } else { nullable = null; nullable1 = nullable; } agentServiceCheck3.Interval = nullable1; AgentServiceCheck agentServiceCheck4 = agentServiceCheck; if (!string.IsNullOrEmpty(httpcheck) || !string.IsNullOrEmpty(tcpCheck)) { nullable = null; nullable2 = nullable; } else { nullable2 = new TimeSpan?(TimeSpan.FromSeconds((double)(2 * inerval))); } agentServiceCheck4.TTL = nullable2; agentServiceCheck.Status = CheckStatus.Passing; agentServiceRegistration2.Check = agentServiceCheck; AgentServiceRegistration agentServiceRegistration3 = agentServiceRegistration; CancellationToken cancellationToken = new CancellationToken(); ConfiguredTaskAwaitable <WriteResult> configuredTaskAwaitable = agent.ServiceRegister(agentServiceRegistration3, cancellationToken).ConfigureAwait(false); statusCode = await configuredTaskAwaitable.StatusCode == HttpStatusCode.OK; } finally { if (consulClient != null) { ((IDisposable)consulClient).Dispose(); } } return(statusCode); }
public NConsulBuilder AddHealthCheck(AgentServiceCheck check) { _checks.Add(check); return(this); }
// 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(); } else { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseCookiePolicy(); app.UseSwagger(c => { c.PreSerializeFilters.Add((doc, request) => { HttpRequest _request = request; StringValues referer; _request.Headers.TryGetValue("Referer", out referer); if (!string.IsNullOrEmpty(referer.ToString()) && referer.ToString().StartsWith("http://localhost:5002")) { doc.BasePath = "/One"; } }); c.RouteTemplate = "/{documentName}/swagger.json"; }); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/One/swagger.json", "One"); c.ShowRequestHeaders(); }); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); var features = app.ServerFeatures; var address = features.Get <IServerAddressesFeature>().Addresses.First(); var uri = new Uri(address); var consulClient = new ConsulClient(x => x.Address = new Uri($"http://10.98.24.53:8500/"));//请求注册的 Consul 地址 var httpCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5), //服务启动多久后注册 Interval = TimeSpan.FromSeconds(10), //健康检查时间间隔,或者称为心跳间隔 HTTP = $"http://{uri.Host}:{uri.Port}/home/health", //健康检查地址 Timeout = TimeSpan.FromSeconds(5) }; // Register service with consul var registration = new AgentServiceRegistration() { Checks = new[] { httpCheck }, ID = Guid.NewGuid().ToString(), Name = "One", Address = uri.Host, Port = uri.Port, Tags = new[] { $"urlprefix-/One" }//添加 urlprefix-/servicename 格式的 tag 标签,以便 Fabio 识别 }; consulClient.Agent.ServiceRegister(registration);//服务启动时注册,内部实现其实就是使用 Consul API 进行注册(HttpClient发起) }
public static void Main(string[] args) { /* using (TcpClient tcpClient = new TcpClient()) * { * try * { * tcpClient.Connect("Consul", 8500); * Console.WriteLine("Port open"); * } * catch (Exception) * { * Console.WriteLine("Port closed"); * } * }*/ var host = CreateWebHostBuilder(args).Build(); #region Consul Configuration ------------------------------------------------------------------------------- var consulClient = new ConsulClient(configuration => { //Check the DockerfileRunArguments on the csProj for more info //Sample params: --network test-net --link Consul:consul // consul the alias of the linkect Consul Container! //It is annoying: Even when I am abble to ping Consul I must add a Link to get it working correctly configuration.Address = new Uri("http://consul:8500"); }); // IP Parameters var hostDnsInfo = Dns.GetHostEntry(Dns.GetHostName()); var ip = hostDnsInfo.AddressList[0].ToString(); var port = 80; // Registration Parameters var name = "data-service"; var id = $"{name}-{Dns.GetHostName()}:{port}"; // Health Check Definition - check on private address within docker network. var tcpCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(5), Interval = TimeSpan.FromSeconds(5), TCP = $"{ip}:{port}" }; var appCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(5), Interval = TimeSpan.FromSeconds(5), HTTP = $"http://{ip}:{port}/api/values" }; //Deregister first consulClient.Agent.ServiceDeregister(id).GetAwaiter().GetResult(); // Service Registration (Gateway on public address, Healthcheck on private address) var registration = new AgentServiceRegistration() { Checks = new[] { appCheck, tcpCheck }, Address = ip, ID = id, Name = name, Port = port, Tags = new[] { "api" } }; #endregion #region Consul Registration -------------------------------------------------------------------------------- consulClient.Agent.ServiceRegister(registration).GetAwaiter().GetResult(); #endregion host.Run(); #region Consul Deregistration ------------------------------------------------------------------------------ consulClient.Agent.ServiceDeregister(id).GetAwaiter().GetResult(); #endregion }
public static IApplicationBuilder UseConsul(this IApplicationBuilder app) { Console.WriteLine("注入consul..."); // 获取主机生命周期管理接口 var lifetime = app.ApplicationServices.GetRequiredService <IHostApplicationLifetime>(); // 获取服务配置项 var consulOptions = AppConfig.GetSection <ConsulServiceOptions>("Consul");; // 获取App配置项 var serverOptions = AppConfig.ServerOptions; // 服务ID必须保证唯一 consulOptions.ServiceId = $"{serverOptions.Name}{serverOptions.WanIp}{serverOptions.Port}".Replace(".", "").ToLower(); var consulClient = new ConsulClient(configuration => { //服务注册的地址,集群中任意一个地址 configuration.Address = new Uri(consulOptions.ConsulAddress); }); var Check = new AgentServiceCheck { // 注册超时 Timeout = TimeSpan.FromSeconds(1), // 服务停止多久后注销服务 DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(1), // 健康检查时间间隔 Interval = TimeSpan.FromSeconds(serverOptions.InspectInterval) }; //健康检查地址 if (serverOptions.Protocol == SyZero.Runtime.Security.ProtocolType.GRPC) { Check.GRPC = $"{serverOptions.WanIp}:{serverOptions.Port}"; Check.GRPCUseTLS = false; } else { Check.HTTP = $"{serverOptions.Protocol}://{serverOptions.WanIp}:{serverOptions.Port}{consulOptions.HealthCheck}"; } // 节点服务注册对象 var registration = new AgentServiceRegistration() { ID = consulOptions.ServiceId, Name = serverOptions.Name, // 服务名 Address = serverOptions.WanIp, Port = serverOptions.Port.ToInt32(), // 服务端口 Check = Check }; // 注册服务 consulClient.Agent.ServiceRegister(registration).Wait(); // 应用程序终止时,注销服务 lifetime.ApplicationStopping.Register(() => { consulClient.Agent.ServiceDeregister(consulOptions.ServiceId).Wait(); }); return(app); }
public async Task RegisterSelfAsync(Action <Dictionary <string, string> > appendMetaAction = null) { var serviceDescription = LocalServiceDescriptionProvider.Build(); var serviceSchema = serviceDescription.ServiceSchema ?? "http"; var registeringServiceAddress = $"{serviceSchema}://{serviceDescription.Host}:{serviceDescription.Port}"; var virtualDirectory = serviceDescription.VirtualDirectory.Trim('/'); var serviceMeta = new Dictionary <string, string> { { ServiceGovernanceConsts.ServiceSchema, serviceSchema } }; if (appendMetaAction != null) { appendMetaAction.Invoke(serviceMeta); } if (!string.IsNullOrEmpty(virtualDirectory)) { serviceMeta.Add(ServiceGovernanceConsts.ServiceVirtualDirectory, serviceDescription.VirtualDirectory); registeringServiceAddress = $"{registeringServiceAddress}/{serviceDescription.VirtualDirectory}"; } var serviceCheck = new AgentServiceCheck { Interval = ServiceGovernanceConfig.ServiceCheckInterval, HTTP = $"{registeringServiceAddress}/{serviceDescription.HealthCheckRoute.Trim('/') ?? string.Empty}", Timeout = ServiceGovernanceConfig.ServiceCheckTimeout, }; if (!IsDevelopmentEnvironment()) { serviceCheck.DeregisterCriticalServiceAfter = ServiceGovernanceConfig.DeregisterCriticalServiceAfter; } var serviceNames = new List <string> { serviceDescription.ServiceName }; if (serviceDescription.ServiceAliases != null && serviceDescription.ServiceAliases.Contains(",")) { foreach (var serviceAlias in serviceDescription.ServiceAliases.Split(',')) { var trimmedAlias = serviceAlias.Trim(); if (!string.IsNullOrEmpty(trimmedAlias)) { serviceNames.Add(trimmedAlias); } } } using (var consulClient = ConsulClientFactory.Create()) { foreach (var serviceName in serviceNames) { var serviceRegistration = new AgentServiceRegistration { Checks = new[] { serviceCheck }, ID = Guid.NewGuid().ToString(), Address = serviceDescription.Host, Port = serviceDescription.Port == 0 ? 80 : serviceDescription.Port, Meta = serviceMeta, }; if (string.IsNullOrEmpty(serviceDescription.ServiceSpace)) { serviceRegistration.Name = serviceName; serviceRegistration.Tags = new[] { $"urlprefix-/{serviceRegistration.Name}" }; } else { serviceRegistration.Name = $"{serviceDescription.ServiceSpace}.{serviceName}"; serviceRegistration.Tags = new[] { serviceDescription.ServiceSpace, $"urlprefix-/{serviceRegistration.Name}" }; } var existingServices = (await consulClient.Catalog.Service(serviceRegistration.Name)).Response; foreach (var service in existingServices) { var registeredServiceAddress = service.GetRegisteredServiceAddress(); if (registeredServiceAddress == registeringServiceAddress) { await consulClient.Agent.ServiceDeregister(service.ServiceID); } } var result = await consulClient.Agent.ServiceRegister(serviceRegistration); if (result.StatusCode == System.Net.HttpStatusCode.OK) { serviceIds.Add(serviceRegistration.Name, serviceRegistration.ID); } } } }
public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, ConsulOptions options = null) { if (options == null) { var configuration = app.ApplicationServices.GetRequiredService <IConfiguration>(); options = configuration.GetSection(ConsulOptionsKey).Get <ConsulOptions>(); } if (string.IsNullOrEmpty(options.Url)) { throw new ArgumentNullException(nameof(options.Url)); } var logger = app.ApplicationServices.GetService <ILoggerFactory>().CreateLogger(typeof(ConsulExtensions).FullName); var lifetime = app.ApplicationServices.GetRequiredService <IHostApplicationLifetime>(); var currentAssembly = Assembly.GetEntryAssembly(); var serviceName = currentAssembly.GetName().Name; var serviceVersion = currentAssembly.GetName().Version?.ToString(); var consulUrl = options.Url; logger.LogInformation($"consulUrl:{consulUrl}"); var registration = new AgentServiceRegistration() { ID = Guid.NewGuid().ToString() + "_" + serviceName + ":" + serviceVersion, Name = serviceName, }; lifetime.ApplicationStarted.Register(() => { try { var addressFeature = app.ServerFeatures.Get <IServerAddressesFeature>(); logger.LogInformation($"addressFeature:{string.Join(",", addressFeature.Addresses)}"); string ip; string scheme; int port; { var address = new Uri(addressFeature.Addresses.FirstOrDefault()); port = address.Port; scheme = address.Scheme; ip = address.Host; if (ip == "[::]") { ip = Utils.IpUtils.GetIp(options.IpSegment); } } if (string.IsNullOrEmpty(ip)) { throw new Exception("ip is null"); } logger.LogInformation($"scheme:{scheme} ip:{ip} port:{port}"); var httpCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5), Interval = TimeSpan.FromSeconds(10), HTTP = $"{scheme}://{ip}:{port}{options.CheckPath}", Timeout = TimeSpan.FromSeconds(5), TLSSkipVerify = false, }; registration.Checks = new[] { httpCheck }; registration.Address = ip; registration.Port = port; registration.Meta = options.Meta ?? new Dictionary <string, string>(); registration.Tags = options.Tags?.ToArray(); registration.Meta.Add("service-ver", serviceVersion); logger.LogInformation($"to register httpCheck url:{httpCheck.HTTP} address:{registration.Address} port:{registration.Port} id:{registration.ID} serverName:{registration.Name}"); var client = new ConsulClient(m => { m.Address = new Uri(consulUrl); m.Token = options.Token; }); client.Agent.ServiceRegister(registration).Wait(); } catch { //注册出错=>退出软件 lifetime.StopApplication(); } }); lifetime.ApplicationStopping.Register(() => { var client = new ConsulClient(m => { m.Address = new Uri(consulUrl); m.Token = options.Token; }); logger.LogInformation($"to deregister service,id:{registration.ID} serverName:{registration.Name}"); client.Agent.ServiceDeregister(registration.ID).Wait(); }); app.Map(options.CheckPath, app2 => { app2.Run(context => { return(context.Response.WriteAsync("ok")); }); }); return(app); }
public static void RegisterToConsul(this IApplicationBuilder app, IConfiguration configuration, IApplicationLifetime lifetime) { lifetime.ApplicationStarted.Register(() => { string serviceName = configuration.GetValue <string>("consulConfig:serviceName"); string serviceIP = configuration.GetValue <string>("consulConfig:serviceIP"); string consulClientUrl = configuration.GetValue <string>("consulConfig:consulClientUrl"); string healthCheckRelativeUrl = configuration.GetValue <string>("consulConfig:healthCheckRelativeUrl"); int healthCheckIntervalInSecond = configuration.GetValue <int>("consulConfig:healthCheckIntervalInSecond"); ICollection <string> listenUrls = app.ServerFeatures.Get <IServerAddressesFeature>().Addresses; if (string.IsNullOrWhiteSpace(serviceName)) { throw new Exception("Please use --serviceName=yourServiceName to set serviceName"); } if (string.IsNullOrEmpty(consulClientUrl)) { consulClientUrl = "http://127.0.0.1:8500"; } if (string.IsNullOrWhiteSpace(healthCheckRelativeUrl)) { healthCheckRelativeUrl = "health"; } healthCheckRelativeUrl = healthCheckRelativeUrl.TrimStart('/'); if (healthCheckIntervalInSecond <= 0) { healthCheckIntervalInSecond = 1; } string protocol; int servicePort = 0; if (!TryGetServiceUrl(listenUrls, out protocol, ref serviceIP, out servicePort, out var errorMsg)) { throw new Exception(errorMsg); } var consulClient = new ConsulClient(ConsulClientConfiguration => ConsulClientConfiguration.Address = new Uri(consulClientUrl)); var httpCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(10),//服务启动多久后注册 Interval = TimeSpan.FromSeconds(healthCheckIntervalInSecond), HTTP = $"{protocol}://{serviceIP}:{servicePort}/{healthCheckRelativeUrl}", Timeout = TimeSpan.FromSeconds(2) }; // 生成注册请求 var registration = new AgentServiceRegistration() { Checks = new[] { httpCheck }, ID = Guid.NewGuid().ToString(), Name = serviceName, Address = serviceIP, Port = servicePort, Meta = new Dictionary <string, string>() { ["Protocol"] = protocol }, Tags = new[] { $"{protocol}" } }; consulClient.Agent.ServiceRegister(registration).Wait(); //服务停止时, 主动发出注销 lifetime.ApplicationStopping.Register(() => { try { consulClient.Agent.ServiceDeregister(registration.ID).Wait(); } catch { } }); }); }
public static IApplicationBuilder UseConsul(this IApplicationBuilder app) { var applicationLifetime = app.ApplicationServices.GetService <IHostApplicationLifetime>(); if (applicationLifetime == null) { throw new ArgumentNullException(nameof(applicationLifetime)); } var consulClient = app.ApplicationServices.GetService <IConsulClient>(); if (consulClient == null) { throw new ArgumentNullException(nameof(consulClient)); } var serviceOptions = app.ApplicationServices.GetRequiredService <IOptions <ServiceDiscoveryOptions> >(); if (serviceOptions == null) { throw new ArgumentNullException(nameof(serviceOptions)); } var env = app.ApplicationServices.GetRequiredService <IHostEnvironment>(); if (env == null) { throw new ArgumentNullException(nameof(env)); } //获取服务启动地址绑定信息 var features = app.Properties["server.Features"] as FeatureCollection; var addresses = features.Get <IServerAddressesFeature>() .Addresses .Select(o => new Uri(o)); //在服务启动时,向Consul 中心进行注册 applicationLifetime.ApplicationStarted.Register(() => { foreach (var address in addresses) { //设置启动服务的ID var serviceId = $"{serviceOptions.Value.ServiceName}_{address.Host}:{address.Port}"; //设置健康检查 var httpCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(1), //错误时间超过1分钟,移除 Interval = TimeSpan.FromSeconds(3), //30秒检查一次 HTTP = new Uri(address, "HealthCheck").OriginalString }; var registration = new AgentServiceRegistration() { Checks = new[] { httpCheck }, //配置健康检查 Address = address.Host, //启动服务的地址 Port = address.Port, //启动服务的端口 ID = serviceId, //服务唯一ID Name = serviceOptions.Value.ServiceName //对外服务名称 }; //向Consul 中心进行注册 consulClient.Agent.ServiceRegister(registration).GetAwaiter().GetResult(); } }); //在程序停止时,向Consul 中心进行注销 applicationLifetime.ApplicationStopped.Register(() => { foreach (var address in addresses) { //设定服务Id(全局唯一 unique) var serviceId = $"{serviceOptions.Value.ServiceName}_{address.Host}:{address.Port}"; consulClient.Agent.ServiceDeregister(serviceId).GetAwaiter().GetResult(); } }); return(app); }
/// <summary> /// 使用consul /// 默认的健康检查接口格式是 http://host:port/HealthCheck /// </summary> /// <param name="app"></param> /// <returns></returns> public static IApplicationBuilder UseConsul(this IApplicationBuilder app) { IConsulClient consul = app.ApplicationServices.GetRequiredService <IConsulClient>(); IApplicationLifetime appLife = app.ApplicationServices.GetRequiredService <IApplicationLifetime>(); IOptions <ServiceRegisterOptions> serviceOptions = app.ApplicationServices.GetRequiredService <IOptions <ServiceRegisterOptions> >(); //TODO: 这两句代码,必须使用Microsoft.NETCore.App 2.1 的程序集 //var features = app.Properties["server.Features"] as FeatureCollection; //var port = new Uri(features.Get<IServerAddressesFeature>().Addresses.FirstOrDefault()).Port; //获取端口 var port = serviceOptions.Value.ServicePort; //获取配置文件的端口 var address = serviceOptions.Value.ServiceIpAddress; //获取配置文件的IP地址 Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine($"application port is :{port}"); var addressIpv4Hosts = NetworkInterface.GetAllNetworkInterfaces() .OrderByDescending(c => c.Speed) .Where(c => c.NetworkInterfaceType != NetworkInterfaceType.Loopback && c.OperationalStatus == OperationalStatus.Up); foreach (var item in addressIpv4Hosts) { if (string.IsNullOrEmpty(address)) { //这是ipv4的ip地址 var firstIpV4Address = item.GetIPProperties().UnicastAddresses.Where(c => c.Address.AddressFamily == AddressFamily.InterNetwork).Select(c => c.Address).FirstOrDefault()?.ToString(); if (string.IsNullOrEmpty(firstIpV4Address)) { continue; } if (firstIpV4Address.Contains("localhost")) { continue; } address = firstIpV4Address; } var serviceId = $"{serviceOptions.Value.ServiceName}_{address}:{port}"; var httpCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(1), Interval = TimeSpan.FromSeconds(10), //健康检查间隔10s,原来是30s HTTP = $"{Uri.UriSchemeHttp}://{address}:{port}/HealthCheck" //这个是默认健康检查接口 }; var registration = new AgentServiceRegistration() { Checks = new[] { httpCheck }, Address = address, ID = serviceId, Name = serviceOptions.Value.ServiceName, Port = port }; bool retry = true; while (retry) { try { consul.Agent.ServiceRegister(registration).GetAwaiter().GetResult(); retry = false; } catch (Exception e) { Console.WriteLine(e); } finally { Thread.Sleep(1000 * 5); } } //当服务停止后想consul发送的请求 appLife.ApplicationStopping.Register(() => { consul.Agent.ServiceDeregister(serviceId).GetAwaiter().GetResult(); }); Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine($"health check service:{httpCheck.HTTP}"); } return(app); }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env , MagicOnionServiceDefinition magicOnion , IHostApplicationLifetime lifetime ) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseMagicOnionSwagger(magicOnion.MethodHandlers, new SwaggerOptions("MagicOnion.Server", "Swagger Integration Test", "/") { XmlDocumentPath = Path.Combine(PlatformServices.Default.Application.ApplicationBasePath, "RpcWebApi.xml") }); app.UseMagicOnionHttpGateway(magicOnion.MethodHandlers, new Channel("127.0.0.1:19021", ChannelCredentials.Insecure)); //app.UseAbp(); app.UseMvc(routes => { routes.MapRoute( name: "defaultWithArea", template: "{area}/{controller=Home}/{action=Index}/{id?}"); routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); #region 注册到consul ServiceEntity serviceEntity = new ServiceEntity { IP = "127.0.0.1", Port = 19021, ServiceName = "RpcWebApi", ConsulIP = "127.0.0.1", ConsulPort = 8500 }; var consulClient = new ConsulClient(x => x.Address = new Uri($"http://{serviceEntity.ConsulIP}:{serviceEntity.ConsulPort}"));//请求注册的 Consul 地址 var httpCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5), //服务启动多久后注册 Interval = TimeSpan.FromSeconds(10), //健康检查时间间隔,或者称为心跳间隔 //HTTP = $"http://{serviceEntity.IP}:5000/api/values",//健康检查地址 HTTP = $"http://{serviceEntity.IP}:5000/health/check", Timeout = TimeSpan.FromSeconds(5) }; var registration = new AgentServiceRegistration() { Checks = new[] { httpCheck }, ID = Guid.NewGuid().ToString(), //集群中的单个服务名称 Name = serviceEntity.ServiceName, //集群取名称 Address = serviceEntity.IP, Port = serviceEntity.Port, Tags = new[] { $"urlprefix-/{serviceEntity.ServiceName}" }//添加 urlprefix-/servicename 格式的 tag 标签,以便 Fabio 识别 }; consulClient.Agent.ServiceRegister(registration);//服务启动时注册,内部实现其实就是使用 Consul API 进行注册(HttpClient发起) lifetime.ApplicationStopping.Register(() => { consulClient.Agent.ServiceDeregister(registration.ID).Wait();//服务停止时取消注册 }); #endregion }
//Returns unique service ID used for removing the service from registry. public static string UseConsul(this IApplicationBuilder app) { using (var scope = app.ApplicationServices.CreateScope()) { var consulOptions = scope.ServiceProvider.GetService <IOptions <ConsulOptions> >(); var fabioOptions = scope.ServiceProvider.GetService <IOptions <FabioOptions> >(); var enabled = consulOptions.Value.Enabled; var consulEnabled = Environment.GetEnvironmentVariable("CONSUL_ENABLED")?.ToLowerInvariant(); if (!string.IsNullOrWhiteSpace(consulEnabled)) { enabled = consulEnabled == "true" || consulEnabled == "1"; } if (!enabled) { return(string.Empty); } var address = consulOptions.Value.Address; if (string.IsNullOrWhiteSpace(address)) { throw new ArgumentException("Consul address can not be empty.", nameof(consulOptions.Value.PingEndpoint)); } //https://cecilphillip.com/using-consul-for-service-discovery-with-asp-net-core/ // Retrieve Consul client from DI var uniqueId = scope.ServiceProvider.GetService <IServiceId>().Id; var client = scope.ServiceProvider.GetService <IConsulClient>(); var serviceName = consulOptions.Value.Service; //create unique serviceId per service instance create, init standalone service after creation separately. //use when we have multiple instance of a particular microservice and because each microservice has same name //we need distinguish between services so for this case and we use serviceId var serviceId = $"{serviceName}:{uniqueId}"; var port = consulOptions.Value.Port; var pingEndpoint = consulOptions.Value.PingEndpoint; var pingInterval = consulOptions.Value.PingInterval <= 0 ? 5 : consulOptions.Value.PingInterval; var removeAfterInterval = consulOptions.Value.RemoveAfterInterval <= 0 ? 10 : consulOptions.Value.RemoveAfterInterval; // Register service with consul var registration = new AgentServiceRegistration { Name = serviceName, //name use for group name a specific service ID = serviceId, //unique name of each instance of a service in a group Address = address, Port = port, //setup fabio tags as SSSD on consul and fabio create a routing table Tags = fabioOptions.Value.Enabled ? GetFabioTags(serviceName, fabioOptions.Value.Service) : null }; //https://cecilphillip.com/using-consul-for-health-checks-with-asp-net-core/ //PingEnabled for checking Health if (consulOptions.Value.PingEnabled || fabioOptions.Value.Enabled) { var scheme = address.StartsWith("http", StringComparison.InvariantCultureIgnoreCase) ? string.Empty : "http://"; var check = new AgentServiceCheck { Interval = TimeSpan.FromSeconds(pingInterval), DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(removeAfterInterval), HTTP = $"{scheme}{address}{(port > 0 ? $":{port}" : string.Empty)}/{pingEndpoint}" }; registration.Checks = new[] { check }; } client.Agent.ServiceRegister(registration); return(serviceId); } }
/// <summary> /// use Consul /// 使用consul /// The default health check interface format is http://host:port/HealthCheck /// 默认的健康检查接口格式是 http://host:port/HealthCheck /// </summary> /// <param name="app"></param> /// <returns></returns> public static IApplicationBuilder UseConsul(this IApplicationBuilder app) { IConsulClient consul = app.ApplicationServices.GetRequiredService <IConsulClient>(); IApplicationLifetime appLife = app.ApplicationServices.GetRequiredService <IApplicationLifetime>(); IOptions <ServiceDiscoveryOptions> serviceOptions = app.ApplicationServices.GetRequiredService <IOptions <ServiceDiscoveryOptions> >(); var features = app.Properties["server.Features"] as FeatureCollection; var port = new Uri(features.Get <IServerAddressesFeature>() .Addresses .FirstOrDefault()).Port; Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine($"application port is :{port}"); var addressIpv4Hosts = NetworkInterface.GetAllNetworkInterfaces() .OrderByDescending(c => c.Speed) .Where(c => c.NetworkInterfaceType != NetworkInterfaceType.Loopback && c.OperationalStatus == OperationalStatus.Up); foreach (var item in addressIpv4Hosts) { var props = item.GetIPProperties(); //this is ip for ipv4 //这是ipv4的ip地址 var firstIpV4Address = props.UnicastAddresses .Where(c => c.Address.AddressFamily == AddressFamily.InterNetwork) .Select(c => c.Address) .FirstOrDefault().ToString(); var serviceId = $"{serviceOptions.Value.ServiceName}_{firstIpV4Address}:{port}"; var httpCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(1), Interval = TimeSpan.FromSeconds(30), //this is default health check interface //这个是默认健康检查接口 HTTP = $"{Uri.UriSchemeHttp}://{firstIpV4Address}:{port}/HealthCheck", }; var registration = new AgentServiceRegistration() { Checks = new[] { httpCheck }, Address = firstIpV4Address.ToString(), ID = serviceId, Name = serviceOptions.Value.ServiceName, Port = port }; consul.Agent.ServiceRegister(registration).GetAwaiter().GetResult(); //send consul request after service stop //当服务停止后想consul发送的请求 appLife.ApplicationStopping.Register(() => { consul.Agent.ServiceDeregister(serviceId).GetAwaiter().GetResult(); }); Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine($"health check service:{httpCheck.HTTP}"); } //register localhost address //注册本地地址 var localhostregistration = new AgentServiceRegistration() { Checks = new[] { new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(1), Interval = TimeSpan.FromSeconds(30), HTTP = $"{Uri.UriSchemeHttp}://localhost:{port}/HealthCheck", } }, Address = "localhost", ID = $"{serviceOptions.Value.ServiceName}_localhost:{port}", Name = serviceOptions.Value.ServiceName, Port = port }; consul.Agent.ServiceRegister(localhostregistration).GetAwaiter().GetResult(); //send consul request after service stop //当服务停止后想consul发送的请求 appLife.ApplicationStopping.Register(() => { consul.Agent.ServiceDeregister(localhostregistration.ID).GetAwaiter().GetResult(); }); app.Map("/HealthCheck", s => { s.Run(async context => { await context.Response.WriteAsync("ok"); }); }); return(app); }
public static IApplicationBuilder RegisterWithConsul(this IApplicationBuilder app) { var consulClient = app.ApplicationServices .GetRequiredService <IConsulClient>(); var configuration = app.ApplicationServices .GetRequiredService <IConfiguration>(); var lifetime = app.ApplicationServices .GetRequiredService <IApplicationLifetime>(); // Get server URI and IP address var features = app.Properties["server.Features"] as FeatureCollection; var addresses = features.Get <IServerAddressesFeature>(); var address = addresses.Addresses.First(); var uri = new Uri(address); var ip = Dns.GetHostEntry(uri.Host).AddressList.FirstOrDefault(x => x.AddressFamily == AddressFamily.InterNetwork); // Get configured service name and id, and update id with a random number for replica handling var random = new Random(); var serviceId = configuration["consulConfig:serviceID"] + $"_{random.Next().ToString()}"; var serviceName = configuration["consulConfig:serviceName"]; var serviceTags = configuration.GetSection("consulConfig:serviceTags").Get <List <string> >().ToArray(); // AgentCheck - Possible health check options: // - http://michaco.net/blog/ServiceDiscoveryAndHealthChecksInAspNetCoreWithConsul var tcpCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5), Interval = TimeSpan.FromSeconds(2), TCP = $"{ip}:{uri.Port}" }; var httpCheck = new AgentServiceCheck { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5), Interval = TimeSpan.FromSeconds(2), HTTP = $"{uri.Scheme}://{ip}:{uri.Port}/status" }; // Register service with consul var registration = new AgentServiceRegistration { ID = $"{serviceId}-{uri.Port}", Name = serviceName, Address = $"{ip}", Port = uri.Port, Tags = serviceTags, Checks = new[] { tcpCheck, httpCheck } }; Console.WriteLine("Registering with Consul"); Console.WriteLine($"IP: {ip}"); consulClient.Agent.ServiceDeregister(registration.ID).Wait(); consulClient.Agent.ServiceRegister(registration).Wait(); // Enable deregistration of service from consul during clean shutdown lifetime.ApplicationStopping.Register(() => { Console.WriteLine("Deregistering from Consul"); consulClient.Agent.ServiceDeregister(registration.ID).Wait(); }); return(app); }
private static AgentServiceRegistration CreateConsulAgentRegistration(this IConveyBuilder builder, ConsulOptions options) { var enabled = options.Enabled; var consulEnabled = Environment.GetEnvironmentVariable("CONSUL_ENABLED")?.ToLowerInvariant(); if (!string.IsNullOrWhiteSpace(consulEnabled)) { enabled = consulEnabled == "true" || consulEnabled == "1"; } if (!enabled) { return(null); } if (string.IsNullOrWhiteSpace(options.Address)) { throw new ArgumentException("Consul address can not be empty.", nameof(options.PingEndpoint)); } var uniqueId = string.Empty; using (var serviceProvider = builder.Services.BuildServiceProvider()) { uniqueId = serviceProvider.GetRequiredService <IServiceId>().Id; } var pingInterval = options.PingInterval <= 0 ? 5 : options.PingInterval; var removeAfterInterval = options.RemoveAfterInterval <= 0 ? 10 : options.RemoveAfterInterval; var registration = new AgentServiceRegistration { Name = options.Service, ID = $"{options.Service}:{uniqueId}", Address = options.Address, Port = options.Port }; if (!options.PingEnabled) { return(registration); } var scheme = options.Address.StartsWith("http", StringComparison.InvariantCultureIgnoreCase) ? string.Empty : "http://"; var check = new AgentServiceCheck { Interval = TimeSpan.FromSeconds(pingInterval), DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(removeAfterInterval), HTTP = $"{scheme}{options.Address}{(options.Port > 0 ? $":{options.Port}" : string.Empty)}/" + $"{options.PingEndpoint}" }; registration.Checks = new[] { check }; return(registration); }
public ConsulServiceSettings WithCheck(AgentServiceCheck check) { _checks.Add(check); return(this); }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure( IApplicationBuilder app, IApplicationLifetime appLife, ILoggerFactory loggerFactory, IOptions <ServiceDisvoveryOptions> serviceDisvoveryOptions, IConsulClient consul) { //var serviceId = "servicename:56688"; //var httpCheck = new AgentServiceCheck() //{ // DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(10), // Interval = TimeSpan.FromSeconds(30), // HTTP = $"http://127.0.0.1:56688/HealthCheck" //}; //var registration = new AgentServiceRegistration() //{ // ID = "servicename:56688", // Address = "127.0.0.1", // Check = httpCheck, // Name = "servicename1", // Port = 56688 //}; //consul.Agent.ServiceRegister(registration).GetAwaiter().GetResult(); //appLife.ApplicationStopping.Register(() => //{ // consul.Agent.ServiceDeregister(serviceId).GetAwaiter().GetResult(); //}); var features = app.Properties["server.Features"] as FeatureCollection; var addresses = features.Get <IServerAddressesFeature>() .Addresses .Select(p => new Uri(p)); foreach (var address in addresses) { var serviceId = $"{serviceDisvoveryOptions.Value.ServiceName}_{address.Host}:{address.Port}"; var httpCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(30), Interval = TimeSpan.FromSeconds(30), HTTP = new Uri(address, "HealthCheck").OriginalString }; var registration = new AgentServiceRegistration() { Check = httpCheck, Address = address.Host, ID = serviceId, Name = serviceDisvoveryOptions.Value.ServiceName, Port = address.Port }; consul.Agent.ServiceRegister(registration).GetAwaiter().GetResult(); appLife.ApplicationStopping.Register(() => { consul.Agent.ServiceDeregister(serviceId).GetAwaiter().GetResult(); }); } app.UseMvc(); }
public static IApplicationBuilder UseConsul(this IApplicationBuilder app) { var configuration = app.ApplicationServices.GetRequiredService <IConfiguration>(); var serviceName = configuration.GetSection("ServiceName").Value; var consulClient = app.ApplicationServices.GetRequiredService <IConsulClient>(); var logger = app.ApplicationServices.GetRequiredService <ILoggerFactory>(); var lifeTime = app.ApplicationServices.GetRequiredService <IApplicationLifetime>(); if (!(app.Properties["server.Features"] is FeatureCollection features)) { return(app); } var addresses = features.Get <IServerAddressesFeature>(); var address = addresses.Addresses.First(); // foreach (var item in addresses.Addresses) // { // Console.WriteLine($"inside loop - address = {item}"); // } Console.WriteLine($"address = {address}"); // var uri = new Uri(address); // Console.WriteLine($"Host: {uri.Host}"); //get host name and IP var hostName = Dns.GetHostName(); // get container id var ip = Dns.GetHostEntry(hostName).AddressList.FirstOrDefault(x => x.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork); Console.WriteLine($"Host Name: {hostName}, IP Address: {ip}"); // to add this service with Fabio Load balancer add httpcheck and tags in registration var httpcheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5), Interval = TimeSpan.FromSeconds(10), HTTP = $"http://{ip}:{80}/Health/IsAlive", Timeout = TimeSpan.FromSeconds(5) }; // register service with Consul var registration = new AgentServiceRegistration() { /* * ID = $"{serviceName}-{uri.Port}", * Name = serviceName, * Address = $"{uri.Host}", * Port = uri.Port */ ID = $"{serviceName}-{Guid.NewGuid().ToString()}", Name = serviceName, Address = $"{ip}", // $"{hostName}", Port = 80, // this is for fabio LB Tags = new[] { $"urlprefix-/" }, // end with slash (/) to catch all route Checks = new[] { httpcheck } }; //logger.LogInformation("Registering with Consul"); consulClient.Agent.ServiceDeregister(registration.ID).ConfigureAwait(true); consulClient.Agent.ServiceRegister(registration).ConfigureAwait(true); lifeTime.ApplicationStopped.Register(() => { //logger.LogInformation("Unregistering from Consul"); consulClient.Agent.ServiceDeregister(registration.ID).ConfigureAwait(true); }); return(app); }
public static IApplicationBuilder UseConsul(this IApplicationBuilder app, bool healthCheck = false) { //var logger = app.ApplicationServices.GetRequiredService<ILoggerFactory>().CreateLogger("Illusion.Common.Consul"); var logger = app.ApplicationServices.GetRequiredService <ILoggerFactory>().CreateLogger(typeof(ServiceCollectionExtensions)); var configuration = app.ApplicationServices.GetRequiredService <IConfiguration>(); var settings = configuration.GetSection(ConsulRegistrationSettings.SectionName).Get <ConsulRegistrationSettings>(); settings.Id = $"{settings.Name}:{configuration.GetValue<string>("COMPUTERNAME")}"; //settings.Meta = new Dictionary<string, string>() //{ // {"Version", VersionInfo.Version} //}; var consulClient = app.ApplicationServices.GetRequiredService <IConsulClient>(); var lifetime = app.ApplicationServices.GetRequiredService <IHostApplicationLifetime>(); if (!(app.Properties["server.Features"] is FeatureCollection features)) { return(app); } var addresses = features.Get <IServerAddressesFeature>(); var address = addresses.Addresses.FirstOrDefault(); if (!Uri.TryCreate(address, UriKind.RelativeOrAbsolute, out var uri)) { // fallback throw new Exception($"Invalid registration address {address}"); } var checks = new List <AgentServiceCheck>(); if (healthCheck) { var healthServiceCheck = new AgentServiceCheck { HTTP = $"http://{uri.Host}:{uri.Port}/health", TLSSkipVerify = true, Interval = TimeSpan.FromSeconds(10), Timeout = TimeSpan.FromSeconds(1), DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(1), }; checks.Add(healthServiceCheck); } var registration = new AgentServiceRegistration() { Meta = settings.Meta, Tags = settings.Tags, ID = settings.Id, Name = settings.Name, Address = uri.Host, Port = uri.Port, Checks = checks.ToArray() }; logger.LogDebug("Register {@Registration}", registration); consulClient.Agent.ServiceDeregister(registration.ID).ConfigureAwait(true); consulClient.Agent.ServiceRegister(registration).ConfigureAwait(true); lifetime.ApplicationStopping.Register(() => { logger.LogDebug($"Deregister {registration.ID} from Consul"); consulClient.Agent.ServiceDeregister(registration.ID).ConfigureAwait(true); }); return(app); }
//Returns unique service ID used for removing the service from registry. public static void UseConsul(this IApplicationBuilder app) { using (var scope = app.ApplicationServices.CreateScope()) { var consulOptions = scope.ServiceProvider.GetService <ConsulOptions>(); var enabled = consulOptions.Enabled; var consulEnabled = Environment.GetEnvironmentVariable("CONSUL_ENABLED")?.ToLowerInvariant(); if (!string.IsNullOrWhiteSpace(consulEnabled)) { enabled = consulEnabled == "true" || consulEnabled == "1"; } if (!enabled) { return; } var address = consulOptions.Address; if (string.IsNullOrWhiteSpace(address)) { throw new ArgumentException("Consul address can not be empty.", nameof(consulOptions.PingEndpoint)); } var uniqueId = scope.ServiceProvider.GetService <IServiceId>().Id; var client = scope.ServiceProvider.GetService <IConsulClient>(); var serviceName = consulOptions.Service; var serviceId = $"{serviceName}:{uniqueId}"; var port = consulOptions.Port; var pingEndpoint = consulOptions.PingEndpoint; var pingInterval = consulOptions.PingInterval <= 0 ? 5 : consulOptions.PingInterval; var removeAfterInterval = consulOptions.RemoveAfterInterval <= 0 ? 10 : consulOptions.RemoveAfterInterval; IEnumerable <string> urlPrefixes; if (consulOptions.UrlPrefixes != null) { urlPrefixes = consulOptions.UrlPrefixes; } else { urlPrefixes = Assembly.GetEntryAssembly().DefinedTypes .Where(t => t.IsClass && typeof(BaristaController).IsAssignableFrom(t)) .ToDictionary(t => t, t => t.GetCustomAttribute(typeof(RouteAttribute)) as RouteAttribute) .Where(kvp => kvp.Value?.Template?.StartsWith("api/") == true) .Select(kvp => kvp.Value.Template); } var registration = new AgentServiceRegistration { Name = serviceName, ID = serviceId, Address = address, Port = port, Tags = urlPrefixes.Select(urlPrefix => $"urlprefix-/{urlPrefix}").ToArray() }; Console.WriteLine("Registration prefixes:"); foreach (var tag in registration.Tags) { Console.WriteLine($"- {tag}"); } if (consulOptions.PingEnabled) { var scheme = address.StartsWith("http", StringComparison.InvariantCultureIgnoreCase) ? string.Empty : "http://"; var check = new AgentServiceCheck { Interval = TimeSpan.FromSeconds(pingInterval), DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(removeAfterInterval), HTTP = $"{scheme}{address}{(port > 0 ? $":{port}" : string.Empty)}/{pingEndpoint}" }; registration.Checks = new[] { check }; } var lifetime = scope.ServiceProvider.GetService <IApplicationLifetime>(); lifetime.ApplicationStarted.Register(() => client.Agent.ServiceRegister(registration)); lifetime.ApplicationStopped.Register(() => client.Agent.ServiceDeregister(serviceId)); } }