前言
在上一篇文章【.Net Core微服務(wù)入門全記錄(一)-項(xiàng)目搭建】說到服務(wù)的彈性伸縮,就需要有一種機(jī)制來實(shí)現(xiàn)。這種機(jī)制就是服務(wù)注冊和發(fā)現(xiàn)。當(dāng)然,這不是必需的。如果您的服務(wù)實(shí)例很少且穩(wěn)定,則無需使用服務(wù)注冊和發(fā)現(xiàn)。
服務(wù)注冊和發(fā)現(xiàn)
通過服務(wù)注冊和發(fā)現(xiàn),客戶端不需要配置每個(gè)服務(wù)實(shí)例的地址core 注冊機(jī),而是從注冊中心獲取。注冊中心如何保證每個(gè)地址的可用性,如果一個(gè)實(shí)例掛了怎么辦?掛機(jī)的實(shí)例原則上不應(yīng)該被客戶端獲取,所以需要提一下:健康檢查。
常見的注冊表是 , , etcd 。
官網(wǎng):主要功能包括服務(wù)注冊與發(fā)現(xiàn)、健康檢查、KV存儲、多數(shù)據(jù)中心等。
已成功運(yùn)行。
服務(wù)注冊
封裝在這個(gè)類庫中的api操作方便我們直接使用。當(dāng)然,自己寫http調(diào)用的接口也不是不可能。. . 接口說明:
。CS:
public static class ConsulHelper
{
///
/// 服務(wù)注冊到consul
///
///
///
public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IConfiguration configuration, IHostApplicationLifetime lifetime)
{
var consulClient = new ConsulClient(c =>
{
//consul地址
c.Address = new Uri(configuration["ConsulSetting:ConsulAddress"]);
});
var registration = new AgentServiceRegistration()
{
ID = Guid.NewGuid().ToString(),//服務(wù)實(shí)例唯一標(biāo)識
Name = configuration["ConsulSetting:ServiceName"],//服務(wù)名
Address = configuration["ConsulSetting:ServiceIP"], //服務(wù)IP
Port = int.Parse(configuration["ConsulSetting:ServicePort"]),//服務(wù)端口 因?yàn)橐\(yùn)行多個(gè)實(shí)例,端口不能在appsettings.json里配置,在docker容器運(yùn)行時(shí)傳入
Check = new AgentServiceCheck()
{
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服務(wù)啟動(dòng)多久后注冊
Interval = TimeSpan.FromSeconds(10),//健康檢查時(shí)間間隔
HTTP = $"http://{configuration["ConsulSetting:ServiceIP"]}:{configuration["ConsulSetting:ServicePort"]}{configuration["ConsulSetting:ServiceHealthCheck"]}",//健康檢查地址
Timeout = TimeSpan.FromSeconds(5)//超時(shí)時(shí)間
}
};
//服務(wù)注冊
consulClient.Agent.ServiceRegister(registration).Wait();
//應(yīng)用程序終止時(shí),取消注冊
lifetime.ApplicationStopping.Register(() =>

{
consulClient.Agent.ServiceDeregister(registration.ID).Wait();
});
return app;
}
}
復(fù)制
.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConsulSetting": {
"ServiceName": "OrderService",
"ServiceIP": "localhost",
"ServiceHealthCheck": "/healthcheck",
"ConsulAddress": "http://host.docker.internal:8500"http://注意,docker容器內(nèi)部無法使用localhost訪問宿主機(jī)器,如果是控制臺啟動(dòng)的話就用localhost
}
}
復(fù)制
。CS:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime lifetime)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
//服務(wù)注冊
app.RegisterConsul(Configuration, lifetime);
}
}
復(fù)制
。CS:
[Route("[controller]")]
[ApiController]
public class OrdersController : ControllerBase
{
private readonly ILogger _logger;
private readonly IConfiguration _configuration;
public OrdersController(ILogger logger, IConfiguration configuration)
{
_logger = logger;
_configuration = configuration;
}
[HttpGet]
public IActionResult Get()
{
string result = $"【訂單服務(wù)】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}——" +
$"{Request.HttpContext.Connection.LocalIpAddress}:{_configuration["ConsulSetting:ServicePort"]}";
return Ok(result);
}
}
復(fù)制
r.cs:
[Route("[controller]")]
[ApiController]
public class HealthCheckController : ControllerBase
{
///
/// 健康檢查接口
///
///
[HttpGet]
public IActionResult Get()
{
return Ok();
}
}
復(fù)制
至此,服務(wù)注冊、注銷、健康檢查等功能的代碼編寫已經(jīng)完成。
運(yùn)行服務(wù)
繼續(xù)運(yùn)行服務(wù)實(shí)例,如果不習(xí)慣可以用控制臺啟動(dòng)。--:參數(shù)是傳入容器的端口信息。
docker build -t orderapi:1.0 -f ./Order.API/Dockerfile .
docker run -d -p 9060:80 --name orderservice orderapi:1.0 --ConsulSetting:ServicePort="9060"
docker run -d -p 9061:80 --name orderservice1 orderapi:1.0 --ConsulSetting:ServicePort="9061"
docker run -d -p 9062:80 --name orderservice2 orderapi:1.0 --ConsulSetting:ServicePort="9062"
docker build -t productapi:1.0 -f ./Product.API/Dockerfile .
docker run -d -p 9050:80 --name productservice productapi:1.0 --ConsulSetting:ServicePort="9050"
docker run -d -p 9051:80 --name productservice1 productapi:1.0 --ConsulSetting:ServicePort="9051"
docker run -d -p 9052:80 --name productservice2 productapi:1.0 --ConsulSetting:ServicePort="9052"
復(fù)制
到目前為止,所有 6 個(gè)服務(wù)器實(shí)例都在運(yùn)行并成功注冊。
只需停止 2 項(xiàng)服務(wù):
可以看到停止的服務(wù)已經(jīng)被刪除了。請注意,當(dāng)我們停止程序時(shí),它會被主動(dòng)調(diào)用以刪除。
//應(yīng)用程序終止時(shí),取消注冊
lifetime.ApplicationStopping.Register(() =>
{
consulClient.Agent.ServiceDeregister(registration.ID).Wait();
});
復(fù)制
當(dāng)然,如果程序發(fā)生異常core 注冊機(jī),健康檢查未能正確響應(yīng),也會被移除core 注冊機(jī),有一點(diǎn)區(qū)別。
至此,注冊、發(fā)現(xiàn)、健康檢查功能就完成了。下一步是考慮客戶端如何獲取這些服務(wù)實(shí)例的地址。
代碼放置在:
未完待續(xù)...