教學課程:使用 Azure 入口網站 和主題/訂用帳戶更新清查

Azure 服務匯流排 是多租使用者雲端傳訊服務,可在應用程式和服務之間傳送資訊。 異步操作可讓您彈性、代理傳訊,以及結構化先入、先出 (FIFO) 傳訊,以及發佈/訂閱功能。 如需 Azure 服務匯流排 的詳細概觀,請參閱什麼是 服務匯流排?

本教學課程示範如何在零售庫存案例中使用 服務匯流排 主題和訂用帳戶,以及使用 Azure 入口網站 和 .NET 的發行/訂閱通道。 此案例的範例是多個零售商店的庫存種類更新。 在此案例中,每個存放區或一組存放區都會取得訊息,供它們更新其種類。 本教學課程示範如何使用訂用帳戶和篩選來實作此案例。 首先,您會建立具有三個訂用帳戶的主題、新增一些規則和篩選,然後從主題和訂用帳戶傳送和接收訊息。

Image showing a sender, a topic with three subscriptions, and three receivers.

在本教學課程中,您會了解如何:

  • 使用 Azure 入口網站 建立 服務匯流排 主題和該主題的三個訂用帳戶
  • 使用 .NET 程式代碼新增訂用帳戶的篩選條件
  • 建立具有不同內容的訊息
  • 傳送訊息並確認他們已抵達預期的訂用帳戶
  • 從訂用帳戶接收訊息

必要條件

若要完成本教學課程,請確定您具有下列項目︰

  • Azure 訂用帳戶。 若要使用 Azure 服務,包括 Azure 服務匯流排,您需要訂用帳戶。 如果您沒有 Azure 訂用帳戶,您可以在開始之前建立 免費帳戶
  • Visual Studio 2019 或更新版本。

服務匯流排 主題和訂用帳戶

主題的每個 訂用帳戶 都可以接收每個訊息的複本。 主題與 服務匯流排 佇列完全通訊協議和語意相容。 服務匯流排 主題支援各種具有篩選條件的選取規則,以及設定或修改訊息屬性的選擇性動作。 每次規則相符時,都會產生訊息。 若要深入瞭解規則、篩選和動作,請遵循此 連結

在 Azure 入口網站 中建立命名空間

若要開始在 Azure 中使用 服務匯流排 傳訊實體,您必須先建立具有跨 Azure 唯一名稱的命名空間。 命名空間提供應用程式內 服務匯流排 資源(佇列、主題等)的範圍容器。

若要建立命名空間:

  1. 登入 Azure 入口網站

  2. 流覽至 [ 所有服務] 頁面

  3. 在左側導覽列上,從類別清單中選取 [整合],將滑鼠停留在 服務匯流排 上方,然後在 服務匯流排 磚上選取+按鈕。

    Image showing selection of Create a resource, Integration, and then Service Bus in the menu.

  4. 在 [建立命名空間] 頁面的 [基本] 標籤中,遵循下列步驟:

    1. 針對 [ 訂用帳戶],選擇要在其中建立命名空間的 Azure 訂用帳戶。

    2. 針對 [ 資源群組],選擇命名空間將存留在其中的現有資源群組,或建立新的資源群組。

    3. 輸入命名空間的名稱。 命名空間名稱應遵守下列命名慣例:

      • 名稱在整個 Azure 中必須是唯一的。 系統會立即檢查此名稱是否可用。
      • 名稱長度至少為 6,最多 50 個字元。
      • 名稱只能包含字母、數位、連字元 “-”。
      • 名稱必須以字母開頭,並以字母或數字結尾。
      • 名稱結尾不是 “-sb” 或 “-mgmt”。
    4. 針對 [ 位置],選擇您的命名空間應該裝載所在的區域。

    5. 針對 [定價層],選取命名空間的定價層 [基本]、[標準] 或 [進階版]。 在本快速入門中,選取 [ 標準]。

      重要

      如果您想要使用主題和訂帳戶,請選擇 [標準] 或 [進階版]。 基本定價層不支援主題/訂用帳戶。

      如果您選取 進階版 定價層,請指定傳訊單位數目。 進階層會在 CPU 和記憶體層級提供資源隔離,讓每個工作負載以隔離方式執行。 此資源容器稱為傳訊單位。 進階命名空間至少有一個傳訊單位。 您可以為每個 服務匯流排 進階版 命名空間選取 1、2、4、8 或 16 個傳訊單位。 如需詳細資訊,請參閱傳訊 服務匯流排 進階版。

    6. 選取頁面底部的 [檢閱 + 建立] 。

      Image showing the Create a namespace page

    7. 在 [檢閱 + 建立] 頁面上檢閱設定,然後選取 [建立]

  5. 部署資源成功后,請選取 部署頁面上的 [移至資源 ]。

    Image showing the deployment succeeded page with the Go to resource link.

  6. 您會看到服務總線命名空間的首頁。

    Image showing the home page of the Service Bus namespace created.

