一、Consul 在net6下的使用
一、什么是consul?
首先我们来了解什么是consul,consul是服务注册与发现的一种常用工具之一,翻阅了网上的部分资料,指把服务地址注册到consul,然后在consul中读取来消费;但在我的理解中,consul的作用是服务治理,属于可以横向伸缩的注册中心;为什么这么说呢?在以前我们用Nginx做负载时,需要把服务地址一个个手动集成进去的,如果服务多了会有什么问题呢?1.需要新增一个服务,必须要重新配置Nginx然后重启;2.感知不了哪个服务停止了;3.如果某个服务停止了,无法自动创建新的服务代替;因为微服务其中一个特点是基础设施自动化,所以明显Nginx满足不了需求,那么服务注册与发现就横空而生了(除了consul外还可以使用etcd,K8S Services等)。
二、consul有几大核心功能:
1.服务注册
其实就是把需要使用的服务注册到注册中心(consul的注册方式是已服务主动推送给consul客户端->服务端),其他客户端可以使用 Consul 发现给定服务的提供者。使用 DNS 或 HTTP,应用程序可以轻松找到它们所依赖的服务(它是通过代理注册的方式注册到注册中心,提供业务代码的解耦)
2.健康检查
其实就是在程序中,建立一个接口,只返回状态使用,consul通过这个接口来检查服务是否健康,如果不健康,则通过策略去移除
3.多个数据中心
其实就是支持集群,通过3个,或5个的单数服务端的consul来支持高可用(因为单数更适合做选举算法,如果数量太多又影响性能,所以这是官网标配);
4.安全服务通信
Consul 可以为服务生成和分发 TLS 证书以建立相互 TLS 连接
consul工作流程图:
三、consul安装
安装分2种,一种是二进制,以命令行的形式安装;一种是以exe文件免安装的形式;
四、consul运行问题
运行时,最可能出现的问题就是端口占用,可新增文件,修改文件端口号,然后执行命令即可,百度上很多解决,请自行搜索命令
五、net6的代码实现
1.服务注册代码,目的是把当前服务推送到consul,并且设置健康检查
依赖组件
consul
1 public static class RegisterToConsul 2 { 3 /// <summary> 4 /// 把本服务注册到Consul 5 /// </summary> 6 /// <param name="config">参数配置</param> 7 /// <param name="appLifetime">程序生命周期</param> 8 public static void RegToConsul(this IConfiguration config) 9 { 10 //Consul地址 11 var address= AppHelper.ReadAppSettings("Consul", "consulAddress"); 12 var consulClient = new ConsulClient(p => { p.Address = new Uri(address); }); 13 14 //本地IP 15 var localIP = AppHelper.ReadAppSettings("Consul", "currentIp"); 16 //本地服务端口 17 var localPort = Convert.ToInt32(AppHelper.ReadAppSettings("Consul", "currentPort")); //端口号从命令行参数获取(注:目前没找到直接获取本服务监听的端口的方法) 18 19 //心跳检测设置 20 var httpCheck = new AgentServiceCheck() 21 { 22 DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(60), //心跳检测失败多久后注销 23 Interval = TimeSpan.FromSeconds(10), //间隔多久心跳检测一次 24 HTTP = $"http://{localIP}:{localPort}/api/Health/Check", //心跳检查地址,本服务提供的地址 25 Timeout = TimeSpan.FromSeconds(5) //心跳检测超时时间 26 }; 27 28 //服务名(这里通过命令行参数传入不同的服务名,模拟我们有不同的服务[其实只是同一个接口项目的不同运行实例]) 29 var serviceName = AppHelper.ReadAppSettings("Consul", "serviceName"); 30 31 //注册信息 32 var registration = new AgentServiceRegistration() 33 { 34 ID = $"{localIP}:{localPort}", //服务ID,唯一 35 Name = serviceName, //服务名(如果服务搭集群,它们的服务名应该是一样的,但是ID不一样) 36 Address = $"{localIP}", //服务地址 37 Port = localPort, //服务端口 38 Tags = new string[] { }, //服务标签,一般可以用来设置权重等本地服务特有信息 39 Checks = new[] { httpCheck }, //心跳检测设置 40 }; 41 42 //向Consul注册服务 43 consulClient.Agent.ServiceRegister(registration).Wait(); 44 45 } 46 }

1 "Consul": { 2 3 "consulAddress": "http://127.0.0.1:8500", 4 5 "serviceName": "Consultest", 6 7 "currentIp": "127.0.0.1", 8 9 "currentPort": "5247" 10 11 }

1 public class AppHelper 2 { 3 private static IConfiguration _config; 4 5 public AppHelper(IConfiguration configuration) 6 { 7 _config = configuration; 8 } 9 10 /// <summary> 11 /// 读取指定节点的字符串 12 /// </summary> 13 /// <param name="sessions"></param> 14 /// <returns></returns> 15 public static string ReadAppSettings(params string[] sessions) 16 { 17 try 18 { 19 if (sessions.Any()) 20 { 21 return _config[string.Join(":", sessions)]; 22 } 23 } 24 catch 25 { 26 return ""; 27 } 28 return ""; 29 } 30 31 /// <summary> 32 /// 读取实体信息 33 /// </summary> 34 /// <typeparam name="T"></typeparam> 35 /// <param name="session"></param> 36 /// <returns></returns> 37 public static List<T> ReadAppSettings<T>(params string[] session) 38 { 39 List<T> list = new List<T>(); 40 _config.Bind(string.Join(":", session), list); 41 return list; 42 } 43 }

1 [Route("api/[controller]")] 2 [ApiController] 3 public class HealthController : ControllerBase 4 { 5 [HttpGet] 6 [Route("Check")] 7 public IActionResult Check() 8 { 9 return Ok(); 10 } 11 }
2.服务发现代码,目的是通过调用consul注册中心的服务

1 private static int index = 0; 2 [HttpGet] 3 [Route("Contents")] 4 public IActionResult Contents() 5 { 6 string url = $"http://{AppHelper.ReadAppSettings("Consul", "serviceName")}/api/values"; 7 ConsulClient client = new ConsulClient(c=> 8 { 9 c.Address = new Uri(AppHelper.ReadAppSettings("Consul", "consulAddress")); 10 } 11 ); 12 var res = client.Agent.Services().Result.Response; 13 Uri uris = new Uri(url); 14 string groupname = uris.Host; 15 var dic = res.Where(s => s.Value.Service.Equals(groupname, StringComparison.OrdinalIgnoreCase)).ToArray(); 16 //轮询读取 17 return Content(Newtonsoft.Json.JsonConvert.SerializeObject(dic[index++ % dic.Length].Value)); 18 }
六、Consul集群,做集群测试
配置地址:https://blog.csdn.net/weixin_46785144/article/details/117172621
七、拓展点
上面的服务发现读取上,当单个服务达到瓶颈了,这时候我们就要负载均衡来分担服务器的压力,那么我们下一节来讲Consul如何进行负载均衡
代码:https://gitee.com/runwei/consul.git
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)