Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其他分布式服务注册与发现的方案,Consul的方案更“一站式”,内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案,不再需要依赖其他工具(比如ZooKeeper等)。使用起来也较为简单。Consul使用Go语言编写,因此具有天然可移植性(支持Linux、windows和Mac OS X);安装包仅包含一个可执行文件,方便部署,与Docker等轻量级容器可无缝配合 。
service discovery:consul通过DNS或者HTTP接口使服务注册和服务发现变的很容易,一些外部服务,例如saas提供的也可以一样注册。
health checking:健康检测使consul可以快速的告警在集群中的操作。和服务发现的集成,可以防止服务转发到故障的服务上面。
publicstatic IWebHostBuilder using ConsulDemo.Extensions; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration;
using Consul; using Newtonsoft.Json; using System; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks;
Console.WriteLine("当前所有服务"); foreach (var service in services) Console.WriteLine($"Service:{service.Value.Service}Address:{service.Value.Address}Port:{service.Value.Port}");
var agentServices = services.Where(s => s.Value.Service.Equals(serviceName, StringComparison.CurrentCultureIgnoreCase)).Select(s => s.Value).ToArray();
//根据当前TickCount对服务器个数取模,“随机”取一个机器出来,避免“轮询”的负载均衡策略需要计数加锁问题 var agentService = agentServices.ElementAt(Environment.TickCount % agentServices.Length);
///<summary> /// 转化到实际接口地址 ///</summary> ///<param name="url"></param> ///<returns></returns> privateasync Task<string> ResolveUrlAsync(string url) { var uri = new Uri(url); var serviceName = uri.Host; var realRootUrl = await ResolveRootUrlAsync(serviceName); return uri.Scheme + "://" + realRootUrl + uri.PathAndQuery; } publicasyncTask<ResponseEntity<T>> GetForEntityAsync<T>(string url, HttpRequestHeaders requestHeaders = null) { using (var httpClient = new HttpClient()) { var requestMsg = new HttpRequestMessage(); if (requestHeaders != null) foreach (var header in requestHeaders) requestHeaders.Add(header.Key, header.Value);
requestMsg.Method = HttpMethod.Get; requestMsg.RequestUri = new Uri(await ResolveUrlAsync(url)); var result = await httpClient.SendAsync(requestMsg); var respEntity = new ResponseEntity<T> { StatusCode = result.StatusCode }; var bodyStr = await result.Content.ReadAsStringAsync(); respEntity.Body = JsonConvert.DeserializeObject<T>(bodyStr); respEntity.Headers = respEntity.Headers; return respEntity; } } } }
publicclassResponseEntity<T> { public HttpStatusCode StatusCode { get; set; } public T Body { get; set; }//返回的json反序列化出来的对象 public HttpResponseHeaders Headers { get; set; }//响应的报文头 }
调用代码
1 2 3 4 5 6 7 8 9 10 11 12 13
staticvoidMain(string[] args) { while (true) { Console.WriteLine("请求开始"); var rest = new RestTemplate(); var data = rest.GetForEntityAsync<DateTime>("http://ConsulDemo/api/Values").Result; Console.WriteLine(data.StatusCode); Console.WriteLine(string.Join(",", data.Body)); Console.WriteLine("请求结束\r\n\r\n"); Console.ReadKey(); } }