マイクロサービス入門.3
目次
Show Me the Code
何を解決しようとしているか。
APIゲートウェイを作成したとき、サービスの場所(ホスト+ポート)を手動で定義しなければなりませんでした.しかし、以下のシナリオを想像してください:与えられたサービスはX軸で縮小される必要があります.新しいインスタンスは異なる場所を持ち、クライアントに動的に利用できるようにしなければなりません.
また、我々のサービスインスタンスのうちの1つがどんな点でも利用できなくなるなら、ゲートウェイはそれが利用できない間、それがそのインスタンスにルート要求をすることができないのを意識しなければなりません.
ソリューション:サービスレジストリ&ヘルスチェック
To solve our problems, we'll be using a combination of two patterns. First, let's discuss the Service Registry pattern.
The Service Registry is, as the name suggests, another service on our ecosystem, that is responsible to register all the services/instances of our application, and keep track of their location. By doing that, our Gateway can, any time that a request arrives, check with the Registry and route the request accordingly. This makes it invisible to the client which instance will receive its request and, as the instances change, the Gateway can always know valid locations! This is known as Server-side discovery.
図1.サーバ側発見
また、サービスが互いに協力しなければならないので、彼らも、他のサービスインスタンスの位置を見つけるためにサービスレジストリにアクセスすることができます.これはクライアント側の発見として知られています.
図2.クライアント側発見
サービスレジストリの利点
サービスレジストリの欠点
健康チェックの利益
健康診断の欠点
コードを見せてください
So, let's begin with the code needed to implement our Service Registry, service registration and health checks.
サービスレジストリ
We'll begin by going the Consul.io ウェブサイトとダウンロード.Consulは私たちのサービスレジストリとして機能します.このチュートリアルの目的のために、開発者モードでconsulを実行します.consulをダウンロードした後、システムパスに追加することもできます.consul agent --dev
当社のサービスレジストリには、それです.もう走っている.あなたがアクセスしてそれをチェックすることができますhttps://localhost:8500/ .さて、我々のゲートウェイを調整するために移動しましょうので、それは有効なサービス/インスタンスの場所のための私達のレジストリをチェックします.我々は、オセロットを編集することから始めます.JSONファイル
{
"Routes": [
"DownstreamPathTemplate": "/api/v1/{everything}",
"DownstreamScheme": "https",
"UpstreamPathTemplate": "/api/gateway/{everything}",
"UpstreamHttpMethod": [ "GET", "POST", "PUT", "PATCH", "DELETE" ],
"ServiceName": "YOUR-SERVICE-NAME"
],
"GlobalConfiguration": {
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 8500,
"Type": "Consul"
}
}
}
ご覧のように、「DownStreamHorestPorts」プロパティを削除し、「ServiceName」プロパティーをルートに追加しました.次に、「ServiceDiscoveryProvider」プロパティーを追加し、ホスト名、ポート、およびサービスの種類を入力します.この設定を完了するには、プロジェクトに別のパッケージを追加する必要があります.dotnet add package Ocelot.Provider.Consul
インストール後、「起動」csファイルをもう一度編集し、次のように追加します.// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddOcelot().AddConsul();
// ...
}
これはゲートウェイの設定です.さて、サービスを設定する必要があります.彼らは領事と登録する必要がありますか?それが我々が次にすることです.登録したいサービスについては、consulパッケージを追加しなければなりません.
dotnet add package Consul
その後、何かをする必要があります.最初に、私たちの“appsettings . json”にいくつかの必要な設定を追加する必要があります."ConsulConfig": {
"Host": "http://localhost:8500",
"ServiceName": "YOUR-SERVICE-NAME"
"ServiceId": "AN-UNIQUE-ID-FOR-EACH-INSTANCE"
}
重要:あなたは“ocelot . json”ファイルのルーティングで同じ“ServiceName”を使用する必要があります.また、同じサービスの複数のインスタンスを使用する場合は「サービスID」が必要です.その後、我々はWeb API上でサービスとしてConsul登録を追加する必要があります.
public static IServiceCollection AddConsulConfig(
this IServiceCollection services,
IConfiguration configuration
)
{
services.AddSingleton<IConsulClient, ConsulClient>(
p => new ConsulClient(
consulConfig =>
{
var address = configuration.GetValue<string>(
"ConsulConfig:Host"
);
consulConfig.Address = new Uri(address);
}
)
);
return services;
}
これはConsulクライアントインスタンスをWeb APIに追加します.さて、クライアントインスタンスを使用してConsulで登録を行う必要があります.public static IApplicationBuilder UseConsul(
this IApplicationBuilder app,
IConfiguration configuration
)
{
var consulClient = app.ApplicationServices
.GetRequiredService<IConsulClient>();
var logger = app.ApplicationServices
.GetRequiredService<ILoggerFactory>()
.CreateLogger("AppExtensions");
var lifetime = app.ApplicationServices
.GetRequiredService<IApplicationLifetime>();
if (!(app.Properties["server.Features"] is FeatureCollection features))
{
return app;
}
var addresses = features.Get<IServerAddressesFeature>();
var address = addresses.Addresses.First();
Console.WriteLine($"address={address}");
var serviceName = configuration.GetValue<string>(
"ConsulConfig:ServiceName"
);
var serviceId = configuration.GetValue<string>(
"ConsulConfig:ServiceId"
);
var uri = new Uri(address);
var registration = new AgentServiceRegistration()
{
ID = serviceId,
Name = serviceName,
Address = $"{uri.Host}",
Port = uri.Port
};
logger.LogInformation("Registering with Consul");
consulClient.Agent
.ServiceDeregister(registration.ID)
.ConfigureAwait(true);
consulClient.Agent
.ServiceRegister(registration)
.ConfigureAwait(true);
lifetime.ApplicationStopping.Register(() =>
{
logger.LogInformation("Unregistering from Consul");
consulClient.Agent.ServiceDeregister(registration.ID)
.ConfigureAwait(true);
});
return app;
}
上記のコードは、同じIDで登録された以前のインスタンスを削除し、サービス/インスタンスを登録します.最後に、シャットダウンしたときに、サービス/インスタンスをデバッグする必要があることをWeb APIに伝えます.そして、我々はしました!現在、我々のサービスはConsulで登録して、APIゲートウェイに利用可能になりました.健康診断を実施し始めましょう!
健康チェック
To add our health check, we first need to install the "AspNetCore.HealthChecks.System" package. This will add some basic health check features. If you need to check the connection to your database, you'll need another package. In my repository, I used PostgreSQL, so, in my case, I needed to add the "AspNetCore.HealthChecks.NpgSql" package.
dotnet add package AspNetCore.HealthChecks.System
dotnet add package AspNetCore.HealthChecks.NpgSql
After the installation, we'll add the following code to our "ConfigureServices" method:
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// ...
var builder = services.AddHealthChecks();
builder.AddProcessAllocatedMemoryHealthCheck(
500 * 1024 * 1024,
"Process Memory",
tags: new[] { "self" }
);
builder.AddPrivateMemoryHealthCheck(
500 * 1024 * 1024,
"Private memory",
tags: new[] { "self" }
);
builder.AddNpgSql(
Configuration.GetConnectionString("DefaultConnection"),
tags: new[] { "service" }
);
// ...
}
We've just added some checks for the amount of memory our Web API is consuming (the limit is 500MB for both "Process Memory" and "Private Memory"), and a check for our database connection.
Finally, we need to create some endpoints to access this information. So, we'll add the following to our "Configure" method:
// Startup.cs
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHealthChecks(
"/health",
new HealthCheckOptions()
{
AllowCachingResponses = false,
Predicate = r => r.Tags.Contains("self"),
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
}
);
app.UseHealthChecks(
"/ready",
new HealthCheckOptions()
{
AllowCachingResponses = false,
Predicate = r => r.Tags.Contains("service"),
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
}
);
// ...
}
We've just added the endpoints "/health" and "/ready" to our Web API. Now, we need to tell our Service Registry that it should perform checks on the endpoints we've just created.
Let's go back to our "UseConsul" method and add the following:
var registration = new AgentServiceRegistration()
{
ID = serviceId,
Name = serviceName,
Address = $"{uri.Host}",
Port = uri.Port,
Checks = [
new AgentServiceCheck()
{
Name = configuration.GetValue<string>("ConsulConfig:ServiceName"),
HTTP = $"https://{uri.Host}:{uri.Port}/health",
Interval = TimeSpan.FromSeconds(30),
},
new AgentServiceCheck()
{
Name = configuration.GetValue<string>("ConsulConfig:ServiceName"),
HTTP = $"https://{uri.Host}:{uri.Port}/ready",
Interval = TimeSpan.FromSeconds(30),
},
],
};
That's it! Now our services can register and tell the Service Registry about their health checks. Consul will perform the checks every 30 seconds and, if the check fails, the service will be marked as 'unhealthy' and won't receive any requests until it resolve its problems.
IMPORTANT: if your Consul instance can't perform the checks, try changing the 'https' to 'http' and the port to the 'http' port!
The next topic of the series is . Until next time!
参考文献
Reference
この問題について(マイクロサービス入門.3), 我々は、より多くの情報をここで見つけました https://dev.to/bernas1104/an-introduction-to-microservices-pt-3-h13テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol