4

私は、自分のプロジェクトで使用する単純なロング ポーリング サービスを実装しようとしてきました。成功すれば、SAAS としてリリースするかもしれません。これらは私がこれまでに試した 2 つのアプローチで、どちらも Node.js を使用しています (バックグラウンドで PostgreSQL をポーリングしています)。

1. すべてのクライアントを同じ間隔で定期的にチェックする

すべての新しい接続は、接続のキューにプッシュされます。これは、一定の間隔でウォークスルーされます。

var queue = [];

function acceptConnection(req, res) {
  res.setTimeout(5000);
  queue.push({ req: req, res: res });
}

function checkAll() {
  queue.forEach(function(client) {
    // respond if there is something new for the client
  });
}

// this could be replaced with a timeout after all the clients are served
setInterval(checkAll, 500);

2. 各クライアントを別々の間隔でチェックする

すべてのクライアントは、ticker新しいデータをチェックする独自のものを取得します

function acceptConnection(req, res) {
  // something which periodically checks data for the client
  // and responds if there is anything new
  new Ticker(req, res);
}

これにより、各クライアントの最小レイテンシが低く保たれますが、多くのタイムアウトを設定することでオーバーヘッドも発生します。

結論

これらのアプローチは両方とも問題を非常に簡単に解決しますが、特にすべてのクライアントのすべてのチェックでデータベースをポーリングしているため、1,000 万のオープン接続などに簡単にスケールアップできるとは思いません。

データベースなしでこれを行うことを考え、開いているすべての接続に新しいメッセージをすぐにブロードキャストしましたが、ブロードキャストが発生している間にクライアントの接続が数秒間切断された場合、それは永続的ではないため失敗します。つまり、基本的に、クライアントが初めてポーリングするときに、履歴でメッセージを検索できる必要があります。

ここでの 1 つのステップは、入ってくる新しいデータ (CouchDB の変更通知?) をサブスクライブできるデータ ソースを用意することだと思いますが、全体像で何かが欠けているのではないでしょうか?

スケーラビリティの高いロングポーリングを行うための通常のアプローチは何ですか? 私は特に Node.js に縛られているわけではありません。実際には、理由のある他の提案を好むでしょう。

4

2 に答える 2

0

これがあなたの質問に答えるかどうかはわかりませんが、私はPushPinのアプローチが好きです(+概念の説明)。

私はこのアイデア (リバース プロキシを使用し、リターン コード + 遅延 REST リターン リクエストを使用して通信する) は気に入っていますが、実装については懸念があります。私は問題を過小評価しているかもしれませんが、使用されているテクノロジーは少しやり過ぎのようです。まだ使用するかどうかはわかりませんが、より軽量なソリューションを好むでしょうが、そのコンセプトは驚異的だと思います.

最終的に何を使ったのか聞いてみたいです。

于 2013-05-15T09:45:04.030 に答える
-1

スケーラビリティについて言及されたので、実用的な唯一の手段は負荷テストであるため、少し理論的に説明する必要があります。したがって、私が提供できるのはアドバイスだけです。

一般的に言えば、何にでも 1 回というのはスケーラビリティに悪影響を及ぼします。特に、接続ごとに 1 回、またはリクエストごとに 1 回です。これは、アプリの一部がトラフィックの量に比例するためです。Node.js は、シングルスレッドの非同期 I/O モデルにより、接続ごとのスレッドの依存関係を取り除きました。もちろん、要求と応答のオブジェクトやソケットなど、接続ごとに何かを完全に排除することはできません。

HTTP 接続ごとにデータベース接続を開くものは避けることをお勧めします。これが接続プールの目的です。

上記の 2 つのオプションのいずれかを選択する場合、個人的には 2 番目の選択肢を選びます。これにより、各接続が分離されます。最初のオプションは、接続を介したループを使用します。これは、接続ごとの実際の実行時間を意味します。I/O が非同期であることを考えると、おそらく大したことではありませんが、接続ごとの反復と接続ごとのオブジェクトの単なる存在の間の選択を考えると、オブジェクトだけを使用することをお勧めします。そうすれば、突然 10,000 接続になったときに心配する必要がなくなります。

C10K の問題はこれについての良い参考資料のように思えますが、これは正直に言うと本当に個人的な判断です。

http://www.kegel.com/c10k.html

http://en.wikipedia.org/wiki/C10k_problem

于 2013-03-03T22:01:35.187 に答える