取得命名空間 連接字串 (Azure 入口網站)

建立新的命名空間會自動產生具有主要和次要密鑰的初始共用存取簽章(SAS)原則,以及主要和次要 連接字串,每個原則都會授與命名空間所有層面的完整控制權。 如需如何為一般傳送者和接收者建立具有更受限許可權的規則,請參閱 服務匯流排 驗證和授權

用戶端可以使用 連接字串 來連線到 服務匯流排 命名空間。 若要複製命名空間的主要 連接字串,請遵循下列步驟:

  1. [服務匯流排 命名空間] 頁面上,選取左側功能表上的 [共用存取原則]。

  2. 在 [ 共用存取原則] 頁面上,選取 [RootManageSharedAccessKey]。

  3. 在 [原則:RootManageSharedAccessKey] 視窗中,選取 [主要 連線 ion String] 旁的 [複製] 按鈕,將 連接字串 複製到剪貼簿以供稍後使用。 將此值貼到 記事本 或其他暫存位置。

    Screenshot shows an S A S policy called RootManageSharedAccessKey, which includes keys and connection strings.

    您可以使用此頁面來複製主要金鑰、次要金鑰、主要 連接字串 和次要 連接字串。

使用 Azure 入口網站 建立主題

  1. [服務匯流排 命名空間] 頁面上,選取左側功能表上的 [主題]。

  2. 選取 工具列上的 [+ 主題 ]。

  3. 輸入主題的名稱。 保留其他選項的預設值。

  4. 選取 建立

    Screenshot of the Create topic page.

建立主題的訂用帳戶

  1. 選取您在上一節中建立的主題

    Screenshot of the Topics page with your topic selected.

  2. [服務匯流排 主題] 頁面上,從左側功能表中選取 [訂用帳戶],然後在工具列上選取 [+ 訂用帳戶]。

    Screenshot of the Subscriptions page with the Add subscription button selected.

  3. 在 [ 建立訂用帳戶] 頁面上,遵循下列步驟:

    1. 輸入 S1 以取得 訂用帳戶的名稱

    2. 然後,選取 [建立 ] 以建立訂用帳戶。

      Screenshot of the Create subscription page.

  4. 重複上一個步驟兩次,以建立名為 S2 和 S3訂用帳戶。

在訂用帳戶上建立篩選規則

布建命名空間和主題/訂用帳戶之後,而且您有命名空間 連接字串 之後,您就可以在訂用帳戶上建立篩選規則,然後傳送和接收訊息。 您可以檢查此 GitHub 範例資料夾中的程式代碼

傳送和接收訊息

