Node.jsおよびRedisでの保留中のユーザー通知

タスクの説明


多くの場合、モバイルプラットフォームの開発者と同様に、Webアプリケーション開発者は、イベントの完了の通知を送信するタスクを持っています。 例:スケジュールされた会議、電話、特定のスケジュールエントリ(todoシート)のユーザーへの通知、または将来の他のアクションのリマインダーの作成。





同様のアプリケーションがソーシャルにある場合。 ネットワーク、そして直接送信通知のために、VKontakteネットワークはこれのためにsecure.sendNotificationメソッドを提供します。

クラスメートの場合: notification.sendSimple ;

AppleおよびAndroidデバイスの場合、そのような通知はそれぞれApple Push Notification ServiceおよびAndroid Cloud to Device Messaging(C2DM)を介して送信できます。



解決するツールの選択


この問題を解決するために、2つの固定資産が選択されました。

Node.js (0.6.x)およびRedis Plus Expressは 、テスト用の受信および送信された通知とVowsの統計を表示するプリミティブUIを実装します。



最初は、Node.jsバージョン0.4クラスターが個別のクラスターパッケージとして作成されるため、 クラスターモジュール(0.6に含まれる)を介してすべてのコアを簡単に使用する機能が含まれていました。



Redisは、すぐに使用できるさまざまなデータ型をサポートするために選択されました(同じMemcacheと比較)。 作業キューを整理するための便利なコマンドも用意されています。 また、 Youporn.comは100%Redisサイトになったため



コアAPI


server_name / send_delayed-遅延通知(GETおよびPOSTパラメーターの両方を受け入れます)





server_name / user_online-特定のユーザーのイベントを取得し(時間が来た場合)、送信します





アプリの設計

キューイングの主な構造:

メッセージキュー -ランクがイベントの時間になるSORTEDSET。

オンラインメッセージのキュー -各uidのSORTEDSETは個別です。このランクはイベントの時間です。

処理用キュー -LIST-このメッセージがこのリストにある場合、メッセージは処理されます。



マスタープロセス


1.サーバー上のコアの数に等しい数個のワーカーを起動します。

2. REPLが開始されます。

3. メッセージキュースキャナーを起動しますオンラインメッセージキューはスキャンされません)。

4.労働者の転倒を監視し、転倒した場合は再起動します。

5.完全に落下した場合、個々のイベントからメッセージキューを復元します。

6. UIサーバーを起動して、統計を追跡します。



スキャナーは、ZREVRANGEBYSCOREを介して、現在時刻と逆の順序で100に等しい量のイベントのパケットをメッセージキューから受信します 。 トランザクションでは、 処理のためにそれらを処理キューに入れ、 メッセージキューから削除します



別の労働者


1. send_delayedまたはuser_onlineコマンドを受け入れます。 これらのイベントは、JSON.stringifyを介してjson形式でHASHに記録されます。 msgpackのイベントストレージも試行されました。 上記のテストによると、より高速にすべきであると書かれていますが、単純なオブジェクトの場合、速度の向上はありませんでした。 イベントIDは、ランダムなハウスによって作成され、 メッセージキューに入れられます 。 イベントの各キーについて、応答時間+設定からの遅延に等しいライフタイムが設定されます。



2. 処理のためにキュースキャナー起動します

スキャナーは、BLPOPを介してLISTからイベントを受信します(キューにある場合にのみ取得するため)。 サーバーを実行したまま./redis-cliでMONITORコマンドを実行すると、ログは次のようになります。



1336484301.674405 "zrevrangebyscore" "actual_queue_test-queue" "1336484301673" "-inf" "limit" "0" "100"

1336484301.675102 "zrevrangebyscore" "actual_queue_test-queue" "1336484301674" "-inf" "limit" "0" "100"

1336484301.675387 "zrevrangebyscore" "actual_queue_test-queue" "1336484301675" "-inf" "limit" "0" "100"








// fill processing queue

Worker.prototype.fetch = function(fn) {

var self = this;

this.client.zrevrangebyscore(this.queue_key, Date.now(),

"-inf", "limit", 0, self.pack, function(err, reply) {

process.nextTick(function() {

self.fetch();

}); // re-schedule fetch

...








この場合、次のティックでフェッチを実行するたびに。 ご覧のとおり、キューにイベントがない場合、ティックごとにチェックする意味がありません。

JSON.parseは、 最後の送信のキーが存在しない場合、または(現在の時間-キー> USER_POLL_THRESHOLD-30分)-recheck_urlがあるかどうかを確認した後、UrlSenderがhttp要求を送信するイベントデータイベントをトリガーします。 httpリクエストで200コードを受信した場合、イベント「event-sent」を開始し、データベース内のイベントを消去し、現在の時刻までにユーザーの最後の送信のキーを設定します



オンラインイベントを処理する順序は次のとおりです:特定のユーザーのオンラインメッセージのキューを受信するZREVRANGEBYSCOREを介して、彼は最も近いイベントを受信します。 USET_POLL_THRESHOLD_ONLINEを設定することで、送信のタイミングが来たかどうかを確認し、 処理のために処理キューに入れて、 メッセージキューから削除します



テスト中


自動テストは、vowsフレームワークを使用して作成されます。 テストの主なアイデアは、特別なロガーメソッドを使用してRedis LISTにイベントのシーケンスを記録し、それをイベントの参照シーケンスと比較することです。



logger.spec('event-processed'); //only test env



logger.spec('event-fetched'); //only test env








テストの実行:

1. config / settings.test.js-> config / settings.jsをコピーして、独自の設定に変更します。

2.サーバーの起動:APP_ENV = npm startのテスト

3.テストの実行:APP_ENV = test vows --spec test / delay-request-test.js



テストスクリプトの例(ルビー)


require 'uri'

require 'net/http'



api_url = "http://127.0.0.1:8000/send_delayed"

url = "http://127.0.0.1:8000/health"

recheck_url = "http://127.0.0.1:8000/recheck_url_correct"

# recheck_url = "http://127.0.0.1:8000/recheck_url_error"

uid=rand(1000)

type="test_common"

delay=1

post_url = URI.parse(api_url)

# res = Net::HTTP.post_form(post_url,{"url" => url, "delay" => delay,

# "uid" => uid, "type" => type, "recheck_url" => recheck_url, "send_than_online" => true})

res = Net::HTTP.post_form(post_url,{"url" => url, "delay" => delay,

"uid" => uid, "type" => type, "recheck_url" => recheck_url})

p res.inspect








統計ビューのインターフェースの例






サーバーのソースコード


ピンキーによる共同執筆

https://github.com/catz/actual_queue




All Articles