/// <summary> /// 使用GRpc注册Consul /// </summary> /// <param name="app">应用生成器</param> /// <returns>应用生成器</returns> public static IApplicationBuilder UseGRpcRegisterConsul(this IApplicationBuilder app) { // 获取consul配置对象 var consulConfig = app.ApplicationServices.GetRequiredService <IOptions <ConsulOptions> >().Value; // 获取本服务的地址,如果不为空,则直接取。否则取配置选项里的服务地址 if (string.IsNullOrWhiteSpace(consulConfig.ServiceAddress)) { consulConfig.ServiceAddress = NetworkUtil.FilterUrl(app.ApplicationServices.GetService <IServerAddressesFeature>().Addresses.FirstOrDefault()); if (string.IsNullOrWhiteSpace(consulConfig.ServiceAddress)) { throw new ArgumentNullException("服务地址不能为空"); } } // 注册到Consul var serviceUri = new Uri(consulConfig.ServiceAddress); var agentCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(consulConfig.ServiceCheck.DeregisterCriticalServiceAfter), Interval = TimeSpan.FromSeconds(consulConfig.ServiceCheck.Interval), GRPC = $"{serviceUri.Host}:{serviceUri.Port}", GRPCUseTLS = string.Compare(serviceUri.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase) == 0, Timeout = TimeSpan.FromSeconds(consulConfig.ServiceCheck.Timeout), }; consulBuilder.AddHealthCheck(agentCheck) .RegisterService(consulConfig.ServiceName, serviceUri.Host, serviceUri.Port, consulConfig.Tags); return(app); }
/// <summary> /// 使用哈希+IP负载均衡 /// </summary> /// <param name="app">应用生成器</param> /// <param name="port">端口</param> /// <returns>应用生成器</returns> public static IApplicationBuilder UseHashIpPortLoadBalance(this IApplicationBuilder app, int port = 0) { if (port == 0) { var add = app.ApplicationServices.GetService <IServerAddressesFeature>().Addresses.FirstOrDefault(); localPort = NetworkUtil.GetPortFromDomain(NetworkUtil.FilterUrl(add)); } else { localPort = port; } HashIpPortLoadBalance.GetPort = () => localPort; return(app); }
/// <summary> /// 创建Consul客户端注册并根据选项进行配置 /// </summary> /// <param name="options">选项配置</param> /// <param name="getLocalServiceAddress">回调获取本地服务地址</param> /// <returns>Consul客户端</returns> public static ConsulClient CreateConsulClientRegister(ConsulOptions options, Func <string> getLocalServiceAddress = null) { if (options == null) { throw new ArgumentNullException("选项配置不能为null"); } if (string.IsNullOrWhiteSpace(options.ConsulAddress)) { throw new ArgumentNullException("Consul地址不能为空"); } if (string.IsNullOrWhiteSpace(options.ServiceName)) { throw new ArgumentNullException("服务名不能为空"); } // 服务ID,如果有配置指定,则使用配置,否则由程序生成唯一 options.ServiceId = options.ServiceId ?? $"{NetworkUtil.LocalIP}_{StringUtil.NewShortGuid()}"; // 定义consul客户端对象 var consulClient = new ConsulClient(clientConfig => { clientConfig.Address = new Uri(options.ConsulAddress); clientConfig.Datacenter = options.Datacenter; }); // 获取本服务的地址,如果不为空,则直接取。否则取配置选项里的服务地址 if (string.IsNullOrWhiteSpace(options.ServiceAddress) && getLocalServiceAddress != null) { options.ServiceAddress = NetworkUtil.FilterUrl(getLocalServiceAddress()); } if (string.IsNullOrWhiteSpace(options.ServiceAddress)) { throw new ArgumentNullException("服务地址不能为空"); } var serviceUri = new Uri(options.ServiceAddress); // 定义一个代理服务注册对象 var registration = new AgentServiceRegistration() { ID = options.ServiceId, Tags = options.Tags, Check = new AgentServiceCheck() // 定义健康检测对象 { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(options.ServiceCheck.DeregisterCriticalServiceAfter), // 服务停止后多久注销服务 HTTP = $"{serviceUri.Scheme}://{serviceUri.Host}:{serviceUri.Port}{options.ServiceCheck.HealthCheck}", // 健康检测URL地址 Interval = TimeSpan.FromSeconds(options.ServiceCheck.Interval), // 每隔多少时间检测 Timeout = TimeSpan.FromSeconds(options.ServiceCheck.Timeout), // 注册超时时间 }, Name = options.ServiceName, Address = serviceUri.Host, Port = serviceUri.Port, }; // 将注册配置信息注册到consul里 consulClient.Agent.ServiceRegister(registration).Wait(); // 程序退出时需要反注册服务 AppDomain.CurrentDomain.ProcessExit += (sender, e) => { consulClient.Agent.ServiceDeregister(registration.ID).Wait(); }; return(consulClient); }