Consul作用;
1.服務注冊發現
2.服務健康檢查
3.負載均衡
使用步驟:
1.下載並解壓(得到一個exe文件)
2.在解壓目錄,cmd,使用命令 Consul.exe agent -dev
這樣便啟動了Consul服務,打開瀏覽器輸入localhost:8500 (默認端口8500)
那么,怎么注冊發現服務呢。需要在要調用的服務里面注冊Consul的地址,並告知Consul自己的ip,端口號,服務名等(需要支持命令行參數)
代碼如下:
public static void ConsulRegister(this IConfiguration configuration) { ConsulClient client = new ConsulClient(c => { c.Address = new Uri("http://localhost:8500/"); c.Datacenter = "dcl"; }); string ip = configuration["ip"]; int port = int.Parse(configuration["port"]); int weight = string.IsNullOrWhiteSpace(configuration["weight"]) ? 1 : int.Parse(configuration["weight"]); client.Agent.ServiceRegister(new AgentServiceRegistration() { ID = "service" + Guid.NewGuid(), Name = "AduService", Address = ip, Port = port, Tags = new string[] { weight.ToString() }, //標簽 Check = new AgentServiceCheck() { Interval = TimeSpan.FromSeconds(12), //12s間隔檢查 HTTP=$"http://{ip}:{port}/api/Health/Index", Timeout=TimeSpan.FromSeconds(5), //檢測等待時間 DeregisterCriticalServiceAfter=TimeSpan.FromSeconds(20) //失敗后多久移除 } }); Console.WriteLine($"{ip}:{port}--weight:{weight}"); }
這些參數都是可以自定義的,要引用包Consul,
Consul地址也不一定要8500,
有一點需要注意,必須添加HealthController!寫什么都好,不然Consul檢查不到這些服務(困擾了我幾天,噗)
代碼加上
private readonly ILogger<HealthController> _logger; private readonly IConfiguration _configuration; public HealthController(ILogger<HealthController> logger, IConfiguration configuration) { _logger = logger; _configuration = configuration; } [HttpGet] [Route("Index")] public IActionResult Index() { _logger.LogWarning($"This is HealthController {_configuration["port"]}"); return Ok(); }
注意,需要在服務的StartUp.cs中的Configure方法中注冊:
#region 注冊Consul this.Configuration.ConsulRegister(); //啟動時注冊,且只注冊一次 #endregion
在主項目中調用:
string url = "http://AduService/api/user/all"; ConsulClient client = new ConsulClient(c => { c.Address = new Uri("http://localhost:8500/"); c.Datacenter = "dcl"; });
var response = client.Agent.Services().Result.Response;
Uri uri = new Uri(url); string groupName = uri.Host; AgentService agentService = null; var serviceDictionary = response.Where(s => s.Value.Service.Equals(groupName, StringComparison.OrdinalIgnoreCase)).ToArray(); agentService = serviceDictionary[0].Value; url = $"{uri.Scheme}://{agentService.Address}:{agentService.Port}{uri.PathAndQuery}";
通過向Consul的服務地址發送請求,遍歷服務,找到和AduService同名的服務下面的實例,獲取url,然后獲取數據
上述代碼是默認請求第一個服務實例。這顯然不夠,我想要動態改變請求實例,並按照權重的形式來訪問》
需要將上面的
agentService = serviceDictionary[0].Value;
修改一下:
//權重,不同服務器的處理能力不同 List<KeyValuePair<string,AgentService >> pairsList = new List<KeyValuePair<string,AgentService>>(); foreach(var pair in serviceDictionary) { int count = int.Parse(pair.Value.Tags?[0]); for(int i = 0; i < count; i++) { pairsList.Add(pair); } } agentService = pairsList.ToArray()[new Random(iIndex++).Next(0, pairsList.Count())].Value;
其中iIndex是聲明的全局變量:
private static int iIndex = 0;