06_NET中使用Consul(服务发现)
中文文档:Consul 中文文档 | Consul 中文文档 (gitbook.io)
安装Consul
window安装:Install | Consul | HashiCorp Developer
1. 选择windows x64 版本(64bit)
2. 进入下载好的文件夹中,打开powershell ,执行命令,启动服务端代理
consul.exe agent -dev
3. 浏览器输入:http://IP:8500/出现ConsulWeb界面就表示成功了
-dev 表示开发模式,生产环境下不建议使用,因为它不会保存任何状态
-server 生产环境下可使用
Docker 安装:
docker pull consul # 默认拉取latest docker pull consul:1.15.4 # 拉取指定版本
安装并运行
docker run -d -p 8500:8500 --restart=always --name=consul consul agent -server - bootstrap -ui -node=1 -client='0.0.0.0'
agent: 表示启动 Agent 进程。
server:表示启动 Consul Server 模式
client:表示启动 Consul Cilent 模式。
bootstrap:表示这个节点是 Server-Leader ,每个数据中心只能运行一台服务器。技术角度上讲Leader 是通过 Raft 算法选举的,但是集群第一次启动时需要一个引导 Leader,在引导群集后,建议不要使用此标志。
ui:表示启动 Web UI 管理器,默认开放端口 8500,所以上面使用 Docker 命令把 8500 端口对外开放。
node:节点的名称,集群中必须是唯一的,默认是该节点的主机名。
client:consul服务侦听地址,这个地址提供HTTP、DNS、RPC等服务,默认是127.0.0.1所以不对外提供服务,如果你要对外提供服务改成0.0.0.0
join:表示加入到某一个集群中去。 如:-json=192.168.0.11。
使用Consul:
安装包:Consul.AspNetCore
服务端:
新建一个WebApi项目:Consul.ServiceA
修改appsettings.json配置文件
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "Consul": { "HostAddress": "http://localhost:8500", "ServiceAddress": "localhost", "Port": 5011, "ServerName": "Consul.ServiceA" } }
HostAddress:Consul地址; ServiceAddress:服务地址; Port:端口; ServerName:服务名称
添加映射类
public class ConsulOption { public string HostAddress { get; set; } public string ServiceAddress { get; set; } public int Port { get; set; } public string ServerName { get; set; } }
添加扩展类
public static class ConsulServiceExtension { public static IServiceCollection AddConsulService(this IServiceCollection services, IConfiguration configuration ) { //获取配置文件信息 var consulSection = configuration.GetSection("Consul"); services.Configure<ConsulOption>(consulSection); var consulOption = consulSection.Get<ConsulOption>(); //添加consul地址 services.AddConsul(p => { p.Address = new Uri(consulOption.HostAddress); }); //注册consul services.AddConsulServiceRegistration(p => { p.ID = Guid.NewGuid().ToString(); p.Name = consulOption.ServerName; p.Address = consulOption.ServiceAddress; p.Port = consulOption.Port; // 健康检查 p.Check = new() { // 1. 如果服务不可用(健康检查失败)的情况下,多久将当前服务移除 DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5), // 2. 健康检查间隔时间 Interval = TimeSpan.FromSeconds(10), // 3. 健康检查地址(心跳地址) HTTP = $"http://{p.Address}:{p.Port}/health" // 4. 超时时间 ,Timeout = TimeSpan.FromSeconds(5) }; }); return services; } }
Program.cs
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddSwaggerGen(); builder.Services.AddConsulService(builder.Configuration); var app = builder.Build(); app.UseSwagger(); app.UseSwaggerUI(); app.UseAuthorization(); app.MapControllers(); app.Run();
添加HealthController控制器
[ApiController] [Route("[controller]")] public class HealthController:ControllerBase { [HttpGet] public IActionResult Check() { return Ok($"进行心跳检测:{DateTime.Now}"); } }
客户端:
新建一个webApi项目:Consul.Client
配置和服务端一致;appsettings.json的配置要记得修改;
-----------------------------------------------------漂亮的分割线-------------------------------------------------------------------------
测试:
服务端Consul.ServiceA添加一个控制器用于测试
[Route("[controller]/[action]")] [ApiController] public class ProductController:ControllerBase { [HttpGet] public IActionResult GetProduct() { List<ProductInfo> list = new() { new() {Id = 1, Name = "商品1"}, new() {Id = 2, Name = "商品2"} }; return Ok(list); } }
客户端Consul.Client添加一个控制器ClientController 去调用服务端
[Route("[controller]/[action]")] [ApiController] public class ClientController:ControllerBase { private readonly IConsulClient _consulClient; public ClientController(IConsulClient consulClient) { _consulClient = consulClient; } [HttpGet] public async Task<IActionResult> GetProductByClient() { var instanceList = (await _consulClient.Catalog. Service("Consul.ServiceA")).Response; //随机获取一个服务 var instance = instanceList[new Random().Next(instanceList.Length)]; using HttpClient client = new(); var json = await client.GetStringAsync($"http://{instance.ServiceAddress}:{instance.ServicePort}/Product/GetProduct"); var result = JsonConvert.DeserializeObject<List<ProductInfo>>(json); return Ok(result); } }
-----------------------------------------------------漂亮的分割线-------------------------------------------------------------------------
添加多个服务端(集群)
配置和Consul.ServiceA也是一样的,appsettings.json的配置要记得修改
"Consul": { "HostAddress": "Consul地址", "ServiceAddress": "服务端地址", "Port": 服务端口, "ServerName": "这里的名称都要一样" }