Esempio n. 1
0
        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);
        }
Esempio n. 3
0
        /// <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));
        }
Esempio n. 4
0
        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);
            }
        }
Esempio n. 5
0
        /// <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);
        }
Esempio n. 6
0
        /// <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);
        }
Esempio n. 7
0
        /// <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);
        }
Esempio n. 9
0
 public NConsulBuilder AddHealthCheck(AgentServiceCheck check)
 {
     _checks.Add(check);
     return(this);
 }
Esempio n. 10
0
        // 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发起)
        }
Esempio n. 11
0
        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);
                    }
                }
            }
        }
Esempio n. 14
0
        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);
        }
Esempio n. 15
0
        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
                    { }
                });
            });
        }
Esempio n. 16
0
        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);
        }
Esempio n. 18
0
        // 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
        }
Esempio n. 19
0
        //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);
        }
Esempio n. 22
0
        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);
        }
Esempio n. 23
0
        public ConsulServiceSettings WithCheck(AgentServiceCheck check)
        {
            _checks.Add(check);

            return(this);
        }
Esempio n. 24
0
        // 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);
        }
Esempio n. 26
0
        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);
        }
Esempio n. 27
0
        //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));
            }
        }