首页 文章

使用SignalR从Azure ServiceBus Message Queue向Azure Web App广播数据

提问于
浏览
1

我有一个Azure ServiceBus消息队列,它正在从一个成熟的Windows应用程序接收消息 . 这部分很好用(每分钟几十条消息) . 我知道消息在那里 . ServiceBus命名空间类似于dtx-ns,队列名称类似于dtxrm001 .

我还有一个完全开发的MVC 5 Azure Web App . 我想连接一个新的View页面,该页面使用SignalR从Azure Service Bus Message Queue接收消息 .

我想要做的就是通过访问网页来查看ServiceBus Queue消息(来自运行完整Windows应用程序的任何人) .

这基本上就是传感器数据,比如来自传感器的温度 .

在购买了5本SignalR书籍并花了3个星期后,我想我需要一些方向 . 我是否将Azure角色添加到Azure MVC应用程序中?我是否添加了工作者角色?我是否使用依赖注入和SignalRBackplaneMessageBus?

看起来像一个简单的任务,但是现在,我现在不知道这个方法是什么?当你真正进入一个样本然后尝试连接来自ServiceBus Message Queue的消息的实际广播时,似乎没有任何意义 .

以下是我尝试过的MVC Web应用启动的一些代码:

Dim cn1 As String = "Endpoint=sb://dtx-ns.servicebus.windows.net/;SharedAccessKeyName=myname;SharedAccessKey=mykey"
    Dim config As New ServiceBusScaleoutConfiguration(cn1, "dtx1")
    config.TopicCount = 3
    config.BackoffTime = New TimeSpan(1, 0, 1)
    config.IdleSubscriptionTimeout = New TimeSpan(1, 0, 0)
    config.MaximumMessageSize = 20000
    config.MaxQueueLength = 50

    GlobalHost.DependencyResolver.UseServiceBus(config)
    GlobalHost.Configuration.TransportConnectTimeout = TimeSpan.FromSeconds(10)

    app.UseCors(CorsOptions.AllowAll)
    app.MapSignalR()

上面显示的 endpoints 是Service Bus Message Queue的连接字符串的一部分 . 如果上面看起来是正确的,那么我该如何设置Hub以从此连接发送消息?

我需要Web角色吗?我是否需要以某种方式在我添加到当前MVC应用程序的项目中实现“Backplane Hub”?我很难过 .

