consul服务注册和发现,详细原理这里就不在说了,如果感兴趣可以单独查一下它的详细介绍,当然和他并肩的也不少,比如常用ZooKeeper。其实道理都一样,用哪个都行。
Consul Model类:
using System; using System.Collections.Generic; using System.Text; namespace Core.Net.Common.Core.Net.Core.Consul { public class ConsulEntity { /// <summary> /// 本地ip /// </summary> public string ip { get; set; } /// <summary> /// 本地端口 /// </summary> public int port { get; set; } /// <summary> /// 服务端服务实例名称 /// </summary> public string ServiceName { get; set; } /// <summary> /// Consul IP /// </summary> public string ConsulIP { get; set; } /// <summary> /// Consul端口 /// </summary> public int ConsulPort { get; set; } } }
consul 注册类:
using Consul; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using System; using System.Collections.Generic; using System.Text; namespace Core.Net.Common.Core.Net.Core.Consul { /// <summary> /// consul /// </summary> public static class AppBuilderExtensions { /// <summary> /// 注册consul /// </summary> /// <param name="app"></param> /// <param name="lifetime"></param> /// <param name="serviceEntity"></param> /// <returns></returns> public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IApplicationLifetime lifetime, ConsulEntity serviceEntity) { //consul地址 Action<ConsulClientConfiguration> configClient = (consulConfig) => { consulConfig.Address = new Uri($"http://{serviceEntity.ConsulIP}:{ serviceEntity.ConsulPort}"); consulConfig.Datacenter = "dc1"; }; //建立连接 var consulClient = new ConsulClient(configClient); var httpCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册 Interval = TimeSpan.FromSeconds(10),//健康监测 HTTP = string.Format($"http://{serviceEntity.ip}:{serviceEntity.port}/api/health/index"),//心跳检测地址 Timeout = TimeSpan.FromSeconds(5) }; //注册 var registrtion = new AgentServiceRegistration() { Checks = new[] { httpCheck }, ID = "CoreNet" + Guid.NewGuid().ToString(),//服务编号不可重复 Name = serviceEntity.ServiceName,//服务名称 Address = serviceEntity.ip,//ip地址 Port = serviceEntity.port//端口 }; //注册服务 consulClient.Agent.ServiceRegister(registrtion); return app; } } }
客户端请求类:
using System; using System.Collections.Generic; using System.Net.Http; using System.Text; namespace Core.Net.Common.Core.Net.Core.Consul { public class ConsulHttpRequest { /// <summary> /// 封装 HttpClient 实例,提供 Http 调用。 /// </summary> /// <param name="url">http url 的地址。</param> /// <returns>返回结束数据,格式:JSON。</returns> public static string InvokeAPI(string url) { using (HttpClient client = new HttpClient()) { HttpRequestMessage message = new HttpRequestMessage(); message.Method = HttpMethod.Get; message.RequestUri = new Uri(url); var result = client.SendAsync(message).Result; string conent = result.Content.ReadAsStringAsync().Result; return conent; } } } }
后台api接口consul服务配置:appsetting.json文件中配置
startup类中中注册consul服务:
////注入Consul配置 //// Configuration.ConsulRegister(); ConsulEntity consulEntity = new ConsulEntity { ip = Configuration["ip"], port = int.Parse(Configuration["port"]), ServiceName = "CoreNet", ConsulIP = Configuration["Consul:IP"], ConsulPort = Convert.ToInt32(Configuration["Consul:Port"]) }; app.RegisterConsul(lifetime, consulEntity);
还有最后一项,就是consul要每隔一段时间要做健康检查,所以api接口要添加一个健康检查控制器:
using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Core.Net.WebApi.Controllers.ConsulHealth { /// <summary> /// Consul健康检查 /// </summary> [Route("api/[controller]/[action]")] [ApiController] public class HealthController : Controller { private IConfiguration _configuration; /// <summary> /// 初始化该类型的新实例。 /// </summary> /// <param name="configuration">配置接口。</param> public HealthController(IConfiguration configuration) { _configuration = configuration; } /// <summary> /// 要调用的接口。 /// </summary> [HttpGet] public IActionResult Index() { Console.WriteLine($"This is HealhController {_configuration["port"]} Invoke"); return Ok(); } } }
然后就是客户端如何请求,这里用web作为客户端请求:
/// <summary> /// consul客户端测试 /// </summary> /// <returns></returns> public string demo() { #region 分布式架构 #region 通过 Consul 服务发现来执行服务实例。ZooKeeper效果同等 //发现服务 string url = "http://CoreNet/api/Login/Index"; ConsulClient client = new ConsulClient(config => { config.Address = new Uri("http://localhost:8500/"); config.Datacenter = "dc1"; }); var response = client.Agent.Services().Result.Response; foreach (var item in response) { Console.WriteLine("*************************************************************"); Console.WriteLine(item.Key); var service = item.Value; Console.WriteLine($"{service.Address}--{service.Port}--{service.Service}"); Console.WriteLine("*************************************************************"); } Uri uri = new Uri(url); string groupName = uri.Host; AgentService agentService = null; var serviceDirectory = response.Where(s => s.Value.Service.Equals(groupName, StringComparison.OrdinalIgnoreCase)).ToArray(); //{//1、 写死的 // agentService = serviceDirectory[0].Value; //} { //2、轮询 if (index >= 10000) { index = 0; } agentService = serviceDirectory[index++ % serviceDirectory.Length].Value; } // {//3、随机 // var indexResult = new Random(index++).Next(0, serviceDirectory.Length); // agentService = serviceDirectory[indexResult].Value; //} url = $"{uri.Scheme}://{agentService.Address}:{agentService.Port}{uri.PathAndQuery}"; #endregion string content = ConsulHttpRequest.InvokeAPI(url); #endregion return content; }
然后就是搭建测试环境了,consul的安装我以前已经做过详细介绍了,这里就不多说了,下面我要建立一个api集群,来模拟consul服务注册和发现,以本地作为测试,端口分别为3100,3200,3300:
具体流程是:
1,启动consul组件
2,启动三个api接口向consul注册。
3,查看consul中api注册的实例。
4,web作为客户端模拟请求,查看数据。
5,关闭集群中的一个api查看consul中的集群健康度和个数。
启动consul组件:
建立api集群,并启动api向consul注册服务实例:
查看consul中api注册的实例。
下图是健康检查:
模拟通过consul获取数据:
至于验证consul发现,自己可以试一下,关闭一个api,consul会自定剔除这个有问题的api。