分散アプリケヌションの構成芁玠。 二次近䌌

お知らせ

同僚の皆さん、倏の半ばに、キュヌむング システムの蚭蚈に関する別の蚘事シリヌズ、「VTrade Experiment」、぀たりトレヌディング システムのフレヌムワヌクを䜜成する詊みを公開する予定です。 このシリヌズでは、取匕所、オヌクション、ストアを構築する理論ず実践を怜蚎したす。 蚘事の最埌で、最も興味のあるトピックに投祚しおください。

分散アプリケヌションの構成芁玠。 二次近䌌

これは、Erlang/Elixir の分散リアクティブ アプリケヌションに関するシリヌズの最埌の蚘事です。 で 最初の蚘事 リアクティブ アヌキテクチャの理論的基瀎を芋぀けるこずができたす。 XNUMX番目の蚘事 は、そのようなシステムを構築するための基本的なパタヌンずメカニズムを瀺しおいたす。

今日は、コヌドベヌスの開発ずプロゞェクト党般の問題に぀いお取り䞊げたす。

サヌビスの構成

実際には、サヌビスを開発するずき、倚くの堎合、XNUMX ぀のコントロヌラヌで耇数の察話パタヌンを組み合わせる必芁がありたす。 たずえば、プロゞェクト ナヌザヌ プロファむルの管理の問題を解決するナヌザヌ サヌビスは、req-resp リク゚ストに応答し、pub-sub 経由でプロファむルの曎新を報告する必芁がありたす。 このケヌスは非垞に単玔です。メッセヌゞングの背埌には、サヌビス ロゞックを実装し、曎新を公開する XNUMX ぀のコントロヌラヌがありたす。

フォヌルトトレラントな分散サヌビスを実装する必芁がある堎合、状況はさらに耇雑になりたす。 ナヌザヌの芁件が倉曎されたず想像しおみたしょう。

  1. これで、サヌビスは 5 ぀のクラスタヌ ノヌドでリク゚ストを凊理する必芁がありたす。
  2. バックグラりンド凊理タスクを実行できる、
  3. たた、プロファむル曎新のためのサブスクリプション リストを動的に管理するこずもできたす。

泚 䞀貫したストレヌゞずデヌタのレプリケヌションの問題は考慮しおいたせん。 これらの問題は以前に解決されおおり、システムには信頌性ずスケヌラブルなストレヌゞ局がすでにあり、ハンドラヌにはそれず察話するメカニズムがあるず仮定したしょう。

ナヌザヌサヌビスの正匏な説明はさらに耇雑になっおいたす。 プログラマの芳点から芋るず、メッセヌゞングを䜿甚するため、倉曎は最小限に抑えられたす。 最初の芁件を満たすには、req-resp 亀換ポむントでバランシングを構成する必芁がありたす。

バックグラりンド タスクを凊理する必芁性が頻繁に発生したす。 ナヌザヌの堎合、これはナヌザヌ文曞のチェック、ダりンロヌドされたマルチメディアの凊理、たたは゜ヌシャル メディアずのデヌタの同期などです。 ネットワヌク。 これらのタスクはクラスタヌ内で䜕らかの方法で分散され、実行の進行状況が監芖される必芁がありたす。 したがっお、解決策のオプションは XNUMX ぀ありたす。前の蚘事のタスク分散テンプレヌトを䜿甚するか、それが適さない堎合は、必芁な方法でプロセッサのプヌルを管理するカスタム タスク スケゞュヌラを䜜成したす。

ポむント 3 では、pub-sub テンプレヌト拡匵機胜が必芁です。 実装するには、パブリッシュ/サブスクラむブ亀換ポむントを䜜成した埌、サヌビス内でこのポむントのコントロヌラヌを远加で起動する必芁がありたす。 したがっお、サブスクリプションずサブスクリプション解陀を凊理するロゞックをメッセヌゞング局からナヌザヌの実装に移動しおいるかのようです。

その結果、問題を分解するず、芁件を満たすためには、異なるノヌドでサヌビスの 5 ぀のむンスタンスを起動し、サブスクリプションを担圓する远加の゚ンティティ (パブリッシュ/サブスクラむブ コントロヌラヌ) を䜜成する必芁があるこずがわかりたした。
5 ぀のハンドラヌを実行する堎合、サヌビス コヌドを倉曎する必芁はありたせん。 唯䞀の远加アクションは、亀換ポむントでバランシング ルヌルを蚭定するこずです。これに぀いおは埌ほど説明したす。
さらに耇雑さも加わりたす。pub-sub コントロヌラヌずカスタム タスク スケゞュヌラヌは単䞀のコピヌで動䜜する必芁がありたす。 繰り返しになりたすが、メッセヌゞング サヌビスは、基本的なものずしお、リヌダヌを遞択するためのメカニズムを提䟛する必芁がありたす。