2 回答

  • 0

    我需要从Azure Service Bus Message Queue读取Azure MVC-5 Web App,然后通过SignalR将数据发送到所有客户端网页,这已得到解决 .

    代码方面,它非常简单和优雅 . 这是我的解决方案:

    首先,我的Visual Studio解决方案只有一个项目 - 主要的Web应用程序项目 . 在项目的根目录中,我有一个名为djwHub的SignalR集线器类;

    Imports Microsoft.AspNet.SignalR
    Imports Microsoft.AspNet.SignalR.Hubs
    Imports Microsoft.AspNet.SignalR.Messaging
    Imports System.Threading.Tasks
    Imports Microsoft.ServiceBus
    Imports Microsoft.ServiceBus.Messaging
    
    <HubName("djwHub")>
    Public Class djwHub
        Inherits Hub
    
        Private connectString As String = "Endpoint=sb://mynamespace.servicebus.windows.net/;SharedAccessKeyName=myKeyName;SharedAccessKey=myKey"
        Private queueName As String = "myQueueName"
        Private m_count As Integer
    
        Public Sub beginReadingMessageQue()
            Dim rf = MessagingFactory.CreateFromConnectionString(connectString)
    
            Dim taskTimer = Task.Factory.StartNew(Async Function()
                                                      Dim receiver = Await rf.CreateMessageReceiverAsync(queueName, ReceiveMode.PeekLock)
    
                                                      While True
                                                          Dim timeNow As String = DateTime.Now.ToString()
                                                          Clients.All.sendServerTime(timeNow)
    
                                                          Try
                                                              Dim message = Await receiver.ReceiveAsync(TimeSpan.FromSeconds(5))
    
                                                              If message IsNot Nothing Then
                                                                  Dim messageBody = message.GetBody(Of [String])()
    
                                                                  Clients.All.sendNewMessage(messageBody)
    
                                                                  Await message.CompleteAsync
                                                              Else
                                                                  'no more messages in the queue
                                                                  Exit Try
                                                              End If
                                                          Catch e As MessagingException
                                                              If Not e.IsTransient Then
                                                                  'Console.WriteLine(e.Message)
                                                                  'Throw
                                                              End If
                                                          End Try
    
                                                          'Delaying by 1/2 second.
                                                          Await Task.Delay(500)
                                                      End While
    
                                                  End Function, TaskCreationOptions.LongRunning)
        End Sub
    End Class
    

    现在,我的MVC-5 Web应用程序在根目录中没有Startup类 . 相反,我的启动发生在位于App_Start文件夹中的IdentityConfig.vb类中 . 所以这就是我把app.MapSignalR()放在这里所示的地方;

    Imports Microsoft.AspNet.Identity
    Imports Microsoft.Owin
    Imports Microsoft.Owin.Security.Cookies
    Imports Owin
    Imports myApp.Users.Infrastructure
    Imports Microsoft.Owin.Security.Google
    Imports Microsoft.AspNet.SignalR
    Imports Microsoft.Owin.Cors
    Imports Microsoft.AspNet.SignalR.ServiceBus
    
    Namespace Users
        Public Class IdentityConfig
            Public Sub Configuration(app As IAppBuilder)
                app.CreatePerOwinContext(Of AppIdentityDbContext)(AddressOf AppIdentityDbContext.Create)
                app.CreatePerOwinContext(Of AppUserManager)(AddressOf AppUserManager.Create)
                app.CreatePerOwinContext(Of AppRoleManager)(AddressOf AppRoleManager.Create)
    
                app.UseCookieAuthentication(New CookieAuthenticationOptions() With { _
                    .AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, _
                    .LoginPath = New PathString("/Account/Login") _
                })
    
                app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie)
                app.MapSignalR()
            End Sub
        End Class
    End Namespace
    

    剩下的唯一部分是Web View页面 . 请注意,我现在在网页上有6个FusionChart仪表 . 但是你应该能够选择与djwHub对话的SignalR函数调用;

    @Code
        Layout = Nothing
    End Code
    
    <head>
        <title>Drillers Readout - Job #@ViewBag.JobNumber</title>
        @Scripts.Render("~/bundles/modernizr")
        @Scripts.Render("~/bundles/jquery")
        @Scripts.Render("~/bundles/bootstrap")
        @Scripts.Render("~/bundles/jqueryui")
    
        <script src="~/Scripts/jquery.signalR-2.2.1.js"></script>
        <script src="~/Scripts/jquery.signalR-2.2.1.min.js"></script>
        <script src="~/signalr/hubs"></script>
        <script type="text/javascript">
            (function () {
                var currentIndex = -1;
                var lastTime;
                var GxDisplay;
                var GyDisplay;
                var GzDisplay;
                var HxDisplay;
                var HyDisplay;
                var HzDisplay;
    
                var myHub = $.connection.djwHub;
                $.connection.hub.logging = true;
    
                myHub.client.sendNewMessage = function (message) {
                    var myArray = JSON.parse(message);
    
                    currentIndex += 1;
                    //var dataId = myArray.dataCount;
    
                    if (currentIndex == 0) {
                        lastTime = new Date(myArray.time1);
                    } else {
                        var newTime = new Date(myArray.time1);
                        if (newTime >= lastTime) {
                            var dataId = myArray.dataCount;
                            var Gx = myArray.Gx;
                            var Gy = myArray.Gy;
                            var Gz = myArray.Gz;
                            var Hx = myArray.Hx;
                            var Hy = myArray.Hy;
                            var Hz = myArray.Hz;
    
                            lastTime = newTime;
    
                            GxDisplay.feedData("value=" + Gx);
                            GyDisplay.feedData("value=" + Gy);
                            GzDisplay.feedData("value=" + Gz);
                            HxDisplay.feedData("value=" + Hx);
                            HyDisplay.feedData("value=" + Hy);
                            HzDisplay.feedData("value=" + Hz);
    
                            $("#newMessage").text('#' + dataId + ": " + lastTime + " Gx=" + Gx.toFixed(2) + " Gy=" + Gy.toFixed(2) + " Gz=" + Gz.toFixed(2)
                                + " Hx=" + Hx.toFixed(2) + " Hy=" + Hy.toFixed(2) + " Hz=" + Hz.toFixed(2));
                        }
                    }
                };
    
                $.connection.hub.start().done(function () {
                    myHub.server.beginReadingMessageQue();
                });
    
                myHub.client.sendServerTime = function (serverTime) {
                    $("#newTime").text(serverTime);
                };
    
                FusionCharts.ready(function () {
                    GxDisplay = new FusionCharts({
                        type: 'angulargauge',
                        renderAt: 'GxChart',
                        width: '250',
                        height: '175',
                        dataFormat: 'json',
                        dataSource: {
                            "chart": {
                                "caption": "Gx",
                                "subcaption": "",
                                "lowerLimit": "-2000",
                                "upperLimit": "2000",
                                "lowerLimitDisplay": "",
                                "upperLimitDisplay": "",
                                "showValue": "1",
                                "valueBelowPivot": "1",
                                "theme": "fint"
                            },
                            "colorRange": {
                                "color": [{
                                    "minValue": "-2000",
                                    "maxValue": "2000",
                                    "code": "#ADD8E6"
                                }]
                            },
                            "dials": {
                                "dial": [{
                                    "id": "fcGx",
                                    "value": "0"
                                }]
                            }
                        }
                    });
    
                    GyDisplay = new FusionCharts({
                        type: 'angulargauge',
                        renderAt: 'GyChart',
                        width: '250',
                        height: '175',
                        dataFormat: 'json',
                        dataSource: {
                            "chart": {
                                "caption": "Gy",
                                "subcaption": "",
                                "lowerLimit": "-2000",
                                "upperLimit": "2000",
                                "lowerLimitDisplay": "",
                                "upperLimitDisplay": "",
                                "showValue": "1",
                                "valueBelowPivot": "1",
                                "theme": "fint"
                            },
                            "colorRange": {
                                "color": [{
                                    "minValue": "-2000",
                                    "maxValue": "2000",
                                    "code": "#ADD8E6"
                                }]
                            },
                            "dials": {
                                "dial": [{
                                    "id": "fcGy",
                                    "value": "0"
                                }]
                            }
                        }
                    });
    
                    GzDisplay = new FusionCharts({
                        type: 'angulargauge',
                        renderAt: 'GzChart',
                        width: '250',
                        height: '175',
                        dataFormat: 'json',
                        dataSource: {
                            "chart": {
                                "caption": "Gz",
                                "subcaption": "",
                                "lowerLimit": "-2000",
                                "upperLimit": "2000",
                                "lowerLimitDisplay": "",
                                "upperLimitDisplay": "",
                                "showValue": "1",
                                "valueBelowPivot": "1",
                                "theme": "fint"
                            },
                            "colorRange": {
                                "color": [{
                                    "minValue": "-2000",
                                    "maxValue": "2000",
                                    "code": "#ADD8E6"
                                }]
                            },
                            "dials": {
                                "dial": [{
                                    "id": "fcGz",
                                    "value": "0"
                                }]
                            }
                        }
                    });
    
                    HxDisplay = new FusionCharts({
                        type: 'angulargauge',
                        renderAt: 'HxChart',
                        width: '250',
                        height: '175',
                        dataFormat: 'json',
                        dataSource: {
                            "chart": {
                                "caption": "Hx",
                                "subcaption": "",
                                "lowerLimit": "-100000",
                                "upperLimit": "100000",
                                "lowerLimitDisplay": "",
                                "upperLimitDisplay": "",
                                "showValue": "1",
                                "valueBelowPivot": "1",
                                "theme": "fint"
                            },
                            "colorRange": {
                                "color": [{
                                    "minValue": "-100000",
                                    "maxValue": "100000",
                                    "code": "#ff1493"
                                }]
                            },
                            "dials": {
                                "dial": [{
                                    "id": "fcHx",
                                    "value": "0"
                                }]
                            }
                        }
                    });
    
                    HyDisplay = new FusionCharts({
                        type: 'angulargauge',
                        renderAt: 'HyChart',
                        width: '250',
                        height: '175',
                        dataFormat: 'json',
                        dataSource: {
                            "chart": {
                                "caption": "Hy",
                                "subcaption": "",
                                "lowerLimit": "-100000",
                                "upperLimit": "100000",
                                "lowerLimitDisplay": "",
                                "upperLimitDisplay": "",
                                "showValue": "1",
                                "valueBelowPivot": "1",
                                "theme": "fint"
                            },
                            "colorRange": {
                                "color": [{
                                    "minValue": "-100000",
                                    "maxValue": "100000",
                                    "code": "#ff1493"
                                }]
                            },
                            "dials": {
                                "dial": [{
                                    "id": "fcHy",
                                    "value": "0"
                                }]
                            }
                        }
                    });
    
                    HzDisplay = new FusionCharts({
                        type: 'angulargauge',
                        renderAt: 'HzChart',
                        width: '250',
                        height: '175',
                        dataFormat: 'json',
                        dataSource: {
                            "chart": {
                                "caption": "Hz",
                                "subcaption": "",
                                "lowerLimit": "-100000",
                                "upperLimit": "100000",
                                "lowerLimitDisplay": "",
                                "upperLimitDisplay": "",
                                "showValue": "1",
                                "valueBelowPivot": "1",
                                "theme": "fint"
                            },
                            "colorRange": {
                                "color": [{
                                    "minValue": "-100000",
                                    "maxValue": "100000",
                                    "code": "#ff1493"
                                }]
                            },
                            "dials": {
                                "dial": [{
                                    "id": "fcHz",
                                    "value": "0"
                                }]
                            }
                        }
                    });
    
                    GxDisplay.render();
                    GyDisplay.render();
                    GzDisplay.render();
                    HxDisplay.render();
                    HyDisplay.render();
                    HzDisplay.render();
                });
            }());
        </script> 
    </head>
    <body>
        <div id="newTime"></div>
    <ul id="newMessage"></ul> <div id="gCharts"> <div id="GxChart"></div> <div id="GyChart"></div> <div id="GzChart"></div> </div> <div id="hCharts"> <div id="HxChart"></div> <div id="HyChart"></div> <div id="HzChart"></div> </div> </body>

    特别感谢astaykov&Ashley Medway和微软,让所有这一切成为可能!

  • 1

    您正在使用代码scale out SignalR via ServiceBus(所谓的ServiceBus背板 - 示例中令人困惑的Web角色实际上是您的MVC应用程序,它可以在App Service中运行或作为WebRole运行 . 您的 SignalR Hub 与您的Web应用程序一起生活在一般情况) . 在Azure Web Apps上运行时,为了扩展SignalR本身,这是正确的 . 但这不是你要求的 .

    您要求的是从ServiceBus读取消息并将其广播到SignalR连接的客户端 . 这是完全不同的用例 . 您可以使用几个选项来实现目标:

    在这两种情况下,SignalR具有"native" .NET client的最不为人知的事实将帮助您(您可以从任何.NET应用程序连接到SignalR,包括在Windows Phone或桌面上运行的一个) .

    我这里没有提供任何代码示例,但我想我会对您的疑虑给予批准 .


相关问题