1

チャット クライアントとして使用されている SignalR の実装があります。問題は、クライアント側のタイマーがあり、サーバーに ping を実行して他のすべてのクライアントにユーザーのステータスを通知することです。

この例では、ハートビートと最新のアクティビティがあります。ハートビートは約 15 秒ごとにサーバーに到達し、latestactivity はユーザーの対話性を追跡します。これら 2 つの値はサーバーに渡されるため、他のすべてのクライアントは他のすべてのクライアントのステータスを通知できます。つまり、ユーザー A が 1 分以上マウスを動かしていない場合、ハートビートがサーバーに到達すると、SignalR を介して他のすべてのユーザーに、現在「離れている」ことをブロードキャストします。

とにかく、チャット アプリに接続するユーザーの数が増えると、SignalR 接続が指数関数的に増加するように見えるという問題があります。

これは怪しいと思われるクライアント js タイマーのソースですが、その理由はわかりません。

define(['jquery', 'underscore', 'backbone'],
function ($, _, Backbone) {

    var Timer = Backbone.Model.extend({
        defaults: {
            interval: 1 * 10 * 1000,
            timeout: null
        },

        initialize: function (options) {
            _.bindAll(this, 'start', 'tick', 'stop', 'tickNow');
            if (options.interval) {
                this.set('interval', options.interval);
            }
        },

        start: function () {
            var timer = setTimeout(this.tick, this.get('interval'));
            this.set('timeout', timer);
        },

        tick: function () {
            var self = this;
            self.trigger('timerexpired', this);
            self.start();
        },

        tickNow: function () {
            var self = this;
            self.stop();
            self.trigger('timerexpired', this);
            self.start();
        },

        stop: function () {
            clearTimeout(this.get('timeout'));
        }
    });

    return Timer;
});
4

3 に答える 3

2

thisstart timer メソッドでキーワードを使用していることに気付きました。this.tick実際に発火したときに、コールツーコールが文脈から外れている可能性があります。試す:

start: function () {
    var self = this;
    var timer = setTimeout(this.tick, self.get('interval'));
    this.set('timeout', timer);
},

ブラウザーでtickメソッドにブレークポイントを挿入し、正しいタイマーを参照していることを確認します。

于 2012-12-17T03:32:41.070 に答える
1

進行が必ずしも指数関数的であることはわかりませんが、線形進行は確かにその傾向があります。基本的に、ここでできることは主に 2 つあります。

  • クライアント側で長いポーリング/スロットリングを使用しますが、既に 15 秒ごとにリクエストを送信しているため、ブラウザーの制限に違反していません。
  • サーバー側では、大規模な ajax アプリケーションが必要な場合は、間違いなくロード バランサーが必要です。クラウドで Amazon の自動スケーリングを使用すると、ロード バランサーを使用するだけで役立つ可能性があります。それは安くはなく、あなたが経験する活動に正比例します.
于 2012-12-14T10:08:36.370 に答える
0

メソッドが実行されると、インスタンスではなくグローバルオブジェクトにバインドされるためthis.tick、最初のパラメータとして単純に を渡すべきではありません。setTimeouttickthiswindowTimer

また、インスタンスが既に実行されているstartときに呼び出しを行っていないことを確認する必要があります。Timer次のメソッドを次のように変更します。

    start: function () {
        var self = this;
        if (this.get('timeout') !== null) {
            throw "start must not be called when the Timer is already running";
        }
        // creating a closure ensures this is bound correctly in tick()
        var timer = setTimeout(function () {
            self.tick(); 
        }, this.get('interval'));
        this.set('timeout', timer);
    },

    tick: function () {
        this.set('timeout', null);
        this.trigger('timerexpired', this);
        this.start();
    },

    stop: function () {
        clearTimeout(this.get('timeout'));
        this.set('timeout', null);
    }

タイマーが正しく機能していることを確認する明白な方法は、console.log への呼び出しを timerexpired イベントにバインドして、イベントが予想以上にトリガーされていないことを確認することです。

同時接続数が制御不能になっている理由を判断するのに役立つ場合は、SignalR 接続を停止および開始するコードを投稿する必要があります。

于 2012-12-14T19:19:41.847 に答える