具有工作人员角色的Azure Service Bus主题和订阅

时间:2018-08-08 20:28:55

标签: c# azure azureservicebus azure-worker-roles azure-servicebus-topics

因此,最近我需要使用Service Bus Topic and Subscriptions,并且关注了许多文章和教程。我已经能够成功实现Microsoft的Get started with Service Bus topics,并且还成功地使用了Visual Studio 2017's Worker Role模板来访问数据库。

但是,我对如何正确地“组合”两者感到困惑。尽管Get started with Service Bus topics文章展示了如何创建2个应用程序,一个要发送,一个要接收然后退出,但Worker Role模板似乎与await Task.Delay(10000);不断循环。

我不确定如何正确地将两者“网格化”。本质上,我希望我的Worker Role保持生命状态,并永远监听其订阅中的条目(或直到它明显退出为止)。

任何指导都很棒!

P.S .:如果您感兴趣,我曾在StackExchange - Software Engineering问过一个有关我应该用于我的案例的适当技术的相关问题。

更新#1(2018/08/09)

基于Arunprabhu's answer,这是一些基于我使用Message的{​​{1}}模板阅读和接收的文章中如何发送Visual Studio 2017的代码

发送(基于Get started with Service Bus topics

Worker Role with Service Bus Queue

接收(基于using System; using System.Text; using System.Threading.Tasks; using Microsoft.Azure.ServiceBus; namespace TopicsSender { internal static class Program { private const string ServiceBusConnectionString = "<your_connection_string>"; private const string TopicName = "test-topic"; private static ITopicClient _topicClient; private static void Main(string[] args) { MainAsync().GetAwaiter().GetResult(); } private static async Task MainAsync() { const int numberOfMessages = 10; _topicClient = new TopicClient(ServiceBusConnectionString, TopicName); Console.WriteLine("======================================================"); Console.WriteLine("Press ENTER key to exit after sending all the messages."); Console.WriteLine("======================================================"); // Send messages. await SendMessagesAsync(numberOfMessages); Console.ReadKey(); await _topicClient.CloseAsync(); } private static async Task SendMessagesAsync(int numberOfMessagesToSend) { try { for (var i = 0; i < numberOfMessagesToSend; i++) { // Create a new message to send to the topic var messageBody = $"Message {i}"; var message = new Message(Encoding.UTF8.GetBytes(messageBody)); // Write the body of the message to the console Console.WriteLine($"Sending message: {messageBody}"); // Send the message to the topic await _topicClient.SendAsync(message); } } catch (Exception exception) { Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}"); } } } } 模板)

Worker Role with Service Bus Queue

更新#2(2018/08/10)

在Arunprabhu提出了一些建议之后,并且知道我正在使用其他库,下面是我目前的解决方案,其中的内容来自多个来源。有什么我要忽略的东西吗?当前遇到的错误可能是另一个问题或已经回答,因此不希望在进一步研究之前发布它。

using System;
using System.Diagnostics;
using System.Net;
using System.Threading;
using Microsoft.ServiceBus.Messaging;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace WorkerRoleWithSBQueue1 {
    public class WorkerRole : RoleEntryPoint {
        // The name of your queue
        private const string ServiceBusConnectionString = "<your_connection_string>";
        private const string TopicName = "test-topic";
        private const string SubscriptionName = "test-sub1";

        // QueueClient is thread-safe. Recommended that you cache 
        // rather than recreating it on every request
        private SubscriptionClient _client;
        private readonly ManualResetEvent _completedEvent = new ManualResetEvent(false);

        public override void Run() {
            Trace.WriteLine("Starting processing of messages");

            // Initiates the message pump and callback is invoked for each message that is received, calling close on the client will stop the pump.
            _client.OnMessage((receivedMessage) => {
                try {
                    // Process the message
                    Trace.WriteLine("Processing Service Bus message: " + receivedMessage.SequenceNumber.ToString());
                    var message = receivedMessage.GetBody<byte[]>();
                    Trace.WriteLine($"Received message: SequenceNumber:{receivedMessage.SequenceNumber} Body:{message.ToString()}");
                } catch (Exception e) {
                    // Handle any message processing specific exceptions here
                    Trace.Write(e.ToString());
                }
            });

            _completedEvent.WaitOne();
        }

        public override bool OnStart() {
            // Set the maximum number of concurrent connections 
            ServicePointManager.DefaultConnectionLimit = 12;

            // Initialize the connection to Service Bus Queue
            _client = SubscriptionClient.CreateFromConnectionString(ServiceBusConnectionString, TopicName, SubscriptionName);
            return base.OnStart();
        }

        public override void OnStop() {
            // Close the connection to Service Bus Queue
            _client.Close();
            _completedEvent.Set();
            base.OnStop();
        }
    }
}

3 个答案:

答案 0 :(得分:2)

考虑到更新后的问题Update#1(2018/08/09)的复杂性,我提供了一个单独的答案。

发送者和接收者正在使用不同的库。

发件人-Microsoft.Azure.ServiceBus

接收器-WindowsAzure.ServiceBus

Microsoft.Azure.ServiceBus的消息对象为Message,其中WindowsAzure.ServiceBus具有BrokeredMessage。

Microsoft.Azure.ServiceBus中有一种方法RegisterMessageHandler,这是WindowsAzure.ServiceBus中client.OnMessage()的替代方法。通过使用此方法,侦听器将消息作为Message对象接收。该库支持您期望的异步编程。

有关两个库的示例,请参考here

答案 1 :(得分:1)

如果使用的是Visual Studio,则存在一个默认模板,可用于使用Service Bus Queue创建Azure Cloud Service和辅助角色。在那里,您需要使用WorkerRole.cs中的SubscriptionClient更改QueueClient。

然后,辅助角色将保持活动状态,侦听主题订阅中的消息。

您可以找到示例here。您应该在Cloud Service中使用Service Bus Queue创建Worker角色

enter image description here

答案 2 :(得分:0)

我想知道您是否有选择Web作业上的工作者角色的特定原因?如果没有,您可以使用具有ServiceBusTrigger属性的Web作业,它将使您的代码更简单。 more info here...