當(dāng)前位置:首頁(yè) > IT技術(shù) > Web編程 > 正文

Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服務(wù)注冊(cè),服務(wù)發(fā)現(xiàn)
2021-10-22 10:10:14

?

一、簡(jiǎn)介

環(huán)境 .NET5,Consul_v1.10.2

在微服務(wù)中利用Consul可以實(shí)現(xiàn)服務(wù)的注冊(cè),服務(wù)發(fā)現(xiàn),治理,健康檢查等。?

Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服務(wù)注冊(cè),服務(wù)發(fā)現(xiàn)_Consul

?

Web調(diào)站點(diǎn)需要調(diào)用多個(gè)服務(wù),如果沒有Consul,可能就是Web中存了全部服務(wù)的ip地址,如果其中一個(gè)服務(wù)更換了地址,web也要跟著修改配置,所以加入了Consul,web直接通過Consul就能一直取到各個(gè)服務(wù)的最新的地址了。

二、Consul搭建

這里使用Docker安裝 ,確保安裝了Docker,執(zhí)行下面命令。



docker run -d -p 8500:8500 --restart=always --name=consul consul:latest agent -server -bootstrap -ui -node=1 -client='0.0.0.0'


如果是windows環(huán)境,到官網(wǎng)??https://www.consul.io?? 下載exe文件。然后cmd命令切換到consul.exe目錄,執(zhí)行consul.exe agent -dev?即可啟動(dòng)。

安裝完,訪問http:ip:8500,看到如下界面則安裝成功。

Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服務(wù)注冊(cè),服務(wù)發(fā)現(xiàn)_微服務(wù)_02

?

三、服務(wù)注冊(cè)

安裝NuGet包 --Consul

appsettings.json增加Consul信息



{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"urls": "http://*:5200",
"Consul": {
"consulAddress": "http://172.16.2.84:8500",
"serviceName": "api",
"currentIp": "172.16.2.9",
"currentPort": "5200"
}

}


增加ConsulRegister.cs



/// <summary>
/// Consul注冊(cè)
/// </summary>
public static class ConsulRegister
{
//服務(wù)注冊(cè)
public static IApplicationBuilder UseConsul(this IApplicationBuilder app, IConfiguration configuration)
{
// 獲取主機(jī)生命周期管理接口
var lifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();

ConsulClient client = new ConsulClient(c =>
{
c.Address = new Uri(configuration["Consul:consulAddress"]);
c.Datacenter = "dc1";
});
string ip = configuration["ip"];
string port = configuration["port"];
string currentIp = configuration["Consul:currentIP"];
string currentPort = configuration["Consul:currentPort"];

ip = string.IsNullOrEmpty(ip) ? currentIp : ip; //當(dāng)前程序的IP
port = string.IsNullOrEmpty(port) ? currentPort : port; //當(dāng)前程序的端口
string serviceId = $"service:{ip}:{port}";//服務(wù)ID,一個(gè)服務(wù)是唯一的
//服務(wù)注冊(cè)
client.Agent.ServiceRegister(new AgentServiceRegistration()
{
ID = serviceId, //唯一的
Name = configuration["Consul:serviceName"], //組名稱-Group
Address = ip, //ip地址
Port = int.Parse(port), //端口
Tags = new string[] { "api站點(diǎn)" },
Check = new AgentServiceCheck()
{
Interval = TimeSpan.FromSeconds(10),//多久檢查一次心跳
HTTP = $"http://{ip}:{port}/Health/Index",
Timeout = TimeSpan.FromSeconds(5),//超時(shí)時(shí)間
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5) //服務(wù)停止多久后注銷服務(wù)
}

}).Wait();
//應(yīng)用程序終止時(shí),注銷服務(wù)
lifetime.ApplicationStopping.Register(() =>
{
client.Agent.ServiceDeregister(serviceId).Wait();
});
return app;
}
}


在Startup.cs中?Configure(IApplicationBuilder app, IWebHostEnvironment env)方法后面加上? app.UseConsul(Configuration);



public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
//Consul注冊(cè)
app.UseConsul(Configuration);
}


增加健康檢查接口

上面Consul注冊(cè)處有一個(gè)Check? Http的是心跳健康檢查的地址,需要提供一個(gè)接口。

新建HealthController.cs



/// <summary>
/// consul健康檢查
/// </summary>
public class HealthController : Controller
{
public IActionResult Index()
{
return Ok();
}
}


?

這樣就配置好了,啟動(dòng)項(xiàng)目時(shí)就會(huì)把服務(wù)注冊(cè)到Consul,我這里用發(fā)布文件同時(shí)啟動(dòng)三個(gè)做負(fù)載。



