2

次のシナリオがあります。

  1. サーバー上の特定のリソースに対するユーザー リクエスト。このリクエストは長時間実行されるタスクであり、2 ~ 3 秒から 10 秒ほどかかります。ユーザーが待機したいので、ジョブチケットをユーザーに発行します。
  2. リクエストを受け取ると、そのリクエストを永続ストレージに保存し、JobTicket (GUID) としてトークンをユーザーに発行します。
  3. ユーザーはハブに接続して、その GUID に関する情報を取得します。

バックグラウンドで:

  1. その要求に対して何らかの操作を実行するために、WAS Hosted と Windows Service があります。
  2. 完了すると、WAS Hosted/Windows サービスは、ジョブが完了した Web アプリケーションを呼び出します。
  3. そこから、ジョブ チケットに基づいてどのユーザーを識別し、その接続でジョブが完了したことをユーザーに知らせます。

現在、サーバーのファームがあり、正常に動作している Windows Server On Prem ServiceBus 1.1 を使用していますが、ServiceBus ベースのバックプレーン メッセージ ブロードキャストを傍受できず、メッセージがすべてのクライアントに送信されるという課題があります。ファームがあるため、ユーザーは途中で接続を切断し、ロードバランサーに基づいて他のサーバーに接続する可能性があるため、シームレスに統合するために Service Bus を使用してスケールアウトする必要があり、アプリケーションの内部目的にも使用しているため、複雑なソリューションで他の組み合わせを使用したくありません。

使用してみIHubPipelineModuleましたが、メッセージ ブロードキャストをスケールアウトしても通過しません。SignalR コードを直接接続してデバッグしようとしましたが、時間がかかりました。実際のコードで恣意的なものを台無しにしたくありません。私が見ることがOnReceiveできるように、メッセージが来ていることがわかりますが、それ以上フォローすることはできません. ブロードキャストメッセージを傍受し、リソースを浪費してすべてのクライアントではなく、意図したクライアントに確実に送信されるようにする小さなメカニズムと、セキュリティ上の懸念が必要です。

この問題で私を助けてください、それは過去4日間からちょっと立ち往生していて、解決策にたどり着くことができず、同時にパターンを確立したいので、この種の小さな問題のために特別なビルドをフォークしたくありません.あなたの専門家の 1 人が、シームレスにそれを行う方法を知っていると確信しています。

ありがとう、シュレニク

4

1 に答える 1

0

多くの苦労と簡単な方法を見つけられなかった後、私は将来誰かのために以下の方法を見つけました。

シナリオ: 1. Web ファーム: 外部ユーザー向けの Web ページをホストする 2. バックエンド プロセス: WebApi、SharePoint、Windows サービスなどの組み合わせです。

Web ページからのユーザーが何らかのリクエストを送信し、戻り値として一意の ID を取得します。内部で要求を受信すると、処理のために TopicClient を使用してその要求を Service Bus のキューに入れます。

SubscriptionClient を使用して Service Bus 上のメッセージを監視する Windows サービスのプールがあり、そのメッセージを処理します。5 秒から 30 秒、場合によってはそれ以上かかるプロセスの完了時。Web ページで待機している場合、または完了通知を待機している場合は、ジョブが完了したことをクライアントに通知する必要があります。

このストーリーでは、SignalR を使用してジョブの完了通知をクライアントにプッシュしています。

今私の以前の問題は、ジョブが完了したことをWindowsサービスからWebアプリケーションに通知する方法です。リクエストを送信したクライアントに通知を送信します。

1 つの方法は、別のハブを Web アプリケーション内で内部的にホストすることです。Windows サービスはクライアントとして機能し、Web アプリケーションがホストするハブを呼び出します。そのハブ メソッドでは、外部向けのハブ メソッドを呼び出して、要求を送信した特定のクライアントにメッセージを伝達します。シングル ユーザー グループを使用します。

また、サービス バスをバックプレーンとして登録しているため、他のサーバーに伝達され、適切なクライアントが通知を受け取ります。したがって、これは理想的なソリューションであり、ほとんどの場合に機能するはずです。

上記のアプローチでは、Windows 認証がないため、Windows サービスが Web クライアントに接続する方法という 1 つの制限がありますが、ADFS では openid ベースの認証があります。このような場合、Web アプリケーションは、Windows サービスが通信するために別のユーザー ID またはパスワードを提供するか、Windows サービスのサービス アカウントのハブに対しても Windows 認証を許可する特別なコードを必要としました。

私は、サーバー間通信と追加のセキュリティの管理との間のこの希望をすべて取り除く方法を試していました。

そのため、SignalR の内部を見つけるのに一晩かかりましたが、簡単に以下を行いました。しかし、それは機能します:

アプローチは、メッセージを ServiceBus バックプレーンに直接送信することです。すべての Web サーバーは既に ServiceBus バックプレーンに接続されているため、メッセージを受信します。

残念ながら、SignalR はメッセージを直接バックプレーンに送信するメカニズムを提供していません。私はそれがpub / subモデルにあると思うので、誰かがシステムをハッキングすることを望んでいません:)。またはそのパターンの違反ですが、私の場合は役割とセキュリティが異なるため、理にかなっています。コードを次のように単純化しました。

  1. 以下と同じ方法で、私のコードで ServiceBusMessageBus インスタンスを作成します: 別のインスタンスを作成し、Windows サービスの存続期間まで保存したので、毎回インスタンスを作成しません:

ServiceBusMessageBus serviceBusBackplane = new ServiceBusMessageBus(new DefaultDependencyResolver(), new ServiceBusScaleoutConfiguration(connectionString, appName));

  1. ClientHubInvocation オブジェクトを作成する: これは、バックプレーン ベースのメッセージ ブロードキャスト時に SignalR インフラストラクチャで実際に作成されるメッセージです。

                    ClientHubInvocation hubData = new ClientHubInvocation
                    {
                        Args = new object[] { msg },
                        Hub = "JobStatusHub",
                        Method = "onJobStatus",
                        State = null,
                    };
    
  2. はい、ServiceBusMessageBus.Publish によって受け入れられるメッセージ オブジェクトを作成します。これは、基本クラス ScaleoutMessageBus.Publish で実際に呼び出されるメソッドです。このクラスは、実際には、他のサーバー ノード上のトピックおよび他のサブスクライバーにメッセージを送信する役割を果たします。それを直接使用してみませんか。Message オブジェクトを作成するには、次のコードが必要です。

Message backplaneMessage = new Message( sourceId, "hg-JobStatusHub." + name, new ArraySegment(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(hubData))));

上記の 2 番目のパラメーターは興味深いものです。すべてのクライアントに公開する場合、構文は "h-" です。私の場合、特定のグループ ユーザーなので、構文は "hg-.. ここでコードを確認できます: https ://github.com/SignalR/SignalR/blob/bc9412bcab0f5ef097c7dc919e3ea1b37fc8718c/src/Microsoft.AspNet.SignalR.Core/Infrastructure/PrefixHelper.cs

  1. 以下のように、メッセージをバックプレーンに直接発行します。

serviceBusBackplane.Publish (backplaneMessage) を待機します。

この PrefixHelper クラスが公開されていることを願っています。

覚えておいてください: これは推奨される方法ではなく、SignalR の将来のアップグレードから隔離されません。しかし、要約すると、これは機能します。SignalR チームが、メッセージをバックプレーンに直接送信するためのすぐに使用できるメカニズムを提供してくれることを願っています。

ありがとう

于 2014-07-09T19:06:36.930 に答える