16

SignalRを使用して、ASP.NET MVC 3アプリケーション(フォーム認証を使用)、SQL Server 2008データベース、およびデータを処理するMSMQ WCFサービス(WASでホストされている)で構成される.NET4.0システムに通知を実装するにはどうすればよいでしょうか。ランタイム環境は、Windows Server 2008 R2StandardEditionで実行されているIIS7.5で構成されています。

私はサンプルで遊んだだけで、SignalRについての幅広い知識はありません。

ここにいくつかの背景があります

Webアプリケーションは、ユーザーからのデータを受け取り、それをテーブルに追加します。次に、WCFサービスの一方向操作(データベースキーを使用)を呼び出して、データ(タスク)を処理します。Webアプリケーションは、データが送信されたことをユーザーに通知するページに戻り、処理が完了すると通知されます。ユーザーは「インデックス」ページを見て、どのタスクが完了したか、失敗したか、または進行中であるかを確認できます。彼らはさらに多くのタスクを提出し続けることができます(これは以前のデータとは無関係です)。ブラウザを閉じて、後で戻ることができます。

MSMQベースのWCFサービスは、データベースからレコードを読み取り、データを処理します。これには、ミリ秒から数分かかる場合があります。データの処理が完了すると、レコードは対応するステータス(エラーまたは失敗)と結果で更新されます。

ほとんどの場合、WCFサービスは処理を実行していませんが、実行する場合、ユーザーは通常、処理がいつ実行されるかをできるだけ早く知りたいと考えています。ユーザーは、WCFサービスで処理するデータがない場合でも、Webアプリケーションの他の部分を引き続き使用します。

これは私がしたことです

プライマリナビゲーションバーには、タスクのステータスが変更されたときにユーザーに通知するためのインジケーター(FacebookやGoogle+と同様)があります。クリックすると、実行内容の概要が表示され、必要に応じて結果を表示できます。

jQueryを使用して、サーバーをポーリングして変更を確認します。コントローラのアクションは、変更された(完了または失敗した)プロセスがあるかどうかを確認し、それ以外の場合は数秒待ってから、クライアントに戻らずに再度確認します。クライアントでのタイムアウトを回避するために、変更がない場合は30秒後に戻ります。jQueryスクリプトはしばらく待機してから、再試行します。

問題点

ページを表示するすべてのユーザーでパフォーマンスが低下します。特に何もする必要はありません。Firefox7以降とSafariのメモリ使用量が時間の経過とともに増加することに気づきました。

SignalRの使用

SignalRに切り替えることで、ポーリングが削減され、データベースでタスクごとに何も変更されていない場合は特に、リソース要件が削減されることを期待しています。フォームベースの認証を使用しているため、WCFサービスがタスクの処理が完了したことをクライアントに通知するのに問題があります。

この質問をすることで、SignalRを使用して通知スキームを再設計する方法について、誰かが私にもっと良い洞察を与えてくれることを願っています。

4

1 に答える 1

8

私が正しく理解している場合は、タスクを特定のユーザー/クライアントに関連付けて、タスクが完了したときにクライアントに通知できるようにする方法が必要です。

SignalR APIのドキュメントには、クライアントID( https://github.com/SignalR/SignalR/wiki/SignalR-Client )に基づいて特定のクライアントのJSメソッドを呼び出すことができると記載されています。理論的には、次のようなことができます。

  1. SignalRが使用するクライアントIDをタスクメタデータの一部として保存します。
  2. 通常どおりタスクをキューに入れます。
  3. タスクが処理され、キューから取り出されると、次のようになります。
    • ステータスでデータベースを更新します。
    • そのタスクの一部として保存されているクライアントIDを使用して、SignalRを使用してそのクライアントに通知を送信します。

クライアントが使用している接続を取得して、メッセージを送信できるはずです。

string clientId = processedMessage.ClientId //Stored when you originally queued it.
IConnection connection = Connection.GetConnection<ProcessNotificationsConnection>();
connection.Send(clientId, "Your data was processed");

これは、この接続をマップし、クライアントが最初にその接続を使用してデータ処理要求を開始したことを前提としています。「プライマリナビゲーションバー」には、ProcessNotificationsConnection前にマッピングしたエンドポイントへの接続を開始したJSがあります。

編集:https ://github.com/SignalR/SignalR/wiki/Hubsから

public class MyHub : Hub
{
     public void Send(string data)
     {
     // Invoke a method on the calling client
     Caller.addMessage(data);

     // Similar to above, the more verbose way
     Clients[Context.ClientId].addMessage(data);

     // Invoke addMessage on all clients in group foo
     Clients["foo"].addMessage(data);
     }
}
于 2011-11-21T15:56:42.437 に答える