2

Azure WebJob から Web サーバー上で実行されているブラウザー クライアントに SignalR メッセージを直接送信したいので、WebJob とサーバーの両方で Azure Service Bus をバックプレーンとして使用するように SignalR を構成しました。WebJob から送信されたメッセージは Service Bus トピック キューに送信され、Web サーバーによって取得されますが、接続されている SignalR Web クライアントには送信されません。これは自動的に行われると思っていましたが、どうにかして Web サーバーから WebJob SignalR メッセージをサブスクライブし、手動でブラウザー クライアントに伝達する必要がありますか?

いくつかのコードを貼り付けますが、エラーが発生していないため、何が関連しているのかわかりません。サービス バスを介して Web ジョブから Web サーバーへのメッセージを追跡できますが、各 Web サーバーで実行されている SignalR ブラウザー クライアントには何も到達しません。

顕著な点;

  • 各ハブ インスタンスは、同じハブ名を使用して登録されます
  • WebJob と Web サーバーの両方が同じ Service Bus バックプレーン接続文字列を使用している
  • メッセージが正しいトピックに送信され、正しいサブスクリプションが読み取られていることがわかります

WebJob からのトレース情報:

SignalR.ServiceBusMessageBus 情報: 0: サービス バスで 5 つのトピックをサブスクライブしています... SignalR.ServiceBusMessageBus 情報: 0: 新しいトピック クライアントの作成 SIGNALR_TOPIC_SignalREvents_0 が正常に完了しました。SignalR.ServiceBusMessageBus 情報: 0 : サービス バスのトピック SIGNALR_TOPIC_SignalREvents_0 の新しいサブスクリプション 2ea68ce5-58fe-4218-8768-e03675be8e74 の作成が正常に完了しました。SignalR.ServiceBusMessageBus 情報: 0 : サービス バスのサブスクリプション エンティティ パス SIGNALR_TOPIC_SignalREvents_0/Subscriptions/2ea68ce5-58fe-4218-8768-e03675be8e74 のメッセージ受信の作成が正常に完了しました。SignalR.ScaleoutMessageBus 情報: 0 : ストリーム (0) - 状態が初期からオープン (x5) に変更されました SignalR.ServiceBusMessageBus 情報: 0 : サービス バス トピック サービスの 5 つのトピックへのサブスクリプションが正常に完了しました。SignalR.ServiceBusMessageBus Verbose: 0: Service Bus 経由で 68 バイトを送信中: {"H":"auctionHub","M":"Init","A":[{"Price":569.72,"Symbol":"GOOG" }]} SignalR.ServiceBusMessageBus Verbose: 0: Service Bus 経由で 68 バイトを送信中: {"H":"auctionHub","M":"Init","A":[{"Price":577.38,"Symbol": "APPL"}]} SignalR.ServiceBusMessageBus Verbose: 0: Service Bus 経由で 68 バイトを受信中: {"H":"auctionHub","M":"Init","A":[{"Price":569.72," Symbol":"GOOG"}]} SignalR.ScaleoutMessageBus 情報: 0 : OnReceived(4, 65, 1)

Web サーバーからのトレース

SignalR.ServiceBusMessageBus 情報: 0: サービス バスで 5 つのトピックをサブスクライブしています... SignalR.ServiceBusMessageBus 情報: 0: 新しいトピック クライアントの作成 SIGNALR_TOPIC_SignalREvents_0 が正常に完了しました。SignalR.ServiceBusMessageBus 情報: 0 : サービス バスのトピック SIGNALR_TOPIC_SignalREvents_0 の新しいサブスクリプション e6afd744-7724-4ab5-8fd9-2717a62caf61 の作成が正常に完了しました。SignalR.ServiceBusMessageBus 情報: 0 : サービス バスのサブスクリプション エンティティ パス SIGNALR_TOPIC_SignalREvents_0/Subscriptions/e6afd744-7724-4ab5-8fd9-2717a62caf61 のメッセージ受信の作成が正常に完了しました。SignalR.ScaleoutMessageBus 情報: 0 : Stream(0) - 状態を初期からオープンに変更 SignalR.ServiceBusMessageBus 情報: 0 : 新しいトピック クライアント SIGNALR_TOPIC_SignalREvents_1 の作成が正常に完了しました。SignalR.ServiceBusMessageBus 情報: 0 : サービス バスでのトピック SIGNALR_TOPIC_SignalREvents_1 の新しいサブスクリプション 2c155757-123f-44ba-ace7-96a6b390234e の作成が正常に完了しました。SignalR.ServiceBusMessageBus 情報: 0 : サービス バス内のサブスクリプション エンティティ パス SIGNALR_TOPIC_SignalREvents_1/Subscriptions/2c155757-123f-44ba-ace7-96a6b390234e のメッセージ受信の作成が正常に完了しました。SignalR.ScaleoutMessageBus 情報: 0 : ストリーム (1) - 状態が初期からオープンに変更されました SignalR.ServiceBusMessageBus 情報: 0 : 新しいトピック クライアント SIGNALR_TOPIC_SignalREvents_2 の作成が正常に完了しました。SignalR.Transports.TransportHeartBeat 情報: 0 :