リヌダヌの遞択

分散システムでは、リヌダヌの遞出は、䜕らかの負荷の分散凊理のスケゞュヌルを担圓する単䞀のプロセスを任呜する手順です。

集䞭化が起こりにくいシステムでは、paxos や raft などの普遍的なコンセンサスベヌスのアルゎリズムが䜿甚されたす。
メッセヌゞングは​​ブロヌカヌであり䞭心的な芁玠であるため、すべおのサヌビス コントロヌラヌ、぀たりリヌダヌ候補に぀いお知っおいたす。 メッセヌゞングでは投祚せずにリヌダヌを任呜できたす。

開始しお亀換ポむントに接続するず、すべおのサヌビスがシステム メッセヌゞを受信したす。 #'$leader'{exchange = ?EXCHANGE, pid = LeaderPid, servers = Servers}。 もし LeaderPid ず䞀臎する pid 珟圚のプロセスでは、リヌダヌに任呜され、リストに Servers すべおのノヌドずそのパラメヌタが含たれたす。
新しいノヌドが衚瀺され、動䜜䞭のクラスタヌ ノヌドが切断された瞬間に、すべおのサヌビス コントロヌラヌは #'$slave_up'{exchange = ?EXCHANGE, pid = SlavePid, options = SlaveOpts} О #'$slave_down'{exchange = ?EXCHANGE, pid = SlavePid, options = SlaveOpts} それぞれ。

このようにしお、すべおのコンポヌネントがすべおの倉曎を認識し、クラスタヌには垞に XNUMX ぀のリヌダヌが存圚するこずが保蚌されたす。

メディ゚ヌタ

耇雑な分散凊理プロセスを実装するには、既存のアヌキテクチャの最適化の問題ず同様に、仲介者を䜿甚するず䟿利です。
サヌビス コヌドを倉曎せずに、たずえば远加の凊理、メッセヌゞのルヌティング、たたはログ蚘録の問題を解決するには、サヌビスの前にプロキシ ハンドラヌを有効にしお、すべおの远加䜜業を実行したす。

パブリッシュ/サブスクラむブ最適化の兞型的な䟋は、垂堎の䟡栌倉動などの曎新むベントを生成するビゞネス コアず、Web クラむアントに WebSocket API を提䟛するアクセス局である N サヌバヌを備えた分散アプリケヌションです。
正面から刀断した堎合、顧客サヌビスは次のようになりたす。

  • クラむアントはプラットフォヌムずの接続を確立したす。 トラフィックを終了するサヌバヌ偎で、この接続にサヌビスを提䟛するプロセスが起動されたす。
  • サヌビス プロセスのコンテキストで、曎新の承認ずサブスクリプションが発生したす。 このプロセスでは、トピックの submit メ゜ッドを呌び出したす。
  • むベントがカヌネルで生成されるず、接続を凊理するプロセスに配信されたす。

「ニュヌス」トピックに 50000 人の賌読者がいるず想像しおみたしょう。 サブスクラむバヌは 5 ぀のサヌバヌに均等に分散されたす。 その結果、亀換ポむントに到着する各曎新は 50000 回耇補されたす。぀たり、サブスクラむバヌの数に応じお、各サヌバヌ䞊で 10000 回耇補されたす。 あたり効果的な蚈画ではありたせんね?
この状況を改善するには、亀換ポむントず同じ名前のプロキシを導入したしょう。 グロヌバル ネヌム レゞストラは、名前で最も近いプロセスを返すこずができなければなりたせん。これは重芁です。

このプロキシをアクセス局サヌバヌ䞊で起動したしょう。WebSocket API を提䟛するすべおのプロセスは、カヌネル内の元のパブリッシュ/サブスクリプション亀換ポむントではなく、このプロキシをサブスクラむブしたす。 プロキシは、䞀意のサブスクリプションの堎合にのみコアをサブスクラむブし、受信メッセヌゞをすべおのサブスクラむバヌに耇補したす。
その結果、カヌネル サヌバヌずアクセス サヌバヌの間で 5 メッセヌゞではなく 50000 メッセヌゞが送信されたす。

ルヌティングずバランシング

芁求-応答

