web-dev-qa-db-ja.com

ソケットを「高速レーン」として使用することにより、ブラウザでのリクエストの輻輳を解決します。

1〜2年前に公開したWebベースのGISアプリケーションのユーザーから、アプリケーションが不安定になったり応答しなくなったりするという苦情が何度も寄せられています。簡単な調査の結果、サードパーティのMap APIからのリクエストが、ブラウザの利用可能な接続のほとんどを占めることがわかりました(動的レイヤーをプルすると、画像です)、また、ユーザー数が多いため(計画どおり1xx対1x)、これらのリクエストの処理時間が長くなったため、独自のAPIからのリクエストは無料の接続を待機し、最終的にタイムアウトする必要がありました。このような状況の概要は次のようになります。 :

requests from the Map API (busy) | requests from our own API to get data from DB to display (waiting) | requests from our own API to post data to DB (waiting)

** A FEW MOMENTS LATER **

requests from the Map API (still working...) | requests from our own API to get data from DB to display (timeout) | requests from our own API to post data to DB (timeout)

私が達成したいのは、Map APIからのリクエストの前にDBからデータを取得するために、独自のAPIからのリクエストを移動することですが、Map APIに、独自のAPIからの(より重要な)リクエストを待機するように指示する方法はありません。マップを更新する前に。私は遭遇しました この質問 そして解決策を提案することを計画しました:Map APIを初期化する前にソケットを開くと、データを取得するための独自のAPIからのリクエストはajaxを使用する代わりにそれを通過します。私は疑問に思う...

また、ソケットを使用してデータをDBにPOSTするために、独自のAPIからリクエストを行う必要がありますか?リライトAPIはAjax to Socketで動作するので時間がかかるため、ユーザーはデータと更新されたマップを取得した後で更新を投稿する必要があります。

また、ソケットを介して独自のAPIからすべてのリクエストを行うと、リクエストの輻輳がAjaxからソケットに移動するようです。

2
Incognitoo

簡単な答えは接続プーリングです。 AJAXリクエストの送信に使用されるXMLHttpRequestオブジェクトのプールを用意し、どのリクエストが使用中で、どれがフリーであるかを追跡する必要があります。コードがリクエストを送信する必要があるので、無料接続。

しかし、これはJavaScriptです。

そして、関係するサードパーティのライブラリがあります。

長い答えは「短い答え」と少しのChicken Voodoo Magic™です。

サードパーティのコードは、_new XMLHttpRequest_オブジェクトを直接インスタンス化するか、XMLHttpRequestを使用するjQuery — $.ajax(...) —のようなさらに別のライブラリを経由して、AJAXリクエストを送信する可能性があります。ありがたいことに、共通の要素はウィンドウオブジェクトのメンバーであるXMLHttpRequestクラスです。

  1. 接続をプールするためのクラスを作成する

  2. プールから無料のXMLHttpRequestオブジェクトを非同期的に取得するのと同じパブリックインターフェイス(プロパティを含む)を使用して、XMLHttpRequestのプロキシクラスを記述します

  3. 接続プールライブラリ全体をラップする関数クロージャ内のローカル変数に_window.XMLHttpRequest_を割り当てます

  4. XMLHttpRequestのプロキシクラスを_window.XMLHttpRequest_に割り当てます

  5. 他のすべてのスクリプトの前にこのスクリプトを含めます

これで、コードが実行されるとnew XMLHttpRequest()が取得されます。これは、内部接続プールに委任するXMLHttpRequestProxyオブジェクトです。 サードパーティのライブラリでもこれを使用します。XMLHttpRequestProxyクラスは実際のXMLHttpRequestクラスと同じパブリックインターフェイスを持っているため、サードパーティのライブラリは認識しません。違い。

JavaScriptファイルの基本的なスタブは次のようになります。

_(function (window) {
    var RawXMLHttpRequest = window.XMLHttpRequest;

    var requestPool = {
        // whatever you need to manage a pool of RawXMLHttpRequest objects

        getConnection: function () {
            // return a Promise
        }
    };

    function XMLHttpRequestProxy() {
        // Same properties and methods as real XMLHttpRequest

        var _xhr = null;

        function getConnection() {
            if (_xhr === null) {
                requestPool.getConnection()
                    .then(function (xhr) {
                        _xhr = xhr;

                        // return Promise, pass _xhr
                    });
            }

            // return Promise, pass _xhr
        }

        this.send = function(requestBody) {
            getConnection()
                .then(function (xhr) {
                    xhr.send(requestBody);
                });
        };
    }

    window.XMLHttpRequest = XMLHttpRequestProxy;
})(this);
_

次のリンクのコードは特定の問題の解決策ではありませんが、この種のパターンを示しています: MockingBird.XMLHttpRequestInterceptor(global)

Onreadystatechangeハンドラーが適切に呼び出されるようにするには、まだジャグリングが必要です。したがって、XMLHttpRequestProxyクラスは、AJAXオブジェクトが使用中または解放されたときに、プールに適切に通知しますが、基本的なテンプレートある。

2
Greg Burghardt