Consul 官网: https://www.consul.io
Consul 下载地址: https://www.consul.io/downloads.html
Consul nuget 命令: Install-Package Consul
我的理解是, Consul 是一个服务管理者, 系统中所有使用到的服务他都帮你管理好, 促销高峰需要新增服务的时候, 服务开启来就自动注册到 Consul 中, 服务下线关闭, 也自动从 Consul 注销, 无缝衔接, 对于使用者来说, 你只需要跟 Consul 说我要某某某服务, Consul 就会返回当前在 Consul 上注册的可用的服务给回你, 你也无需像以前那样将服务的地址配置在系统当中, 就好像 DNS 服务器那样, 你输入域名, DNS 服务器返回其中一个 IP 地址给你, 然后你就可以正常访问, 另外在集群环境下选择服务的策略交给调用方, 你可以选择随机, 轮询, 权重等方式, 具体视乎你的需求.
一, Windows 系统启动 Consul
这里以 Windows 系统进行演示, 实际项目中可以搭建在 Linux 上, 下载到本地之后解压, 使用命令行模式进入到 Consul 目录, 输入命令启动 Consul 服务:
consul.exe agent -dev
启动 Consul 成功, 命令行信息中显示, 可以使用地址: http://127.0.0.1:8500 打开 UI 管理界面进行查看管理操作.
二,.NET Core+Consul 演示
1, 新建一个 ASP.NET Core web 应用程序, nuget 安装 Consul:Install-Package Consul
2, 增加用于 Consul 健康监测的 Controller, 这里就是一个简单的 Controller,Action, 能正常被访问即可.
- namespace MsgService.Controllers
- {
- [Produces("application/json")]
- [Route("api/Health")]
- public class HealthController : Controller
- {
- [HttpGet]
- public IActionResult Get()
- {
- Console.WriteLine("健康检查" + DateTime.Now);
- return Content("ok");
- }
- }
- }
3, 修改应用程序站点的 Startup 类 , 在函数 Configure 中增加多一个参数 IApplicationLifetime appLifeTime, 然后在 Configure 函数中增加注册, 注销的代码, 这段代码的意思是, 当应用程序站点启动或者注销的时候, 就会对 Consul 进行消息通知. 这里 ConsulConfig 方法里写死了我本机运行的 Consul 地址: http://127.0.0.1:8500, 实际项目中肯定是要做成配置的.
- //Consul 新增 IApplicationLifetime appLifeTime 参数
- public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifeTime)
- {
- // 注册 Consul
- string ip = Configuration["ip"];
- string port = Configuration["port"];
- string serviceName = "MsgService";
- string serviceId = serviceName + Guid.NewGuid();
- using (var consulClient = new ConsulClient(ConsulConfig))
- {
- AgentServiceRegistration asr = new AgentServiceRegistration
- {
- Address = ip,
- Port = Convert.ToInt32(port),
- ID = serviceId,
- Name = serviceName,
- Check = new AgentServiceCheck
- {
- DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
- HTTP = $"http://{ip}:{port}/api/Health",
- Interval = TimeSpan.FromSeconds(10),
- Timeout = TimeSpan.FromSeconds(5),
- },
- };
- consulClient.Agent.ServiceRegister(asr).Wait();
- }
- // 注销 Consul
- appLifeTime.ApplicationStopped.Register(() =>
- {
- using (var consulClient = new ConsulClient(ConsulConfig))
- {
- Console.WriteLine("应用退出, 开始从 consul 注销");
- consulClient.Agent.ServiceDeregister(serviceId).Wait();
- }
- });
- }
- //Consul 配置委托
- private void ConsulConfig(ConsulClientConfiguration config)
- {
- config.Address = new Uri("http://127.0.0.1:8500"); //Demo 硬编码 Consul 的地址
- config.Datacenter = "dc1";
- }
4, 修改应用程序站点的 Program.BuildWebHost 方法, 目的是方便我们在 web 应用程序 bin 目录下以指定的 IP 地址, 指定的端口启动服务
- /// <summary>
- /// 设置 NetCore 监听端口取命令行中的参数
- /// </summary>
- /// <param name="args"></param>
- /// <returns></returns>
- public static IWebHost BuildWebHost(string[] args)
- {
- var config = new ConfigurationBuilder()
- .AddCommandLine(args)
- .Build();
- string ip = config["ip"];
- string port = config["port"];
- Console.WriteLine($"ip={ip},port={port}");
- return WebHost.CreateDefaultBuilder(args)
- .UseStartup<Startup>()
- .UseUrls($"http://{ip}:{port}")
- .Build();
- }
5, 启动服务
打开应用程序目录定位在 bin 目录下, 使用命令行模式输入命令, 以指定的 IP, 指定的端口启动服务, 一切正常的话, 在 consul 管理界面可以看到已经注册上的服务信息.
这里只注册一个服务进行演示, 在实际微服务项目中, 肯定是集群环境的, 比如同一个服务, 你有 4 台机器, 那 consul 上就注册了 4 个, 服务名字都是一样的, 只是 URL 地址不一样, 当遇上促销的时候, 服务压力比较大, 这时候当要加多一台服务器, 新的服务就自动加到 consul 上来, 消费者就从 consul 取其中一个服务进行调用.
dotnet [应用程序. dll] --ip 127.0.0.1 --port 6001
三, 服务消费
1, 新建一个. NET Core 控制台应用程序;
2,nuget 安装 Consul 组件;
3, 取出已经在 Consul 注册的全部服务
- static void Main(string[] args)
- {
- using (var consul = new Consul.ConsulClient(c =>
- {
- c.Address = new Uri("http://127.0.0.1:8500");
- }))
- {
- // 取在 Consul 注册的全部服务
- var services = consul.Agent.Services().Result.Response;
- foreach (var s in services.Values)
- {
- Console.WriteLine($"ID={s.ID},Service={s.Service},Addr={s.Address},Port={s.Port}");
- }
- }
- Console.ReadKey();
- }
- }
现在在 Consul 已经注册了 3 个 MsgService 服务, 打印在控制台上.
4, 随机从注册的服务中取出其中一个服务
当我们在 consul 上注册了 N 个相同的服务之后, 我们肯定不能每次都选取某一个服务的, 不然得累死那台服务, 而其他服务却是空闲的状态, 因此我们加入随机选取的逻辑, 从注册的 N 个服务中, 随机选取其中一个服务, 另外还有其他比如轮询, 权重等等的策略, 使得我们更灵活的调用服务.
- using (var consul = new Consul.ConsulClient(c =>
- {
- c.Address = new Uri("http://127.0.0.1:8500"); //Consul 地址
- }))
- {
- // 取出全部的 MsgService 服务
- var services = consul.Agent.Services().Result.Response.Values.Where(p => p.Service.Equals("MsgService", StringComparison.OrdinalIgnoreCase));
- // 客户端负载均衡, 随机选出一台服务
- Random rand = new Random();
- var index = rand.Next(services.Count());
- var s = services.ElementAt(index);
- Console.WriteLine($"Index={index},ID={s.ID},Service={s.Service},Addr={s.Address},Port={s.Port}");
- }
5, 服务调用
- // 向服务发送请求
- using (var httpClient = new HttpClient())
- using (var httpContent = new StringContent("{phoneNum:'119',msg:'help me'}", Encoding.UTF8, "application/json"))
- {
- var result = httpClient.PostAsync($"http://{s.Address}:{s.Port}/api/SMS/Send_LX", httpContent);
- Console.WriteLine($"调用 {s.Service}, 状态:{result.Result.StatusCode}");
- }
来源: https://www.cnblogs.com/waynechan/p/9354909.html