dotnet ConsulAndOcelot.Demo.ServerB.dll --urls="http://*5201" --ip="172.16.2.9" --port=5201

dotnet ConsulAndOcelot.Demo.ServerB.dll --urls="http://*5202" --ip="172.16.2.9" --port=5202

dotnet ConsulAndOcelot.Demo.ServerB.dll --urls="http://*5203" --ip="172.16.2.9" --port=5203


?

Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服務(wù)注冊(cè),服務(wù)發(fā)現(xiàn)_microsoft_03

?

?

?Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服務(wù)注冊(cè),服務(wù)發(fā)現(xiàn)_Consul_04

?

?

啟動(dòng)后,再看一下Consul界面,可以發(fā)現(xiàn)服務(wù)已成功注冊(cè)到Consul。

Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服務(wù)注冊(cè),服務(wù)發(fā)現(xiàn)_微服務(wù)_05

?

?

Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服務(wù)注冊(cè),服務(wù)發(fā)現(xiàn)_服務(wù)發(fā)現(xiàn)_06

四、服務(wù)發(fā)現(xiàn)

另外建一個(gè).NetCore程序。

安裝Nuget包 --Consul

appsettings.json?配置Consul信息



{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"Consul": {
"consulAddress": "http://172.16.2.84:8500",
"serviceName": "platform",
"apiServiceName": "api"
}
}


新建ConsulHelper.cs類



/// <summary>
/// Consul幫助類
/// </summary>
public class ConsulHelper
{
private IConfiguration _configuration;
public ConsulHelper(IConfiguration configuration)
{
_configuration = configuration;
}
/// <summary>
/// 根據(jù)服務(wù)名稱獲取服務(wù)地址
/// </summary>
/// <param name="serviceName"></param>
/// <returns></returns>
public string GetDomainByServiceName(string serviceName)
{
string domain = string.Empty;
//Consul客戶端
using (ConsulClient client = new ConsulClient(c =>
{
c.Address = new Uri(_configuration["Consul:consulAddress"]);
c.Datacenter = "dc1";

})
)
{
//根據(jù)服務(wù)名獲取健康的服務(wù)
var queryResult = client.Health.Service(serviceName, string.Empty, true);
var len = queryResult.Result.Response.Length;
//平均策略-多個(gè)負(fù)載中隨機(jī)獲取一個(gè)
var node = queryResult.Result.Response[new Random().Next(len)];
domain = $"http://{node.Service.Address}:{node.Service.Port}";
}
return domain;
}

/// <summary>
/// 獲取api域名
/// </summary>
/// <returns></returns>
public string GetApiDomain()
{
return GetDomainByServiceName(_configuration["Consul:apiServiceName"]);
}
}


把ConsulHelper注入到IOC容器,Startup.cs中。ConfigureServices(IServiceCollection services)方法加上



public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddTransient<ConsulHelper>();
}


驗(yàn)證



public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly ConsulHelper _consulHelper;

public HomeController(ILogger<HomeController> logger, ConsulHelper consulHelper)
{
_logger = logger;
_consulHelper = consulHelper;
}

public IActionResult Index()
{
///獲取api服務(wù)地址
var domain = _consulHelper.GetApiDomain();
ViewBag.domain = domain;
return View();
}
}


執(zhí)行結(jié)果,通過Consul獲得了服務(wù)地址,刷新后會(huì)隨獲取到三個(gè)負(fù)載中的一個(gè)。

Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服務(wù)注冊(cè),服務(wù)發(fā)現(xiàn)_微服務(wù)_07

?

?

Consul只負(fù)責(zé)服務(wù)發(fā)現(xiàn),沒有自帶負(fù)載均衡策略。用上面的平均策略就可以了,如果想要做成輪詢策略的也可以,不過會(huì)增加一些開銷,可以給每組服務(wù)定義一個(gè)

靜態(tài)自增變量index=0,然后獲取的時(shí)候,index%服務(wù)數(shù)取余,然后index++,這樣就是0%3=0,1%3=1,2%3=2,3%3=0一直循環(huán),獲取List[index]服務(wù),index>10000的時(shí)候重置為0,這樣就能循環(huán)的調(diào)用了。Conul后面配合Ocelot網(wǎng)關(guān)使用,Ocelot中會(huì)自帶幾種負(fù)載策略。

源碼地址:??https://github.com/weixiaolong325/Ocelot-Consul-Polly-Id4.Demo??

本文摘自 :https://blog.51cto.com/u

開通會(huì)員,享受整站包年服務(wù)立即開通 >