若要執行程式代碼,請遵循下列步驟:

  1. 在命令提示字元或 PowerShell 提示字元中,發出下列命令來複製 服務匯流排 GitHub 存放庫

    git clone https://github.com/Azure/azure-service-bus.git
    
  2. 瀏覽至範例資料夾 azure-service-bus\samples\DotNet\Azure.Messaging.ServiceBus\BasicSendReceiveTutorialWithFilters

  3. 取得您稍早在本教學課程中複製到 記事本 連接字串。 您也需要您在上一節中建立的主題名稱。

  4. 在命令提示字元中,輸入下列命令:

    dotnet build
    
  5. 瀏覽至 BasicSendReceiveTutorialWithFilters\bin\Debug\netcoreapp3.1 資料夾。

  6. 輸入下列命令以執行程式。 請務必將 取代為您先前取得的值,並將 myTopicName 取代myConnectionString為您建立的主題名稱:

    dotnet --roll-forward Major BasicSendReceiveTutorialWithFilters.dll -ConnectionString "myConnectionString" -TopicName "myTopicName"
    
  7. 請遵循控制台中的指示,先選取篩選建立。 建立篩選的一部分是移除預設篩選。 當您使用 PowerShell 或 CLI 時,您不需要移除預設篩選條件,但如果您在程式代碼中這麼做,則必須移除它們。 主控台命令 1 和 3 可協助您管理您先前建立之訂用帳戶上的篩選:

    • 執行 1:移除預設篩選。

    • 執行 2:以新增您自己的篩選。

    • 執行 3: 略過本教學課程的此步驟。 此選項選擇性地移除您自己的篩選。 它不會重新建立預設篩選。

      Showing output of 2

  8. 建立篩選之後,您可以傳送訊息。 按 4 並觀察傳送至主題的 10 則訊息:

    Send output

  9. 按 5 並觀察正在接收的訊息。 如果您沒有收到 10 則訊息,請按 「m」 以顯示功能表,然後再按 5。

    Receive output

清除資源

不再需要時,請遵循下列步驟來清除資源。

  1. 流覽至 Azure 入口網站 中的命名空間。
  2. [服務匯流排 命名空間] 頁面上,從命令行選取 [刪除],以刪除其中命名空間和資源(佇列、主題和訂用帳戶)。

了解範例程式碼

本節包含範例程式代碼執行作業的詳細數據。

取得 連接字串和主題

首先,程式代碼會宣告一組變數,以驅動程序的剩餘執行。

string ServiceBusConnectionString;
string TopicName;

static string[] Subscriptions = { "S1", "S2", "S3" };
static IDictionary<string, string[]> SubscriptionFilters = new Dictionary<string, string[]> {
    { "S1", new[] { "StoreId IN('Store1', 'Store2', 'Store3')", "StoreId = 'Store4'"} },
    { "S2", new[] { "sys.To IN ('Store5','Store6','Store7') OR StoreId = 'Store8'" } },
    { "S3", new[] { "sys.To NOT IN ('Store1','Store2','Store3','Store4','Store5','Store6','Store7','Store8') OR StoreId NOT IN ('Store1','Store2','Store3','Store4','Store5','Store6','Store7','Store8')" } }
};
// You can have only have one action per rule and this sample code supports only one action for the first filter, which is used to create the first rule. 
static IDictionary<string, string> SubscriptionAction = new Dictionary<string, string> {
    { "S1", "" },
    { "S2", "" },
    { "S3", "SET sys.Label = 'SalesEvent'"  }
};
static string[] Store = { "Store1", "Store2", "Store3", "Store4", "Store5", "Store6", "Store7", "Store8", "Store9", "Store10" };
static string SysField = "sys.To";
static string CustomField = "StoreId";
static int NrOfMessagesPerStore = 1; // Send at least 1.

連接字串 和主題名稱會透過命令行參數傳入,如下所示,然後在方法中Main()讀取:

static void Main(string[] args)
{
    string ServiceBusConnectionString = "";
    string TopicName = "";

    for (int i = 0; i < args.Length; i++)
    {
        if (args[i] == "-ConnectionString")
        {
            Console.WriteLine($"ConnectionString: {args[i + 1]}");
            ServiceBusConnectionString = args[i + 1]; // Alternatively enter your connection string here.
        }
        else if (args[i] == "-TopicName")
        {
            Console.WriteLine($"TopicName: {args[i + 1]}");
            TopicName = args[i + 1]; // Alternatively enter your queue name here.
        }
    }

    if (ServiceBusConnectionString != "" && TopicName != "")
    {
        Program P = StartProgram(ServiceBusConnectionString, TopicName);
        P.PresentMenu().GetAwaiter().GetResult();
    }
    else
    {
        Console.WriteLine("Specify -Connectionstring and -TopicName to execute the example.");
        Console.ReadKey();
    }
}

