五分钟了解Consul
Hi,大家好,我叫consul,翻译成中文叫做“领事”,其实我更喜欢叫自己为中介,因为我觉得自己做的事情和房产中介非常像。比如说想要卖房的房东到我这边登记,我将房屋信息登录到我的表格中(服务注册),有买家来咨询时,我再查询表格将符合条件的房子返回给买家(服务发现),平时我也要做点房源的维护工作,比如每隔一天就打电话问下房东:“你的房子还卖么?(服务健康检查)”。
我的诞生也和现在互联网项目的开发模式有关,从之前的三层架构衍化成现在有微服务架构,把原来BLL和DAL层做事按业务拆成独立的分布式服务(其实很多人就是把CURD放到单独的服务中而已),为了高可用&高扩展,又把这些服务(进程)集群化,就出现一堆的地址和端口。客户端由原来的进程内调用变成跨进程或跨网络调用服务,把这些一堆地址和端口放到配置文件中。这样做其实没什么问题,但维护起来比较麻烦,比如说增加一个服务,就要修改配置文件并重启客户端,同理,删掉一个服务也要同样的操作。
我的作用主要是管理这些集群服务的配置,整体流程是这样子的:服务(进程)启动的时候把服务名和自己的IP、端口通过HTTP告诉我,我将这些信息记到自己的内存表格中,客户端调用时带上要查询的服务名通过HTTP发送给我,我再自己的内存表中找到叫这服务名的所有配置发送给客户端。
平时我还要做一些服务健康检查的事儿,在上面服务启动的时候,服务还要给我配置一个检查接口和检查频率等一些参数,我会按这些参数每隔一段时间,比如10秒钟去请求一下这个接口,如果不通,我就隔5秒再重试下,如果重试3次还不通,我就认定这个服务挂掉了,就从内存表格中删掉这个服务配置,不然客户端要请求到这个不通服务,我就罪过了。
说了这么多,还是看下我的整个流程图吧,一图胜千言:
最后,再用代码实现下吧,语言是C#,其实语言类似,反正都有现成的sdk。
1、VS中建个控制台应用,并通过nuget安装consul包
2、注册几个服务
1 static void Main(string[] args)
2 {
3 string serviceName = "OrderService";
4
5 // 注册服务
6 RegisteService(serviceName, new DnsEndPoint("127.0.0.1", 16005));
7 RegisteService(serviceName, new DnsEndPoint("127.0.0.1", 16007));
8 RegisteService(serviceName, new DnsEndPoint("127.0.0.1", 16008));
9 Console.ReadKey();
10 }
11
12 static bool RegisteService(string serviceName, DnsEndPoint dnsEndPoint)
13 {
14 var serviceId = GenServiceId(serviceName, dnsEndPoint);
15 var checkId = GenCheckId(serviceName, dnsEndPoint);
16 var checkName = GenCheckName(serviceName, dnsEndPoint);
17 var check = new AgentCheckRegistration
18 {
19 ID = checkId,
20 Name = checkName,
21 TCP = $"{dnsEndPoint.Host}:{dnsEndPoint.Port}",
22 Interval = TimeSpan.FromSeconds(10),
23 Status = HealthStatus.Passing,
24 DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(20),
25 };
26 var service = new AgentServiceRegistration
27 {
28 ID = serviceId,
29 Name = serviceName,
30 Address = dnsEndPoint.Host,
31 Port = dnsEndPoint.Port,
32 Check = check
33 };
34
35 var _client = new ConsulClient(config =>
36 {
37 var uriBuilder = new UriBuilder("http://localhost:8500");
38 config.Address = uriBuilder.Uri;
39 });
40 var res = _client.Agent.ServiceRegister(service).Result;
41 if (res.StatusCode != HttpStatusCode.OK)
42 return false;
43 return true;
44 }
3、服务发现
1 static void Main(string[] args)
2 {
3 string serviceName = "OrderService";
4
5 // 服务发现
6 List<string> targets = FindServiceEndpoints(serviceName);
7 foreach(var item in targets)
8 {
9 Console.WriteLine(item);
10 }
11 Console.ReadKey();
12 }
13
14 static List<string> FindServiceEndpoints(string serviceName)
15 {
16 var _client = new ConsulClient(config =>
17 {
18 var uriBuilder = new UriBuilder("http://localhost:8500");
19 config.Address = uriBuilder.Uri;
20 });
21
22 var targets = new List<string>();
23 try
24 {
25 var r = _client.Health.Service(serviceName, "", true).Result;
26 if (r.StatusCode != HttpStatusCode.OK)
27 throw new ApplicationException($"query consul server error");
28
29 targets = r.Response.Select(x => $"{x.Service.Address}:{x.Service.Port}").ToList();
30 }
31 catch { }
32 return targets;
33 }
更多精彩请关注我的关注号:

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库