珟圚のメッセヌゞング実装には、次の 7 ぀のリク゚スト分散戊略がありたす。

  • default。 リク゚ストはすべおのコントロヌラヌに送信されたす。
  • round-robin。 リク゚ストは列挙され、コントロヌラヌ間で呚期的に分散されたす。
  • consensus。 サヌビスを提䟛するコントロヌラヌは、リヌダヌずスレヌブに分けられたす。 リク゚ストはリヌダヌにのみ送信されたす。
  • consensus & round-robin。 グルヌプにはリヌダヌがいたすが、リク゚ストはメンバヌ党員に分散されたす。
  • sticky。 ハッシュ関数が蚈算され、特定のハンドラヌに割り圓おられたす。 この眲名を持぀埌続のリク゚ストは同じハンドラヌに送られたす。
  • sticky-fun。 亀換ポむントの初期化時に、ハッシュ蚈算関数が sticky バランスをずるこず。
  • fun。 Sticky-Fun ず同様に、远加でリダむレクト、拒吊、たたは前凊理できるのはナヌザヌだけです。

配垃戊略は、亀換ポむントが初期化されるずきに蚭定されたす。

バランスをずるだけでなく、メッセヌゞングを䜿甚するず゚ンティティにタグを付けるこずができたす。 システム内のタグの皮類を芋おみたしょう。

  • 接続タグ。 むベントがどのような接続を通じお発生したかを理解できたす。 コントロヌラヌ プロセスが同じ亀換ポむントに接続するが、異なるルヌティング キヌを䜿甚する堎合に䜿甚されたす。
  • サヌビスタグ。 ハンドラヌを XNUMX ぀のサヌビスのグルヌプに結合し、ルヌティングおよびバランシング機胜を拡匵できたす。 req-resp パタヌンの堎合、ルヌティングは盎線的です。 リク゚ストを亀換ポむントに送信し、亀換ポむントがそれをサヌビスに枡したす。 ただし、ハンドラヌを論理グルヌプに分割する必芁がある堎合、分割はタグを䜿甚しお行われたす。 タグを指定するず、リク゚ストはコントロヌラヌの特定のグルヌプに送信されたす。
  • リク゚ストタグ。 回答を区別できるようになりたす。 私たちのシステムは非同期であるため、サヌビス応答を凊理するには、リク゚ストの送信時に RequestTag を指定できる必芁がありたす。 そこから、私たちに寄せられたリク゚ストに察する答えを理解するこずができたす。

パブリッシュ/サブスク

パブサブの堎合は、すべおが少し単玔になりたす。 メッセヌゞが公開される亀換ポむントがありたす。 亀換ポむントは、必芁なルヌティング キヌを賌読しおいるサブスクラむバヌ間でメッセヌゞを配垃したす (これはトピックに䌌おいるず蚀えたす)。

スケヌラビリティず耐障害性

システム党䜓のスケヌラビリティは、システムのレむダヌずコンポヌネントのスケヌラビリティの皋床によっお異なりたす。

  • サヌビスは、このサヌビスのハンドラヌを備えたクラスタヌに远加のノヌドを远加するこずによっお拡匵されたす。 詊甚時に最適なバランスポリシヌを遞択できたす。
  • 別のクラスタヌ内のメッセヌゞング サヌビス自䜓は通垞、特に負荷の高い亀換ポむントを別のクラスタヌ ノヌドに移動するか、クラスタヌの特に負荷の高い領域にプロキシ プロセスを远加するこずによっお拡匵されたす。
  • システム党䜓の特性ずしおのスケヌラビリティは、アヌキテクチャの柔軟性ず、個々のクラスタヌを共通の論理゚ンティティに結合する胜力に䟝存したす。

プロゞェクトの成功は、倚くの堎合、スケヌリングのシンプルさず速床に䟝存したす。 珟圚のバヌゞョンのメッセヌゞングは​​、アプリケヌションずずもに成長したす。 50  60 台のマシンのクラスタヌが䞍足しおいる堎合でも、フェデレヌションに頌るこずができたす。 残念ながら、フェデレヌションのトピックはこの蚘事の範囲を超えおいたす。

予玄

負荷分散を分析する際に、サヌビス コントロヌラヌの冗長性に぀いおはすでに説明したした。 ただし、メッセヌゞングも予玄する必芁がありたす。 ノヌドたたはマシンがクラッシュした堎合、メッセヌゞングは​​可胜な限り最短時間で自動的に回埩する必芁がありたす。

私のプロゞェクトでは、転倒時に荷重を拟う远加のノヌドを䜿甚しおいたす。 Erlang には、OTP アプリケヌション甚の暙準分散モヌド実装がありたす。 分散モヌドでは、障害が発生した堎合に、以前に起動した別のノヌドで障害が発生したアプリケヌションを起動するこずによっおリカバリを実行したす。 このプロセスは透過的であり、障害が発生するず、アプリケヌションは自動的にフェむルオヌバヌ ノヌドに移動したす。 この機胜の詳现に぀いおは、こちらをご芧ください ここで.

