練習 - 使用主題來傳送及接收訊息
您已決定使用 Azure 服務匯流排主題,在您的銷售人力應用程式中發佈銷售績效訊息。 銷售人員會在自己的行動裝置上使用此應用程式,傳送每個區域和時段的銷售數字摘要訊息。 這些訊息會散發到位於公司營運區域 (包括美洲和歐洲) 的網路服務。
您已在此主題的 Azure 訂用帳戶中實作了必要的基礎結構。 您現在想要撰寫程式碼以將訊息傳送至主題,並撰寫程式碼從訂用帳戶擷取訊息。 然後,您會將訊息傳送至主題,並擷取特定訂用帳戶的訊息。
請在 Azure Cloud Shell 中執行下列命令,以確定自己使用正確的目錄:
cd ~/mslearn-connect-services-together/implement-message-workflows-with-service-bus/src/start
code .
撰寫程式碼以將訊息傳送至主題
若要完成能傳送銷售績效相關訊息的元件,請完成下列步驟:
在 Azure Cloud Shell 編輯器中,開啟 performancemessagesender/Program.cs 並尋找下列程式碼行:
const string ServiceBusConnectionString = "";
在引號之間貼上您在上個練習中儲存的連接字串。
如果您使用與 salesperformancemessages 不同的名稱作為佇列名稱,請更新程式碼中的
TopicName
屬性值:const string TopicName = "salesperformancemessages";
尋找
SendPerformanceMessageAsync()
方法。 (提示:其位於或接近第 26 行) 在該方法內,尋找下列程式碼:// Create a Service Bus client here
以這行程式碼取代該行程式碼:
// By leveraging "await using", the DisposeAsync method will be called automatically when the client variable goes out of scope. // In more realistic scenarios, you would store off a class reference to the client (rather than to a local variable) so that it can be used throughout your program. await using var client = new ServiceBusClient(ServiceBusConnectionString);
在
SendPerformanceMessageAsync()
方法內尋找下列程式碼:// Create a sender here
以這行程式碼取代該行程式碼:
await using ServiceBusSender sender = client.CreateSender(TopicName);
在
try...catch
區塊中,尋找下列程式碼:// Create and send a message here
以這行程式碼取代該行程式碼:
string messageBody = "Total sales for Brazil in August: $13m."; var message = new ServiceBusMessage(messageBody);
若要在主控台中顯示訊息,請在下一行插入下列程式碼:
Console.WriteLine($"Sending message: {messageBody}");
若要將訊息傳送到主題,請在下一行插入下列程式碼:
await sender.SendMessageAsync(message);
檢查您的最終程式碼是否類似於下列範例:
using System; using System.Threading.Tasks; using Azure.Messaging.ServiceBus; namespace performancemessagesender { class Program { const string ServiceBusConnectionString = "Endpoint=sb://example.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=xxxxxx"; const string TopicName = "salesperformancemessages"; static void Main(string[] args) { Console.WriteLine("Sending a message to the Sales Performance topic..."); SendPerformanceMessageAsync().GetAwaiter().GetResult(); Console.WriteLine("Message was sent successfully."); } static async Task SendPerformanceMessageAsync() { // By leveraging "await using", the DisposeAsync method will be called automatically once the client variable goes out of scope. // In more realistic scenarios, you would store off a class reference to the client (rather than to a local variable) so that it can be used throughout your program. await using var client = new ServiceBusClient(ServiceBusConnectionString); await using ServiceBusSender sender = client.CreateSender(TopicName); try { string messageBody = "Total sales for Brazil in August: $13m."; var message = new ServiceBusMessage(messageBody); Console.WriteLine($"Sending message: {messageBody}"); await sender.SendMessageAsync(message); } catch (Exception exception) { Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}"); } } } }
若要儲存變更,請選取 Ctrl+S,然後選取 Ctrl+Q 以關閉編輯器。
將訊息傳送至主題
若要執行可傳送銷售相關訊息的元件,請在 Cloud Shell 中執行下列命令︰
dotnet run --project performancemessagesender
當程式執行時,請監看 Cloud Shell 中指出正在傳送訊息的通知。 每次執行應用程式時,都會將另一則訊息新增至主題,而且每個訂用帳戶都會有一個複本可供使用。
Sending a message to the Sales Performance topic... Sending message: Total sales for Brazil in August: $13m. Message was sent successfully.
先檢查訊息計數,然後再擷取訂用帳戶的訊息
當您看到 Message was sent successfully
時,請執行下列命令來查看 Americas
訂用帳戶中有多少訊息。 請記得以您的服務匯流排命名空間取代 <namespace-name>。
az servicebus topic subscription show \
--resource-group "<rgn>[sandbox resource group name]</rgn>" \
--topic-name salesperformancemessages \
--name Americas \
--query messageCount \
--namespace-name <namespace-name>
如果您將 Americas
取代為 EuropeAndAsia
,然後再次執行命令,您將會看到這兩個訂用帳戶都有相同的訊息數目。
撰寫程式碼以擷取訂用帳戶的主題訊息
若要建立能擷取銷售績效相關訊息的元件,請完成下列步驟:
執行
code .
以啟動編輯器。在編輯器中,開啟 performancemessagereceiver/Program.cs 並尋找下列程式碼:
const string ServiceBusConnectionString = "";
在引號之間貼上您在上個練習中儲存的連接字串。
若要建立服務匯流排用戶端,請尋找
MainAsync()
方法。 在該方法中,找出下列程式碼行:// Create a Service Bus client that will authenticate using a connection string
將該程式碼取代為此行:
var client = new ServiceBusClient(ServiceBusConnectionString);
若要設定訊息處理選項,請尋找下列程式碼:
// Create the options to use for configuring the processor
將該程式碼取代為此行:
var processorOptions = new ServiceBusProcessorOptions { MaxConcurrentCalls = 1, AutoCompleteMessages = false };
若要建立處理器,請尋找下列程式碼:
// Create a processor that we can use to process the messages
將該程式碼取代為此行:
ServiceBusProcessor processor = client.CreateProcessor(TopicName, SubscriptionName, processorOptions);
若要設定處理常式,請尋找下列程式碼:
// Configure the message and error handler to use
將該程式碼取代為此行:
processor.ProcessMessageAsync += MessageHandler; processor.ProcessErrorAsync += ErrorHandler;
若要開始處理,請尋找下列程式碼:
// Start processing
將該程式碼取代為此行:
await processor.StartProcessingAsync();
尋找以下這行程式碼:
// Since we didn't use the "await using" syntax here, we need to explicitly dispose the processor and client
將該行取代為此程式碼:
await processor.DisposeAsync(); await client.DisposeAsync();
若要在主控台中顯示內送郵件,請尋找
MessageHandler()
方法。 您已登錄此方法來處理傳入訊息。將該方法內的所有程式碼取代為下列程式碼:
Console.WriteLine($"Received message: SequenceNumber:{args.Message.SequenceNumber} Body:{args.Message.Body}");
若要從訂用帳戶中移除已接收的訊息,請在下一行中新增下列程式碼:
await args.CompleteMessageAsync(args.Message);
檢查您的最終程式碼是否類似於下列範例:
using System; using System.Text; using System.Threading; using System.Threading.Tasks; using Azure.Messaging.ServiceBus; namespace performancemessagereceiver { class Program { const string ServiceBusConnectionString = "Endpoint=sb://alexgeddyneil.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=xxxxxx"; const string TopicName = "salesperformancemessages"; const string SubscriptionName = "Americas"; static void Main(string[] args) { MainAsync().GetAwaiter().GetResult(); } static async Task MainAsync() { var client = new ServiceBusClient(ServiceBusConnectionString); Console.WriteLine("======================================================"); Console.WriteLine("Press ENTER key to exit after receiving all the messages."); Console.WriteLine("======================================================"); var processorOptions = new ServiceBusProcessorOptions { MaxConcurrentCalls = 1, AutoCompleteMessages = false }; ServiceBusProcessor processor = client.CreateProcessor(TopicName, SubscriptionName, processorOptions); processor.ProcessMessageAsync += MessageHandler; processor.ProcessErrorAsync += ErrorHandler; await processor.StartProcessingAsync(); Console.Read(); await processor.DisposeAsync(); await client.DisposeAsync(); } static async Task MessageHandler(ProcessMessageEventArgs args) { Console.WriteLine($"Received message: SequenceNumber:{args.Message.SequenceNumber} Body:{args.Message.Body}"); await args.CompleteMessageAsync(args.Message); } static Task ErrorHandler(ProcessErrorEventArgs args) { Console.WriteLine($"Message handler encountered an exception {args.Exception}."); Console.WriteLine("Exception context for troubleshooting:"); Console.WriteLine($"- Endpoint: {args.FullyQualifiedNamespace}"); Console.WriteLine($"- Entity Path: {args.EntityPath}"); Console.WriteLine($"- Executing Action: {args.ErrorSource}"); return Task.CompletedTask; } } }
若要儲存變更,請選取 Ctrl+S,然後選取 Ctrl+Q 以關閉編輯器。
擷取訂用帳戶的主題訊息
若要執行可擷取訂用帳戶銷售績效相關訊息的元件,請執行下列命令:
dotnet run --project performancemessagereceiver
您會看到類似於下列範例的輸出:
Received message: SequenceNumber:1 Body:Total sales for Brazil in August: $13m.
當程式列傳回正在接收訊息的通知後,請按 Enter 停止應用程式。
擷取訂用帳戶的訊息之後,請檢查訊息計數
執行下列命令,確認 Americas
訂用帳戶中未剩下任何訊息。 請務必以您的服務匯流排命名空間取代 <namespace-name>。
az servicebus topic subscription show \
--resource-group "<rgn>[sandbox resource group name]</rgn>" \
--topic-name salesperformancemessages \
--name Americas \
--query messageCount \
--namespace-name <namespace-name>
如果您將此程式碼中的 Americas
取代為 EuropeAndAsia
,以查看 EuropeAndAsia
訂用帳戶的目前訊息計數,您會看到訊息計數為 1
。 在上述程式碼中,僅 Americas
設定為擷取主題訊息,因此訊息仍在等候 EuropeAndAsia
加以擷取。