Websocket扩展了天蓝色的服务总线

时间:2017-05-01 14:50:37

标签: .net asp.net-web-api websocket azureservicebus

我正在通过.net中的rest和web套接字编写高度可用的api。我正在寻找以下策略:

  1. 跟踪每个打开的网络套接字到我的api应用程序
  2. 如何在asp.net webapi应用程序中使用队列消息或来自Azure服务总线的主题
  3. 我应该研究哪些模式或策略
  4. 此时,我的关键词搜索并未向我提供有关如何实现此问题的大量见解,但如果有任何想法,我会非常感谢您的建议!

    TL; DR:是否有人在webapi项目中创建了一个队列服务,以便将消息推送到websocket?

2 个答案:

答案 0 :(得分:1)

  

是否有人在webapi项目中创建了一个队列服务,以便将消息推送到websocket?

根据您的要求,您可以创建后台任务,以便从服务总线队列接收消息,如下所示:

<强>的Global.asax.cs

public class WebApiApplication : System.Web.HttpApplication
{
    private static ManualResetEvent _maunalResetEvent = new ManualResetEvent(false);
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        ThreadPool.QueueUserWorkItem(_ =>
        {
            var connectionString = "";
            var queueName = "samplequeue";
            var client = QueueClient.CreateFromConnectionString(connectionString, queueName);
            client.OnMessage(message =>
            {
                var messageBody = message.GetBody<String>();
                System.Diagnostics.Trace.TraceInformation(String.Format("Message body: {0}", messageBody));

               //TODO: send message to the specific client (user)
            });
            _maunalResetEvent.WaitOne();
        });
    }

    protected void Application_End()
    {
        _maunalResetEvent.Set();
    }
}

注意:有关从队列接收邮件的详细信息,请参阅此官方tutorial

为了将消息推送到您的客户端,如果您基于webapi-and-websockets,我认为您需要选择WebSocketCollection实例,然后选择具有{WebSocketHandler实例的特定_username实例{1}}匹配收到的队列消息中的属性,或者将消息广播到所有客户端,如下所示:

收到队列消息后,使用以下代码向所有客户端广播:

ChatWebSocketHandler.ChatClients.Broadcast("{queue-message}");

enter image description here

此外,您可以利用SignalR并将您的客户端(用户)映射到signalR连接,然后当您收到队列消息时,您可以将其发送给您的客户端(用户)。有关详细信息,请参阅Mapping SignalR Users to Connections。此外,您可以关注SignalR Hubs API Guide和此git sample

答案 1 :(得分:0)

我的要求有点费解。我能够通过主题和订阅模型解决问题。

我从队列中发布主题,并通过在websocket请求上生成的过滤订阅广播到所有websocket连接。非常光滑!

 private async Task ProcessWebsocketSession(AspNetWebSocketContext context)
    {
        var details = ((APIIdentity)User.Identity).Details;
        //SubscriptionHandler creates the subscription for the given system, and disposes of it safely when leaving scope
        using (var ws = context.WebSocket)
        using (var subHander = new SubscriptionHandler(details))
        {
            var client = subHander.Client;
            client.OnMessage((brokerMsg) => 
            {
                var payload = brokerMsg.GetBody<string>();
                var dataToSend = JsonConvert.DeserializeObject<Data>(brokerMsg.GetBody<string>());
                //refreshing from db, to check if data has been updated in process
                dataToSend = Repo.GetData(BusinessID, dataToSend .ID).FirstOrDefault();
                if (dataToSend != null && !dataToSend Send.IsConfirmed.Value)
                {
                    byte[] binaryData = Encoding.ASCII.GetBytes(payload);
                    var segment = new ArraySegment<byte>(binaryData);
                    var task = ws.SendAsync(segment, WebSocketMessageType.Text,
                        true, CancellationToken.None);
                    task.Wait();
                }
                brokerMsg.Complete();
            });
            var receivedBytes = new ArraySegment<byte>(new byte[1024]);
            while (ws.State == WebSocketState.Open)
            {
                // ping/pong response to verify socket is connected without changing data
                var msg = await ws.ReceiveAsync(receivedBytes, CancellationToken.None);
                if (msg.MessageType == WebSocketMessageType.Text)
                {
                    var text = Encoding.ASCII.GetString(receivedBytes.ToArray());
                    if (text.ToLower() == "ping")
                    {
                        await ws.SendAsync(new ArraySegment<byte>(Encoding.ASCII.GetBytes(text.ToCharArray())), WebSocketMessageType.Text, true, CancellationToken.None);
                    }
                }

            } 

        }