拿掉預設篩選

當您建立訂用帳戶時,服務匯流排 為每個訂用帳戶建立預設篩選條件。 此篩選可接收傳送至主題的每個訊息。 如果您想要使用自訂篩選,您可以移除預設篩選,如下列程式代碼所示:

private async Task RemoveDefaultFilters()
{
    Console.WriteLine($"Starting to remove default filters.");

    try
    {
        var client = new ServiceBusAdministrationClient(ServiceBusConnectionString);
        foreach (var subscription in Subscriptions)
        {
            await client.DeleteRuleAsync(TopicName, subscription, CreateRuleOptions.DefaultRuleName);
            Console.WriteLine($"Default filter for {subscription} has been removed.");
        }

        Console.WriteLine("All default Rules have been removed.\n");
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }

    await PresentMenu();
}

建立篩選器

下列程式代碼會新增本教學課程中定義的自訂篩選:

private async Task CreateCustomFilters()
{
    try
    {
        for (int i = 0; i < Subscriptions.Length; i++)
        {
            var client = new ServiceBusAdministrationClient(ServiceBusConnectionString);
            string[] filters = SubscriptionFilters[Subscriptions[i]];
            if (filters[0] != "")
            {
                int count = 0;
                foreach (var myFilter in filters)
                {
                    count++;

                    string action = SubscriptionAction[Subscriptions[i]];
                    if (action != "")
                    {
                        await client.CreateRuleAsync(TopicName, Subscriptions[i], new CreateRuleOptions
                        {
                            Filter = new SqlRuleFilter(myFilter),
                            Action = new SqlRuleAction(action),
                            Name = $"MyRule{count}"
                        });
                    }
                    else
                    {
                        await client.CreateRuleAsync(TopicName, Subscriptions[i], new CreateRuleOptions
                        {
                            Filter = new SqlRuleFilter(myFilter),
                            Name = $"MyRule{count}"
                        });
                    }
                }
            }

            Console.WriteLine($"Filters and actions for {Subscriptions[i]} have been created.");
        }

        Console.WriteLine("All filters and actions have been created.\n");
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }

    await PresentMenu();
}

拿掉自定義建立的篩選

如果您要移除訂用帳戶上的所有篩選,下列程式代碼會示範如何執行此動作:

private async Task CleanUpCustomFilters()
{
    foreach (var subscription in Subscriptions)
    {
        try
        {
            var client = new ServiceBusAdministrationClient(ServiceBusConnectionString);
            IAsyncEnumerator<RuleProperties> rules = client.GetRulesAsync(TopicName, subscription).GetAsyncEnumerator();
            while (await rules.MoveNextAsync())
            {
                await client.DeleteRuleAsync(TopicName, subscription, rules.Current.Name);
                Console.WriteLine($"Rule {rules.Current.Name} has been removed.");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }
    Console.WriteLine("All default filters have been removed.\n");

    await PresentMenu();
}

傳送訊息

將訊息傳送至主題類似於將訊息傳送至佇列。 此範例示範如何使用工作清單和異步處理來傳送訊息:

public async Task SendMessages()
{
    try
    {
        await using var client = new ServiceBusClient(ServiceBusConnectionString);
        var taskList = new List<Task>();
        for (int i = 0; i < Store.Length; i++)
        {
            taskList.Add(SendItems(client, Store[i]));
        }

        await Task.WhenAll(taskList);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
    Console.WriteLine("\nAll messages sent.\n");
}

private async Task SendItems(ServiceBusClient client, string store)
{
    // create the sender
    ServiceBusSender tc = client.CreateSender(TopicName);

    for (int i = 0; i < NrOfMessagesPerStore; i++)
    {
        Random r = new Random();
        Item item = new Item(r.Next(5), r.Next(5), r.Next(5));

        // Note the extension class which is serializing an deserializing messages
        ServiceBusMessage message = item.AsMessage();
        message.To = store;
        message.ApplicationProperties.Add("StoreId", store);
        message.ApplicationProperties.Add("Price", item.GetPrice().ToString());
        message.ApplicationProperties.Add("Color", item.GetColor());
        message.ApplicationProperties.Add("Category", item.GetItemCategory());

        await tc.SendMessageAsync(message);
        Console.WriteLine($"Sent item to Store {store}. Price={item.GetPrice()}, Color={item.GetColor()}, Category={item.GetItemCategory()}"); ;
    }
}

接收訊息

訊息會透過工作清單再次接收,而程式代碼會使用批處理。 您可以使用批處理來傳送和接收,但此範例只會示範如何批次接收。 事實上,您不會中斷迴圈,但請繼續循環並設定較高的時間範圍,例如一分鐘。 對訊息代理程式的接收呼叫會持續開啟,而且如果訊息送達,則會立即傳回,併發出新的接收呼叫。 這個概念稱為 長時間輪詢。 使用接收泵,您可以在快速入門中看到,以及存放庫中的數個其他範例中,是較典型的選項。

public async Task Receive()
{
    var taskList = new List<Task>();
    for (var i = 0; i < Subscriptions.Length; i++)
    {
        taskList.Add(this.ReceiveMessages(Subscriptions[i]));
    }

    await Task.WhenAll(taskList);
}

private async Task ReceiveMessages(string subscription)
{
    await using var client = new ServiceBusClient(ServiceBusConnectionString);
    ServiceBusReceiver receiver = client.CreateReceiver(TopicName, subscription);

    // In reality you would not break out of the loop like in this example but would keep looping. The receiver keeps the connection open
    // to the broker for the specified amount of seconds and the broker returns messages as soon as they arrive. The client then initiates
    // a new connection. So in reality you would not want to break out of the loop. 
    // Also note that the code shows how to batch receive, which you would do for performance reasons. For convenience you can also always
    // use the regular receive pump which we show in our Quick Start and in other GitHub samples.
    while (true)
    {
        try
        {
            //IList<Message> messages = await receiver.ReceiveAsync(10, TimeSpan.FromSeconds(2));
            // Note the extension class which is serializing an deserializing messages and testing messages is null or 0.
            // If you think you did not receive all messages, just press M and receive again via the menu.
            IReadOnlyList<ServiceBusReceivedMessage> messages = await receiver.ReceiveMessagesAsync(maxMessages: 100);

            if (messages.Any())
            {
                foreach (ServiceBusReceivedMessage message in messages)
                {
                    lock (Console.Out)
                    {
                        Item item = message.As<Item>();
                        IReadOnlyDictionary<string, object> myApplicationProperties = message.ApplicationProperties;
                        Console.WriteLine($"StoreId={myApplicationProperties["StoreId"]}");
                        if (message.Subject != null)
                        {
                            Console.WriteLine($"Subject={message.Subject}");
                        }
                        Console.WriteLine(
                            $"Item data: Price={item.GetPrice()}, Color={item.GetColor()}, Category={item.GetItemCategory()}");
                    }

                    await receiver.CompleteMessageAsync(message);
                }
            }
            else
            {
                break;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }
}

注意

您可以使用 服務匯流排 Explorer 來管理 服務匯流排 資源。 服務匯流排 總管可讓用戶連線到 服務匯流排 命名空間,並輕鬆地管理傳訊實體。 此工具提供進階功能,例如匯入/匯出功能,或測試主題、佇列、訂用帳戶、轉送服務、通知中樞和事件中樞的能力。

下一步

在本教學課程中,您已使用 Azure 入口網站 布建資源,然後從 服務匯流排 主題及其訂用帳戶傳送和接收訊息。 您已了解如何︰

  • 使用 Azure 入口網站 建立 服務匯流排 主題和該主題的一或多個訂用帳戶
  • 使用 .NET 程式代碼新增主題篩選
  • 建立兩個具有不同內容的訊息
  • 傳送訊息並確認他們已抵達預期的訂用帳戶
  • 從訂用帳戶接收訊息

如需傳送和接收訊息的更多範例,請開始使用 GitHub 上的 服務匯流排 範例。

請前往下一個教學課程,以深入瞭解如何使用 服務匯流排 的發佈/訂閱功能。