著者
マイクロ手紙:tangy8080
Eメール:[email protected]は
更新:2019年6月28日午後02時25分40秒金曜日
時折共有記事は、サブスクリプションの数以内に私自身の学習過程の一部を用意し、を購読し、私のサブスクリプション番号を共有する歓迎
あなたが読み取り処理に記事の誤りを見つけた場合、あなたは私のマイクロ文字tangy8080フィードバックを追加することができます。あなたのサポートをありがとう。
トピック
複数のサービス間の通信は、導入します
前置条件
[なし]
テキスト
あまりにも頻繁に相互に呼び出しチェーンが。異常全体の呼び出しチェーンを引き起こす可能性がある場合、結合度を低減するために、サービス間の少ない通話しようとする必要があります。
Https://docs.microsoft.com/en-us/dotnet/standard/microservices-アーキテクチャ/建築家・microService-コンテナアプリケーション/コミュニケーション・イン・microService・アーキテクチャ
microServiceコミュニティのが「スマートエンドポイントおよびダムパイプ」の理念を推進し、このスローガンには、デザインを奨励しているAS APOS microservices BETWEENできるだけ切り離され、WITHINできるだけ凝集単一microservice。としては、先に説明したが、各microserviceは、独自のデータと、自身のドメインロジックを所有している。しかし、エンドツーエンドのアプリケーションを構成するmicroservicesは、通常、単にREST通信ではなく、そのようなWS- *やフレキシブルなどの複雑なプロトコルを使用して、振り付けさイベント駆動型通信の代わりに、中央集中型のビジネス -process-オーケストレータ。
しかし、サービス間の通話は、時々 、最後の章に「その自然とともに」となっ自動サービス発見領事の使用はK8S実現
例として、サービスの終了時に2を
- でも外で全体としてconfigcenterクラスター、(この時、我々は概念に関与している:? ZTE集中管理権限を許可されていない場合、それは設定が非常に危険になり、まだこの問題は、我々は後で言及されますアクセスするために、クラスタ外ではないでしょう)物流センター(記憶のためのIT KVコンサル)統一された構成を提供
- 端末が通知を更新するなど、外部端子クラスタの集中制御を提供するターミナルサービス、などの端末は、端末が送信する通知等
端末は端末ごとにデータを格納するためのデータベース情報(IPなど、ポートなど)を設定する必要があり、設定がでconfigcenterに保存されている。それにconfigcenterからターミナルサービス構成を削除するには、どのように?この時間は、サービス間の通信を必要とします
サービス間でどのように通信
すべての通信に関連し、通常は二つの概念を必要とします
- などのプロトコルTCP、UDP、HTTP、?
- クライアント・サーバ・プロトコルに基づいてJSON、XMLなど、自動的に生成するコードについてQIEデータ
通信プロトコル
マイクロサービス間の通信がより普及し、2つのTCPおよびHTTPがあります
- スリフト、GRPCなど:TCP通信に基づいてから選択するフレームワークがいくつかあります
HTTP
領事の手のラインとマイクロサービスとの間のベースのライブラリとHTTPプロトコル
ここで、私は次のように、その動作モードを簡単なマイクロサービスとの間、自分の手のラインとライブラリの呼び出しを選択する必要があります
ConsulCallerでは、我々は領事の図書館サービスの発見を使用しています。彼らは、サービスインスタンスを見つけた場合、プログラムがランダムアルゴリズムに従ってインスタンスを選択し、その後、呼び出し元に戻りました。
送信元アドレス
gitの://gitblit.honeysuckle.site/public/Honeysuckle.git
実装を説明します
- 広がり関数AddConsulCallerを増やし、IServiceCollectionを拡張。呼び出し側。で、着信サービスの構成情報領事を設定するための機能
ので、ここで簡単ではあるが、より説明の領事のアドレス、ポート、トークンを含め、IConsulConfiguration領事定義された設定パラメータ。
public static void AddConsulCaller(this IServiceCollection services, Action<ConsulCallerOptions> optionsAction)
{
var consulConfiguration=new ConsulConfiguration();
services.AddSingleton<IConsulConfiguration>(consulConfiguration);
services.AddSingleton<IServiceDiscover, ServiceDiscover>();
services.AddSingleton<IConsulClientFactory, ConsulClientFactory.ConsulClientFactory>();
services.AddTransient<IConsulCaller, ConsulCaller>();
var consulCallerOptions = new ConsulCallerOptions(consulConfiguration);
optionsAction.Invoke(consulCallerOptions);
}
- 私はGet関数が含まれているIConsulClientFactoryインタフェースを定義します。IConsulClientはオブジェクトを返すために使用される。オブジェクトがで発見サービスインスタンスの領事をサポートしています
public IConsulClient Get(IConsulConfiguration config)
{
return new ConsulClient(c =>
{
c.Address = new Uri($"http://{config.Host}:{config.Port}");
if (!string.IsNullOrEmpty(config?.Token))
{
c.Token = config.Token;
}
});
}
3.もう一つの重要なインターフェイス機能を含むIServiceDiscover、GetServicesあり、機能は、サービス・インスタンスに係るサービスリストの名前を返します
private readonly IConsulClient _consul;
private const string VersionPrefix = "version-";
public ServiceDiscover(IConsulClientFactory consulClientFactory, IConsulConfiguration consulConfiguration)
{
_consul = consulClientFactory.Get(consulConfiguration);
}
public List<Service> GetServices(string key)
{
var queryResult = _consul.Health.Service(key, string.Empty, true).Result;
var services = new List<Service>();
foreach (var serviceEntry in queryResult.Response)
{
if (IsValid(serviceEntry))
{
var nodes = _consul.Catalog.Nodes().Result;
if (nodes.Response == null)
{
services.Add(BuildService(serviceEntry, null));
}
else
{
var serviceNode = nodes.Response.FirstOrDefault(n => n.Address == serviceEntry.Service.Address);
services.Add(BuildService(serviceEntry, serviceNode));
}
}
else
{
Console.WriteLine($"Unable to use service Address: {serviceEntry.Service.Address} and Port: {serviceEntry.Service.Port} as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0");
}
}
return services;
}
private static Service BuildService(ServiceEntry serviceEntry, Node serviceNode)
{
return new Service(
serviceEntry.Service.Service,
new ServiceHostAndPort(serviceNode == null ? serviceEntry.Service.Address : serviceNode.Name, serviceEntry.Service.Port),
serviceEntry.Service.ID,
GetVersionFromStrings(serviceEntry.Service.Tags),
serviceEntry.Service.Tags ?? Enumerable.Empty<string>());
}
private static bool IsValid(ServiceEntry serviceEntry)
{
if (string.IsNullOrEmpty(serviceEntry.Service.Address) || serviceEntry.Service.Address.Contains("http://") || serviceEntry.Service.Address.Contains("https://") || serviceEntry.Service.Port <= 0)
{
return false;
}
return true;
}
private static string GetVersionFromStrings(IEnumerable<string> strings)
{
return strings
?.FirstOrDefault(x => x.StartsWith(VersionPrefix, StringComparison.Ordinal))
.TrimStart(VersionPrefix);
}
4.最後に、我々は、コール・インタフェースを提供IConsulCallerインターフェースを、提供するサービス名とコールバック関数を入力します。
どのように使用するには?
参照asp.netコアサービスで1. ConsulCallerを追加しました
//使用ConsulCaller服务
services.AddConsulCaller(options =>
{
options.ConsulConfiguration.Host = Configuration["Consul:Host"];
options.ConsulConfiguration.Port = Convert.ToInt32(Configuration["Consul:Port"]);
});
2.他のサービスのクラスタを呼び出し
const string serviceName = "configcenter";
_consulCaller.Call(serviceName, (endpoint, httpclient) =>
{
try
{
var uri = $"http://{endpoint.DownstreamHost}:{endpoint.DownstreamPort}/Consul/Get";
//根据返回的服务实例,实现自己的调用逻辑
}
catch (Exception ex)
{
var errorMsg = $"{nameof(TerminalServerDbContext)}.{nameof(OnConfiguring)} _consulCaller.Call Error ";
Console.WriteLine(errorMsg + ex.Message);
Logger.Error(errorMsg, ex);
}
finally
{
httpclient.Dispose();
}
});
- 最初のステップでIConsulCallerオブジェクトが容器IServiceCollection内に注入されています
参考リンク
[なし]