SignalR.ServiceBusMessageBus Verbose: 0: Service Bus 経由で 37 バイトを受信中: {"H":"auctionHub","M":"Init","A":[1]} SignalR.ScaleoutMessageBus 情報: 0: OnReceived(4, 221, 1)

SignalR サービス バス構成コード (WebJob と Web サーバーで同じ)

var scaleOutConfig = new ServiceBusScaleoutConfiguration(ConfigurationManager.ConnectionStrings["AzureWebJobsServiceBus"].ConnectionString, "SignalREvents");
GlobalHost.DependencyResolver.UseServiceBus(scaleOutConfig);

髪の毛が残っていたら、引き裂いていたでしょう。私はこれを広範囲に検索しましたが、有用なものを見つけることができませんでした。任意のポインタをいただければ幸いです。

編集 >>

[HubName("auctionHub")]
public class AuctionHub : Hub<IAuctionHubClientMethods>
{
    private readonly IAuctionHubService _auctionHubService;

    public AuctionHub(IAuctionHubService auctionHubService)
    {
        _auctionHubService = auctionHubService;
    }

    public override Task OnConnected()
    {
        var userId = Context.User.Identity.GetUserId();
        var connectionId = Context.ConnectionId;
        _auctionHubService.OnConnected(Groups, userId, connectionId);
        return base.OnConnected();
    }

public interface IAuctionHubClientMethods
{
    Task Heartbeat(string now);
    Task Init(AuctionViewModel eventId);
}

public class AuctionHubService : IAuctionHubService
{
    <snip>

    public AuctionHubService(IAuctionServices auctionServicesProxy, IQueryProcessor queryProcessor, ApplicationUserManager userManager)
    {
         <snip>
    }

    public void OnConnected(IGroupManager groups, string userId, string connectionId)
    {
        var user = _userManager.FindById(userId);
        var client = user.Client;
        var id = client?.Id;
        groups.Add(connectionId, user.Client.Id.ToString());
    }

    public void Init(int eventId, IHubCallerConnectionContext<IAuctionHubClientMethods> clients)
    {
        var query = new GetAuctionViewModelByEventIdQuery { EventId = eventId };
        var eventState = _queryProcessor.Process(query);
        eventState.Suppliers.ForEach(x => clients.Group(x.SupplierId.ToString()).Init(eventState));
    }
}

OnDisconnectedそしてOnReconnected手付かずです。

必要に応じて SignalR コンテキストを提供するために SimpleInjector を使用していますが、この実装は効果がありますか?

 var hubConfiguration = new HubConfiguration
        {
            EnableDetailedErrors = true,
            EnableJavaScriptProxies = false,
            Resolver = new SignalRDependencyResolver(MvcApplication.Container),
        };

app.MapSignalR<SignalRHubDispatcher>("/signalr", hubConfiguration);

public class SignalRHubDispatcher : HubDispatcher
{
    public SignalRHubDispatcher(Container container, HubConfiguration configuration) : base(configuration)
    {
        _container = container;
    }

    protected override Task OnConnected(IRequest request, string connectionId)
    {
        return Invoke(() => base.OnConnected(request, connectionId));
    }

    protected override Task OnReceived(IRequest request, string connectionId, string data)
    {
        return Invoke(() => base.OnReceived(request, connectionId, data));
    }

    protected override Task OnDisconnected(IRequest request, string connectionId, bool stopCalled)
    {
        return Invoke(() => base.OnDisconnected(request, connectionId, stopCalled));
    }

    protected override Task OnReconnected(IRequest request, string connectionId)
    {
        return Invoke(() => base.OnReconnected(request, connectionId));
    }

    private async Task Invoke(Func<Task> method)
    {
        using (_container.BeginExecutionContextScope())
        {
            await method();
        }
    }

    private readonly Container _container;
}
4

0 に答える 0