接上一文章:https://blog.csdn.net/liangmengbk/article/details/117382250
Consul的主要功能是服务的注册与发现。如下图所示:
Consul完成对服务S-B-1、S-B-2、S-B-3 三个服务的注册,同时可以对三个服务做健康检查,检查服务是否正常运行。
上图中S-A作为消费者,调用Consul,Consul根据配置的权重,返回一个正常运行的服务(S-B-1、S-B-2、S-B-3中的其中一个)地址给S-A,S-A拿到Consul返回的地址后对S-B-X服务进行调用。
对应的代码如下:(.NetCore WebApi程序)
using Consul;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
namespace NetCore.XFZ.Controllers
{
//[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
#region 依赖注入
private readonly ILogger<TestController> _logger;
private IConfiguration _IConfiguration;
public TestController(ILogger<TestController> logger, IConfiguration configuration)
{
_logger = logger;
_IConfiguration = configuration;
}
#endregion
/// <summary>
/// 调用服务(作为消费者)
/// </summary>
/// <returns></returns>
[Route("api/Test/Invoke")]
public IActionResult Invoke()
{
this._logger.LogInformation("IActionResult-Invoke 执行");
string urlDeault = $"http://ApiServiceTest/api/values";//调用已经启动的服务
string urlTaret = this.ResolveUrlAsync(urlDeault);//将http://ApiServiceTest/api/values转为http://127.0.0.1:5726/api/values
//访问webapi
using (HttpClient httpClient = new HttpClient())
{
HttpRequestMessage requestMessage = new HttpRequestMessage();
requestMessage.Method = HttpMethod.Get;
requestMessage.RequestUri = new Uri(urlTaret);
var result = httpClient.SendAsync(requestMessage).Result;
return new JsonResult(new
{
Id = 222,
Name = "消费者",
result.StatusCode,
urlTaret,
Content = result.Content.ReadAsStringAsync().Result
});
}
}
/// <summary>
/// 获取服务的完整路径
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
private string ResolveUrlAsync(string url)
{
Uri uri = new Uri(url);
string serviceName = uri.Host;
string rootUrl = this.GetServiceAddress(serviceName);
return uri.Scheme + "://" + rootUrl + uri.PathAndQuery;
}
/// <summary>
/// 根据服务名称获取服务地址
/// </summary>
/// <param name="serviceName">服务名称</param>
/// <returns></returns>
private string GetServiceAddress(string serviceName)
{
using (ConsulClient consulClient = new ConsulClient(c => c.Address = new Uri("http://127.0.0.1:8500")))//实例化当前consul
{
//consulClient.Agent.Services() 获取consul中注册的所有服务
Dictionary<string, AgentService> services = consulClient.Agent.Services().Result.Response;
//获取所有服务名字为ApiServiceTest的所有服务
var agentServices = services.Where(s => s.Value.Service.Equals(serviceName, StringComparison.CurrentCultureIgnoreCase)).Select(s => s.Value);
//根据当前TickCount对服务器个数取模,"随机"取一个机器出来,避免"轮询"的负载均衡策略需要计数加锁问题
//可以根据tag--根据用户ip--等各种因素来调度
var agentService = agentServices.ElementAt(Environment.TickCount % agentServices.Count());
return $"{agentService.Address}:{agentService.Port}";
}
}
}
}
代码实现了调用名称为ApiServiceTest的服务。
具体逻辑为:
1.根据要调用的服务名称从Consul中获取到服务的地址
2.根据获取到的服务地址调用webapi服务
浏览器发送请求,返回结果如下:
对上面内容进行格式转换:
其中content的值是从webapi接口中返回的数据。
Consul在这里的功能可以理解为翻译,把服务的名称(ApiServiceTest)翻译为服务的地址(127.0.0.1:5726)。