簡単に言えば、新しいデータだけがネットワーク経由で送信されるということです。これがどのように機能するかです。
Meteorサーバーには、サブスクリプションを管理する3つの重要な部分があります。サブスクリプションが提供するデータのロジックを定義するpublish関数。Mongoのドライバの変更のためにデータベースを監視; そして、マージボックスクライアントのアクティブなサブスクリプションのすべてを組み合わせて、クライアントにネットワークを介してそれらを送信し、。
公開機能
Meteorクライアントがコレクションをサブスクライブするたびに、サーバーはパブリッシュ関数を実行
します。公開機能の仕事は、クライアントが持つべきドキュメントのセットを見つけ出し、各ドキュメントプロパティをマージボックスに送信することです。新しいサブスクライブクライアントごとに1回実行されます。を使用した任意の複雑なアクセス制御など、必要なJavaScriptをpublish関数に配置できますthis.userId
。publish関数はthis.added
、this.changed
およびを
呼び出して、データをマージボックスに送信しますthis.removed
。詳細については、
完全な公開ドキュメントを参照してください。
パブリッシュほとんどの関数は、低レベルの周りマックする必要はありません
added
、changed
とremoved
ただし API。パブリッシュ機能はMongoのカーソルを返す場合、流星サーバは自動的にMongoのドライバ(の出力接続insert
、update
およびremoved
マージボックスの入力にコールバック)( this.added
、this.changed
およびthis.removed
)。パブリッシュ関数ですべての権限チェックを事前に実行し、ユーザーコードなしでデータベースドライバーをマージボックスに直接接続できることは非常に便利です。そして、自動公開がオンになっていると、この少しでも非表示になります。サーバーは、各コレクションのすべてのドキュメントに対するクエリを自動的に設定し、それらをマージボックスにプッシュします。
一方、データベースクエリの公開に限定されません。たとえば、内のデバイスからGPS位置を読み取るMeteor.setInterval
、または別のWebサービスからレガシーREST APIをポーリングする発行関数を作成できます。これらのケースでは、低レベルを呼び出すことで、マージボックスへの変更を放出するだろうadded
、changed
とremoved
DDP API。
モンゴドライバー
Mongoのドライバーの仕事は、ライブのクエリへの変更のためにモンゴデータベースを監視することです。これらのクエリは継続的に実行され、呼び出しによって結果が変更されると更新を返しますadded
removed
およびchanged
コールバックを、。
Mongoはリアルタイムデータベースではありません。したがって、ドライバーは投票します。アクティブな各ライブクエリの最後のクエリ結果のメモリ内コピーを保持します。各ポーリングサイクルで、新しい結果を以前に保存した結果と比較し、added
、removed
およびchanged
差を記述するイベント。複数の呼び出し元が同じライブクエリのコールバックを登録する場合、ドライバーはクエリの1つのコピーのみを監視し、登録された各コールバックを呼び出して同じ結果を返します。
サーバーがコレクションを更新するたびに、ドライバーはそのコレクションの各ライブクエリを再計算します(Meteorの今後のバージョンでは、更新時に再計算するライブクエリを制限するためのスケーリングAPIが公開されます)。 Meteorサーバーをバイパスした帯域外データベースの更新をキャッチします。
マージボックス
仕事マージボックスが(結果を組み合わせることであるadded
、changed
とremoved
単一のデータ・ストリームにクライアントのアクティブなパブリッシュ機能のすべてのコール)。接続されているクライアントごとに1つのマージボックスがあります。クライアントのminimongoキャッシュの完全なコピーを保持します。
サブスクリプションが1つだけの例では、マージボックスは本質的にパススルーです。しかし、より複雑なアプリは、重複する可能性のある複数のサブスクリプションを持つことができます。2つのサブスクリプションの両方が同じドキュメントに同じ属性を設定した場合、マージボックスはどの値が優先されるかを決定し、それをクライアントにのみ送信します。サブスクリプションの優先度を設定するためのAPIはまだ公開していません。現時点では、優先度は、クライアントがデータセットにサブスクライブする順序によって決定されます。クライアントが行う最初のサブスクリプションの優先度が最も高く、2番目のサブスクリプションが次に高いというように続きます。
マージボックスはクライアントの状態を保持するため、パブリッシュ関数がフィードする内容に関係なく、最小量のデータを送信して各クライアントを最新の状態に保つことができます。
アップデートで何が起こるか
これで、シナリオの準備が整いました。
1,000のクライアントが接続されています。それぞれが同じライブMongoクエリ(Somestuff.find({})
)にサブスクライブされています。クエリは各クライアントで同じであるため、ドライバーは1つのライブクエリのみを実行します。1,000個のアクティブなマージボックスがあります。そして、各クライアントの機能を公開し、登録added
、changed
および
removed
フィードマージボックスのいずれかにすることをそのライブのクエリに。他には何も結合ボックスに接続されていません。
まずモンゴドライバー。クライアントの1つが新しいドキュメントをに挿入するSomestuff
と、再計算がトリガーされます。Mongoドライバーは、内のすべてのドキュメントのクエリを再実行Somestuff
し、結果をメモリ内の以前の結果と比較して、1つの新しいドキュメントがあることを検出し、登録されている1,000個のinsert
コールバックのそれぞれを呼び出します。
次に、公開機能。ここではほとんど何も起こりません。1,000のinsert
コールバックのそれぞれがを呼び出してデータをマージボックスにプッシュしますadded
。
最後に、各マージボックスは、クライアントのキャッシュのメモリ内コピーに対してこれらの新しい属性をチェックします。どちらの場合も、値がクライアントにまだないこと、既存の値をシャドウしないことがわかります。そのため、マージボックスはDATA
SockJS接続でDDP メッセージをクライアントに送信し、サーバー側のメモリ内コピーを更新します。
合計CPUコストは、1つのMongoクエリを比較するためのコストに、クライアントの状態をチェックして新しいDDPメッセージペイロードを構築する1,000のマージボックスのコストを足したものです。ネットワーク上を流れる唯一のデータは、データベース内の新しいドキュメントに対応する1,000個のクライアントのそれぞれに送信される単一のJSONオブジェクトと、元の挿入を行ったクライアントからサーバーへの 1つのRPCメッセージです。
最適化
これが私たちが間違いなく計画したことです。
より効率的なMongoドライバー。
0.5.1でドライバーを
最適化して、個別のクエリごとに1つのオブザーバーのみを実行しました。
すべてのDBの変更がクエリの再計算をトリガーする必要はありません。いくつかの自動化された改善を行うことができますが、最善のアプローチは、再実行する必要があるクエリを開発者が指定できるAPIです。たとえば、1つのチャットルームにメッセージを挿入しても、2番目のルームのメッセージに対するライブクエリが無効にならないことは開発者にとって明らかです。
Mongoドライバー、パブリッシュ関数、マージボックスは、同じプロセスで実行する必要はなく、同じマシンで実行する必要もありません。一部のアプリケーションは複雑なライブクエリを実行し、データベースを監視するためにより多くのCPUを必要とします。他のユーザーは、わずかなクエリしか持っていません(ブログエンジンを想像してください)が、おそらく多くの接続されたクライアントがあります。これらは、マージボックスのためにより多くのCPUを必要とします。これらのコンポーネントを分離すると、各部分を個別にスケーリングできます。
多くのデータベースは、行が更新されたときに起動し、古い行と新しい行を提供するトリガーをサポートしています。その機能により、データベースドライバーは変更をポーリングする代わりにトリガーを登録できます。