マイクロサービスアーキテクチャでインフラストラクチャを構築した経験







過去1年間、マイクロサービスについて非常に多くの出版物があったため、マイクロサービスの内容と理由を説明するのは時間の無駄になるため、残りの議論では、このアーキテクチャを実装する方法と、正確に直面した理由と直面した問題に焦点を当てます。







小さな銀行では大きな問題がありました。大量のレガシーとの膨大な量の同期RPCインタラクションによって接続された3つのpythonモノリス。 同時に発生するすべての問題を少なくとも部分的に解決するために、マイクロサービスアーキテクチャに切り替えることが決定されました。 しかし、そのようなステップを決定する前に、3つの主要な質問に答える必要があります。









これらの質問に対する実際の簡単な回答は、この記事に当てられます。







モノリスをマイクロサービスに分割する方法と、従うべき基準。



この一見単純な質問が、最終的にすべてのさらなるアーキテクチャを決定しました。







私たちは銀行です。したがって、システム全体は、財政とさまざまな補助的なものを備えた業務を中心に展開します。 sagasを使用して金融システムのACIDトランザクションを分散システムに転送することは確かに可能ですが、一般的なケースでは非常に困難です。 したがって、次のルールを開発しました。









当然ながら、同時にそれらを完全に満たすことは不可能でしたが、部分的な実装でさえ開発を大幅に簡素化します。







マイクロサービスはどのように相互作用しますか?



多くのオプションがありますが、最終的にはすべてが単純な「マイクロサービス交換メッセージ」によって抽象化できますが、同期プロトコル(RESTを介したRPCなど)を実装する場合、モノリスの欠点のほとんどは残りますが、マイクロサービスの利点はほとんど現れません。 したがって、明らかな決定は、メッセージブローカーを使用して開始することでした。 RabbitMQとKafkaのどちらを選択するかは後者に決まっています。その理由は次のとおりです。









さらに、 非常に高品質で詳細な比較に注意を喚起したいと思います。







kafka + asynchronyのキューにより、次のことが可能になります。









データのシリアル化システムとして、AVROを選択しました。理由は別の記事に記載されています







ただし、選択したシリアル化方法に関係なく、プロトコルの更新方法を理解することが重要です。 AVROはスキーマ解決をサポートしていますが、これを使用せず純粋に管理上決定します。









AVRO回路自体をgitサブモジュールに保存し、すべてのkafkaプロジェクトに接続します。 彼らは、スキームの集中レジストリをまだ実装しないことに決めました。







PS:同僚は、AVROの代わりにJSONスキーマでのみオープンソースオプションを作成しました







いくつかの微妙な点



各サブスクライバーは、トピックからすべてのメッセージを受信します



これがパブリッシュ-サブスクライブインタラクションモデルの特異性です。トピックをサブスクライブすると、サブスクライバーはそれらすべてを受け取ります。 その結果、サービスで必要なのが一部のメッセージのみである場合、それらを除外する必要があります。 これが問題になる場合は、いくつかの異なるトピックでメッセージをレイアウトする個別のサービスルーターを作成し、それによってkafkaにはないRabbitMQ機能の一​​部を実装することが可能になります。 現在、1つのスレッドでpythonの1つのサブスクライバーが1秒間に約7〜5000メッセージを処理していますが、PyPyから実行すると、速度は11〜15,000 /秒に増加します。







トピック内のポインターの有効期間を制限する



kafkaの設定には、リーダーが停止した場所をkafkaが「記憶」する時間を制限するパラメーターがあります-デフォルトでは2日間。 休暇中に問題が発生し、2日間解決されない場合、トピックの位置が失われないように、1週間に上げるとよいでしょう。







確認時間制限の読み取り



Kafkaリーダーが30秒以内に読み取りを確認しない場合(構成可能なパラメーター)、ブローカーは何かが間違っていると信じ、読み取りを確認しようとするとエラーが発生します。 これを回避するために、メッセージを長時間処理する場合、ポインターを移動せずに読み取り確認を送信します。







接続のグラフを理解することは困難です。



graphvizですべての関係を正直に描くと、1つのノードに数十の接続があるマイクロサービスの伝統的な黙示録のハリネズミです。 少なくとも何らかの方法(接続のグラフ)を読みやすくするために、次の表記法に同意しました:マイクロサービス-楕円、カフカの上部-長方形。 したがって、1つのグラフで、相互作用の事実とそのタイプの両方を表示できます。 しかし、残念ながら、それはそれほど良くなっていません。 したがって、この質問はまだ開かれています。













監視方法



モノリスの一部としても、ログファイルとセントリーがありましたが 、Kafkaを介して対話に切り替えてk8に展開すると、ログはElasticSearchに移動し、Elasticでサブスクライバーのログを読み取ることで最初に監視されました。 ログなし-作業なし。

その後、プロメテウスの使用を開始し、 kafka-exporterはダッシュボードをわずかに変更しました: https : //github.com/kkirsanov/articles/blob/master/2019-habr-kafka/dashboard.json







その結果、これらの写真を取得します。



どのサービスがどのメッセージの処理を停止したかを確認できます。







さらに、主要トピック(支払いトランザクション、パートナーからの通知など)からのすべてのメッセージはInfluxDBにコピーされ、同じグラフナにまとめられます。 したがって、メッセージパッシングの事実を記録できるだけでなく、コンテンツに応じてさまざまなサンプルを作成することもできます。 したがって、「サービスからの応答の平均遅延時間は何ですか」や「このストアでの昨日と今日のトランザクションフローは非常に異なりますか」などの質問に対する答えは、常に手元にあります。







また、インシデントの分析を簡素化するために、次のアプローチを使用します。各サービスは、メッセージを処理するときに、システムがタイプのレコードの配列を表示するときに発行されるUUIDを含むメタ情報で補完します。









その結果、メッセージが計算グラフを通過すると、メッセージはグラフ上を移動したパスに関する情報で強化されます。 MQのzipkin / opentracingの類似物であることがわかります。これにより、メッセージを受信して​​グラフ上のパスを簡単に復元できます。 これは、グラフでサイクルが発生する場合に特に役立ちます。 支払いのシェアがわずか0.0001%の小さなサービスの例を思い出してください。メッセージのメタ情報を分析することで、検証のためにデータベースにアクセスすることなく、支払いの開始者であるかどうかを判断できます。








All Articles