.net core consul 服务配置 服务发现 服务健康检测 服务变更加载
準(zhǔn)備環(huán)境
?安裝consul之后
1. 創(chuàng)建一個(gè).net core webapi 舉例為UsercenterService
2. nuget引用Consul組件??https://github.com/PlayFab/consuldotnet
3. 創(chuàng)建配置實(shí)體類 (后面涉及功能介紹時(shí)候再解釋屬性含義)
1 public class AppSettings 2 { 3 /// <summary> 4 /// 數(shù)據(jù)庫連接字符串 5 /// </summary> 6 public string DbConnection { get; set; } 7 8 /// <summary> 9 /// 服務(wù)注冊(cè)參數(shù) 10 /// </summary> 11 public ServiceRegisterOptions ServiceRegisterOptions { get; set; } 12 } 13 14 public class ServiceRegisterOptions 15 { 16 /// <summary> 17 /// 是否啟用 18 /// </summary> 19 public bool IsActive { get; set; } 20 /// <summary> 21 /// 服務(wù)名稱 22 /// </summary> 23 public string ServiceName { get; set; } 24 /// <summary> 25 /// 服務(wù)IP或者域名 26 /// </summary> 27 public string ServiceHost { get; set; } 28 /// <summary> 29 /// 服務(wù)端口號(hào) 30 /// </summary> 31 public int ServicePort { get; set; } 32 /// <summary> 33 /// consul注冊(cè)地址 34 /// </summary> 35 public string ConsulRegisterUrl { get; set; } 36 /// <summary> 37 /// 標(biāo)簽 例如laiwutest 38 /// </summary> 39 public string[] Tags { get; set; } 40 } View Code4. appsettings配置consul服務(wù)地址和UserService配置在consul的節(jié)點(diǎn)key
4.1 配置consul地址(舉例是在VS調(diào)試開發(fā)環(huán)境。所以在appsettings.Development.json中配置)?
1 { 2 "ConsulForConfig": { 3 "Host": "{IP}:8500",//這里替換成自己consul服務(wù)的IP地址 4 "Prefix": "git-dev/huangqiang/usercenterRegionIIS.json" 5 } 6 } View Code? ? ? ?4.2 在consul上創(chuàng)建該節(jié)點(diǎn)并且配置
1 { 2 "DbConnection": "111111111111111111111111111111111111111", 3 "ServiceRegisterOptions": 4 { 5 "IsActive":true, 6 "ServiceName":"UserCenterRegion", 7 "ServiceHost":"{IP}",//修改{IP}為你注入的服務(wù)的ip地址 8 "ServicePort":"{Port}",//修改{Port}為你注入的服務(wù)的端口 9 "ConsulRegisterUrl":"{IP}:8500",//修改{IP}為你的consul服務(wù)的IP 10 "Tags":["浙江杭州"] 11 }, 12 } View Code? ?
獲取配置??
1 public static AppSettings AddAppSettingByConsul(this IServiceCollection sc, IConfiguration configuration) 2 { 3 try 4 { 5 //get local consul service address configration consulclient 6 var consulAddress = $"http://" + configuration["ConsulForConfig:Host"]; 7 var key = configuration["ConsulForConfig:Prefix"]; 8 if (string.IsNullOrWhiteSpace(consulAddress) || string.IsNullOrWhiteSpace(key)) 9 { 10 throw new Exception("無法獲取consulAddress地址或者consul key"); 11 } 12 var consulClient = new ConsulClient(cfg => { cfg.Address = new Uri(consulAddress); }); 13 sc.AddSingleton<IConsulClient>(p => consulClient); 14 //get app config 15 var res = consulClient.KV.Get(key).GetAwaiter().GetResult(); 16 var resStr = Encoding.UTF8.GetString(res.Response.Value); 17 var appSettings = JsonConvert.DeserializeObject<AppSettings>(resStr); 18 if (appSettings == null) 19 { 20 throw new Exception($"appSettings 為null,consul 配置:{resStr}"); 21 } 22 sc.AddSingleton<AppSettings>(appSettings); 23 return appSettings; 24 } 25 catch (Exception e) 26 { 27 _log.Main.Error($"獲取consul appsettings配置異常:{e.Message}"); 28 Environment.Exit(-1); 29 } 30 return null; 31 } View Code這里抽了一個(gè)擴(kuò)展方法。使用的時(shí)候在Startup.cs類中的方法ConfigureServices中加入,這里弄了返回值只是偷懶下。
AddAppSettingByConsul方法邏輯:先是拿到配置的consull服務(wù)地址和Key,再通過前面nuget引用的consul組件中的consulclient獲取配置,最后注入到容器
調(diào)試下 就拿到配置了。這樣方便分布式服務(wù),不用每臺(tái)都配置,直接consul管理
?
?
?
配置健康檢測和服務(wù)注冊(cè)
?準(zhǔn)備健康檢測接口:
1 [Route("api/v1/[controller]")] 2 [ApiController] 3 public class HealthController : ControllerBase 4 { 5 [HttpGet] 6 public IActionResult Get() => Ok("ok"); 7 } View Code.net core 配置注冊(cè)和健康檢測的地址
1 public static void UseConsul(this IApplicationBuilder app, IApplicationLifetime appLife) 2 { 3 try 4 { 5 var appSettings = app.ApplicationServices.GetService<AppSettings>(); 6 var consulClient = app.ApplicationServices.GetService<IConsulClient>(); 7 8 //config consul health check 9 var healthCheck = new AgentServiceCheck 10 { 11 DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5), 12 Interval = TimeSpan.FromSeconds(30), 13 HTTP = $"{appSettings.ServiceRegisterOptions.ServiceHost}:{appSettings.ServiceRegisterOptions.ServicePort}/api/v1/Health", 14 }; 15 16 //service register 17 var serviceId = $"{appSettings.ServiceRegisterOptions.ServiceName}_{appSettings.ServiceRegisterOptions.ServiceHost}:{appSettings.ServiceRegisterOptions.ServicePort}"; 18 var registration = new AgentServiceRegistration 19 { 20 Checks = new[] { healthCheck }, 21 Address = appSettings.ServiceRegisterOptions.ServiceHost, 22 Port = appSettings.ServiceRegisterOptions.ServicePort, 23 ID = serviceId, 24 Name = appSettings.ServiceRegisterOptions.ServiceName, 25 Tags = appSettings.ServiceRegisterOptions.Tags 26 }; 27 consulClient.Agent.ServiceRegister(registration).GetAwaiter().GetResult(); 28 29 //service Deregister when app stop 30 appLife.ApplicationStopped.Register(() => 31 { 32 consulClient.Agent.ServiceDeregister(serviceId).GetAwaiter().GetResult(); 33 }); 34 35 36 } 37 catch (Exception e) 38 { 39 _logger.Main.Error($"UseConsul error:{e.Message}"); 40 Environment.Exit(-1); 41 } 42 43 } View Code?
這里也是抽了個(gè)擴(kuò)展方法。調(diào)用放到Startup
?
UseConsul方法解釋:先是從容器中拿到前面注入的配置實(shí)體AppSettings和ConsulClient。再配置健康檢測,再配置服務(wù)注冊(cè),再配置當(dāng)服務(wù)關(guān)閉時(shí)候注銷服務(wù)。
其中健康檢測的DeregisterCriticalServiceAfter表示如果服務(wù)啟動(dòng)失敗,多少時(shí)間內(nèi)注銷consul上的該服務(wù)。
服務(wù)注冊(cè)的參數(shù)就不介紹了
然后跑起來之后,到consul ui瞧一瞧。是不是注冊(cè)成功,心跳正常
狀態(tài)為passing為正常的,剛啟動(dòng)時(shí)候狀態(tài)會(huì)為critical。 當(dāng)你的狀態(tài)一直為critical時(shí)候,過了前面DeregisterCriticalServiceAfter的時(shí)間,服務(wù)將會(huì)注銷,也就是注冊(cè)失敗。可能原因:服務(wù)地址配置有問題,consul無法訪問你的health地址,也可能你的端口沒打開。telnet看看
?
當(dāng)都成功的時(shí)候,服務(wù)已經(jīng)正常注冊(cè)到consul。下面再說說服務(wù)發(fā)現(xiàn)和服務(wù)變更發(fā)現(xiàn)
?
?
服務(wù)發(fā)現(xiàn)和服務(wù)變更發(fā)現(xiàn)
服務(wù)發(fā)現(xiàn)調(diào)用的方法有很多,agent,catalog,health,都可以獲取列表。但是agent是查詢本地自己的,catalog是整個(gè)集群的,heath是查詢健康的。這里用health獲取舉例
關(guān)鍵就一句話:_consulClient.Health.Service(serviceName, tag, true, queryOptions).Result。
這樣就能獲取到注冊(cè)到consul的服務(wù)列表了,但是如果有服務(wù)變更了(新的服務(wù)注冊(cè),舊的服務(wù)停止),應(yīng)該怎么辦?
一般想到啟動(dòng)一個(gè)線程不停的去拿,是沒有問題,但是有個(gè)更好的東西,“Blocking Queries”??https://www.consul.io/api/index.html
這個(gè)東西簡單來說就是會(huì)記錄一個(gè)版本,consul服務(wù)端通過這個(gè)版本來判斷是不是已經(jīng)是最新的服務(wù)列表,如果是的話,那么將會(huì)阻塞一定時(shí)間(這個(gè)時(shí)間可配置)
在c# 里面體現(xiàn)就是第三個(gè)參數(shù)queryOptions的WaitIndex和WaitTime,以及返回LastIndex,下面po出一部分代碼。
public void GetAllService(){_serviceIndexList.ForEach(p =>{Task.Run(() =>{var queryOptions = new QueryOptions { WaitTime = TimeSpan.FromSeconds(_waitTime) };while (true){GetAgentServices(queryOptions, p.ServiceName, p.Tag);}});});}public void GetAgentServices(QueryOptions queryOptions, string serviceName, string tag = null){try{var res = _consulClient.Health.Service(serviceName, tag, true, queryOptions).Result;_logger.Main.Info($"GetServiceList:{serviceName} {tag} waitIndex:{res.LastIndex}");if (queryOptions.WaitIndex != res.LastIndex){queryOptions.WaitIndex = res.LastIndex;var currentService = _consulServices.FirstOrDefault(p => p.ServiceName == serviceName);if (currentService == null){_consulServices.Add(new ConsulService{ServiceName = serviceName,Tag = tag,ServiceEntries = new ConcurrentBag<ServiceEntry>(res.Response)});}else{currentService.ServiceEntries = new ConcurrentBag<ServiceEntry>(res.Response);}}}catch (AggregateException ae){_logger.Main.Error($"consul獲取{serviceName},{tag}服務(wù)列表資源錯(cuò)誤:{ae.Flatten()}",ae);}catch (Exception e){_logger.Main.Error($"consul獲取{serviceName},{tag}服務(wù)列表資源錯(cuò)誤",e);}} View Code注:代碼中的_serviceIndexList是存著需要獲取哪些服務(wù)的服務(wù)tag,_consulServices是程序維護(hù)的最新服務(wù)列表
?
轉(zhuǎn)載于:https://www.cnblogs.com/TeemoHQ/p/10523637.html
總結(jié)
以上是生活随笔為你收集整理的.net core consul 服务配置 服务发现 服务健康检测 服务变更加载的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 21.Merge Two Sorted
- 下一篇: React 点击按钮显示div与隐藏di