微服务彻底改变了我们构建和扩展应用程序的方式。通过将较大的系统分解为较小的独立服务,我们获得了灵活性、敏捷性和快速适应不断变化的需求的能力。但是,微服务系统也非常动态。服务可以来来去去,可以扩大或缩小,甚至可以在基础设施中移动。
这种动态性质带来了巨大的挑战。您的服务如何可靠地找到彼此并与之通信?
对 IP 地址和端口进行硬编码是造成脆弱性的原因。如果服务实例更改位置或新实例启动,则整个系统可能会停止运行。
服务发现充当微服务的中心目录。它为服务提供了一种机制,用于注册自身并发现其他服务的位置。
在本周的期刊中,我们将了解如何使用 Consul 在 .NET 微服务中实现服务发现。
服务发现是一种模式,允许开发人员使用逻辑名称来引用外部服务,而不是物理 IP 地址和端口。它为服务提供了一个集中的位置来注册自己。客户端可以查询服务注册中心以查找服务的物理地址。这在大型分布式系统(如 Netflix 和 Amazon)中很常见。
以下是服务发现流程的样子:
当我们有多个想要调用的服务时,同样的概念也适用。每个服务都会在服务注册中心中注册自身。客户端使用逻辑名称来引用服务,并从服务注册表中解析物理地址。
最受欢迎的服务发现解决方案是 Netflix、Eureka 和 HashiCorp、Consul。
库中还有一个来自 Microsoft 的轻量级解决方案。它使用应用程序设置来解析服务的物理地址,因此仍需要一些手动工作。但是,可以在 Azure 应用程序配置中存储集中式服务注册表的服务位置。我将在以后的一些文章中探讨这个服务发现库。Microsoft.Extensions.ServiceDiscovery
但现在我想向你展示如何将 Consul 与 .NET 应用程序集成。
在本地运行 Consul 服务器的最简单方法是使用 Docker 容器。您可以创建映像的容器实例。hashicorp/consul
下面是将 Consul 服务配置为文件的一部分的示例:docker-compose
consul:
image: hashicorp/consul:latest
container\_name: Consul
ports:
\- '8500:8500'
如果您导航到 ,您将看到 Consul Dashboard。localhost:8500
现在,让我们看看如何在 Consul 上注册我们的服务。
我们将使用 Steeltoe Discovery 库通过 Consul 实现服务发现。Consul 客户端实现让您的应用程序能够向 Consul 服务器注册服务,并发现其他应用程序注册的服务。
让我们安装这个库:Steeltoe.Discovery.Consul
Install-Package Steeltoe.Discovery.Consul
我们必须通过调用并显式配置 Consul 服务发现客户端来配置一些服务。另一种选择是调用,它在运行时使用反射来确定哪个服务注册表可用。AddServiceDiscoveryAddDiscoveryClient
using Steeltoe.Discovery.Client;
using Steeltoe.Discovery.Consul;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddServiceDiscovery(o => o.UseConsul());
var app = builder.Build();
app.Run();
最后,我们的服务可以通过应用程序设置配置逻辑服务名称来向 Consul 注册。当应用程序启动时,逻辑名称将被添加到 Consul 服务注册表中。Consul 将存储此服务的相应实际地址。reporting-service
{
"Consul": {
"Host": "localhost",
"Port": 8500,
"Discovery": {
"ServiceName": "reporting-service",
"Hostname": "reporting-api",
"Port": 8080
}
}
}
当我们启动应用程序并打开 Consul 仪表板时,我们应该能够看到及其各自的物理地址。reporting-service
在使用 HTTP 进行 HTTP 调用时,我们可以使用服务发现。服务发现允许我们为要调用的服务使用逻辑名称。发送网络请求时,服务发现客户端会将逻辑名称替换为正确的物理地址。HttpClient
在此示例中,我们将配置类型化客户端的基址,并通过调用 来添加服务发现。ReportingServiceClienthttps://reporting-serviceAddServiceDiscovery
负载均衡是一个可选步骤,我们可以通过调用 or 来配置它。您还可以通过提供实现来配置自定义负载均衡策略。
builder.Services
.AddHttpClient<ReportingServiceClient>(client =>
{
client.BaseAddress = new Uri("https://reporting-service");
})
.AddServiceDiscovery()
.AddRoundRobinLoadBalancer();
我们可以像常规客户端一样使用类型化客户端来发出请求。服务发现客户端将请求发送到外部服务的 IP 地址。ReportingServiceClientHttpClient
app.MapGet("articles/{id}/report",
async (Guid id, ReportingServiceClient client) =>
{
var response = await client
.GetFromJsonAsync<Response>($"api/reports/article/{id}");
return response;
});
服务发现通过自动执行服务注册和发现来简化微服务的管理。这消除了手动配置更新的需要,从而降低了出错的风险。
服务可以按需发现彼此的位置,确保通信渠道即使在服务环境发生变化时也能保持开放。通过使服务能够在发生中断或故障时发现替代服务实例,服务发现可以增强微服务系统的整体弹性。
源代码获取:公众号回复消息【code:13261
】