什么是Consul
Consul是一个服务网格(微服务间的 TCP/IP,负责服务之间的网络调用、限流、熔断和监控)解决方案,它是一个一个分布式的,高度可用的系统,而且开发使用都很简便。它提供了一个功能齐全的控制平面,主要特点是:服务发现、健康检查、键值存储、安全服务通信、多数据中心。
Consul是用Go开发的分布式服务协调管理的工具,它提供了服务发现,健康检查,Key/Value存储等功能,并且支持跨数据中心的功能。consul提供的一些关键特性:
service discovery:consul通过DNS或者HTTP接口使服务注册和服务发现变的很容易,一些外部服务,例如saas提供的也可以一样注册。
health checking:健康检测使consul可以快速的告警在集群中的操作。和服务发现的集成,可以防止服务转发到故障的服务上面。
key/value storage:一个用来存储动态配置的系统。提供简单的HTTP接口,可以在任何地方操作。
multi-datacenter:无需复杂的配置,即可支持任意数量的区域。
Consul的应用 服务注册与发现 其实服务注册与发现的原理很简单。
当我们在本机运行Consul时,他会自动监听8500端口;然后我们通过一个开源类库(这个开源类库可以在nuget上检索到,文章下面会介绍),调用其下不同的方法来向这个Consul进程发送TCP消息,来注册服务或者发现服务。
Consul进程在接收到注册消息时,就把注册的服务信息存储到本地磁盘或内存(因为我没有具体去调查Consul存储数据是否使用了数据库,但我们都知道数据库的数据也是保存在本地磁盘的,所以,它肯定是把数据存进磁盘或者内存中了)。
数据中心 Consul存储数据的地方,官方为其命名为数据中心,也就是上面说的保存我们注册的服务信息的本地磁盘或者内存。
Consul提供负载均衡的集群 Consul的集群也很好理解,在我们成功启动Consul以后,它除了监听8500端口以外,它还监听了一个8031端口。
这个8031端口就是用于Consul集群相互通信的。
我们都知道集群是要两台以上的电脑的,所以,我们就必须找到两台或以上的电脑安装Consul中间件。
然后,使用Consul的命令行,将两台电脑连接到一起,这样集群就形成了。
在集群内每台电脑上安装的Consul中间件,我们统称为服务器代理(Agent);当集群启动后,会在多个代理服务器之间选举出一个Leader。
选举Leader自然就是服务器代理之间的通信了,也就是通过上面提到的8031端口通信的。
选举了Leader,服务器代理就可以将自身的负载信息发送给Leader了,这样客户端调用Consul检索服务数据时,就可以去性能最优的那台机器上获取信息了。(注:这个就是举例说明,并非Consul的负载均衡的真实处理模式)
代码例子 服务注册与发现 我们新建一个 api Service
在 startup.cs 中的 Configure 增加如下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 string ip = Configuration["ip"];//部署到不同服务器的时候不能写成127.0.0.1或者0.0.0.0,因为这是让服务消费者调用的地址 int port = int.Parse(Configuration["port"]);//获取服务端口 var client = new ConsulClient(ConfigurationOverview); //回调获取 var result = client.Agent.ServiceRegister(new AgentServiceRegistration() { ID = "ServerNameFirst" + Guid.NewGuid(),//服务编号保证不重复 Name = "MsgServer",//服务的名称 Address = ip,//服务ip地址 Port = port,//服务端口 Check = new AgentServiceCheck //健康检查 { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后反注册 Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔,或者称为心跳间隔(定时检查服务是否健康) HTTP = $"http://{ip}:{port}/api/Health",//健康检查地址 Timeout = TimeSpan.FromSeconds(5)//服务的注册时间 } });
1 2 3 4 5 6 7 private static void ConfigurationOverview(ConsulClientConfiguration obj) { //consul的地址 obj.Address = new Uri("http://192.168.1.37:8500"); //数据中心命名 obj.Datacenter = "dc1"; }
客户端调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 static List<string> Urls = new List<string>(); static void Main(string[] args) { Console.WriteLine("开始输出当前所有服务地址"); Catalog_Nodes().GetAwaiter().GetResult(); //Console.WriteLine(HelloConsul().GetAwaiter().GetResult()); Console.WriteLine("开始随机请求一个地址服务地址"); int index = new Random().Next(Urls.Count); string url = Urls[index]; Console.WriteLine("请求的随机地址:" + url); HttpClient client = new HttpClient(); var result = client.GetAsync(url).Result; //string result = HttpClientHelpClass.PostResponse(url, param, out string statusCode); Console.WriteLine("返回状态:" + result.StatusCode); Console.WriteLine("返回结果:" + result.Content); Console.ReadLine(); } public static async Task Catalog_Nodes() { var client = new ConsulClient(ConfigurationOverview); var nodeList = await client.Agent.Services(); var url = nodeList.Response.Values; foreach (var item in url) { string Address = item.Address; int port = item.Port; string name = item.Service; Console.WriteLine($"地址:{Address}:{port},name:{name}"); Urls.Add($"http://{Address}:{port}/weatherforecast"); } } private static void ConfigurationOverview(ConsulClientConfiguration obj) { //consul的地址 obj.Address = new Uri("http://192.168.1.37:8500"); //数据中心命名 obj.Datacenter = "dc1"; }
运行即可看到 我们已经成功调用了Consul,也成功的获取到了服务信息。
参考:https://www.cnblogs.com/shanyou/archive/2015/08/09/4714838.html https://www.cnblogs.com/kiba/p/11941731.html https://www.cnblogs.com/yanbigfeg/p/9199590.html