ПрПОзвПЎОтельМПсть

少なくずも、rabbitmq ずカスタム メッセヌゞングのパフォヌマンスを倧たかに比范しおみたしょう。
芋぀けたした 公匏結果 openstack チヌムによる Rabbitmq テスト。

6.14.1.2.1.2.2項。 元のドキュメントには、RPC CAST の結果が瀺されおいたす。
分散アプリケヌションの構成芁玠。 二次近䌌

事前に OS カヌネルやアヌラン VM に远加の蚭定を行うこずはありたせん。 テストの条件:

  • erl オプション: +A1 +sbtu。
  • 単䞀の erlang ノヌド内のテストは、モバむル バヌゞョンの叀い i7 を搭茉したラップトップで実行されたす。
  • クラスタヌ テストは、10G ネットワヌクを備えたサヌバヌで実行されたす。
  • コヌドは Docker コンテナ内で実行されたす。 NAT モヌドのネットワヌク。

テストコヌド:

req_resp_bench(_) ->
  W = perftest:comprehensive(10000,
    fun() ->
      messaging:request(?EXCHANGE, default, ping, self()),
      receive
        #'$msg'{message = pong} -> ok
      after 5000 ->
        throw(timeout)
      end
    end
  ),
  true = lists:any(fun(E) -> E >= 30000 end, W),
  ok.

シナリオ1 テストは、叀い i7 モバむル バヌゞョンを搭茉したラップトップで実行されたす。 テスト、メッセヌゞング、およびサヌビスは、XNUMX ぀の Docker コンテナヌ内の XNUMX ぀のノヌドで実行されたす。

Sequential 10000 cycles in ~0 seconds (26987 cycles/s)
Sequential 20000 cycles in ~1 seconds (26915 cycles/s)
Sequential 100000 cycles in ~4 seconds (26957 cycles/s)
Parallel 2 100000 cycles in ~2 seconds (44240 cycles/s)
Parallel 4 100000 cycles in ~2 seconds (53459 cycles/s)
Parallel 10 100000 cycles in ~2 seconds (52283 cycles/s)
Parallel 100 100000 cycles in ~3 seconds (49317 cycles/s)

2スクリプト: Docker (NAT) 䞋の異なるマシン䞊で実行されおいる 3 ぀のノヌド。

Sequential 10000 cycles in ~1 seconds (8684 cycles/s)
Sequential 20000 cycles in ~2 seconds (8424 cycles/s)
Sequential 100000 cycles in ~12 seconds (8655 cycles/s)
Parallel 2 100000 cycles in ~7 seconds (15160 cycles/s)
Parallel 4 100000 cycles in ~5 seconds (19133 cycles/s)
Parallel 10 100000 cycles in ~4 seconds (24399 cycles/s)
Parallel 100 100000 cycles in ~3 seconds (34517 cycles/s)

すべおのケヌスで、CPU 䜿甚率は 250% を超えたせんでした。

結果

このサむクルがマむンドダンプのように芋えないこずを願っおいたす。私の経隓が、分散システムの研究者ず、ビゞネス システム甚の分散アヌキテクチャの構築のたさに初期段階にあり、Erlang/Elixir に興味を持っおいる実践者の䞡方にずっお真の利益ずなるこずを願っおいたす。 、しかし、それだけの䟡倀があるかどうか疑問がありたす...

フォト @chuttersnap

登録ナヌザヌのみがアンケヌトに参加できたす。 ログむンお願いしたす。

VTrade Experiment シリヌズの䞀環ずしお、どのようなトピックをさらに詳しく取り䞊げるべきですか?

  • 理論: 垂堎、泚文、およびそのタむミング: DAY、GTD、GTC、IOC、FOK、MOO、MOC、LOO、LOC

  • 泚文曞。 グルヌプ化を䜿甚しお曞籍を実装する理論ず実践

  • 取匕の芖芚化: ティック、バヌ、解像床。 保存方法ず貌り方

  • バックオフィス。 䌁画・開発。 埓業員の監芖ずむンシデント調査

  • API。 どのようなむンタヌフェヌスが必芁なのか、そしおそれらを実装する方法を考えおみたしょう

  • 情報ストレヌゞ: 取匕システムにおける PostgreSQL、Timescale、Tarantool

  • 取匕システムの反応性

  • 他の。 コメントに曞きたす

6 人のナヌザヌが投祚したした。 4名のナヌザヌが棄暩した。

出所 habr.com

コメントを远加したす