Azure Service Bus Topic を Python で送受信する

## この記事の目的

Azure Service Bus Topic をローカルPython環境から送信し、Azure Functions で受信するまでの手順を解説します。

## 👇これより先は下記内容を前提とします

- [Azure Functions でPython関数を作成してデプロイする](https://docs.saurus12.com/python/azure_function_python)

## Service Bus Topic 関連リソースを作成する

Azure ログインを実施し、サブスクリプションを設定します。  

```text
az login
az account set --subscription "*****-****-****-****-****"
```

リソースグループ`resource_group_for_python`に、Service Bus メッセージング名前空間`servicebus111`を作成します。

```text
az servicebus namespace create^
 --resource-group resource_group_for_python^
 --name servicebus111^
 --location japaneast
```

Service Bus Topic `MyTopic111`を作成します。

```text
az servicebus topic create^
 --resource-group resource_group_for_python^
 --namespace-name servicebus111^
 --name MyTopic111
```

サブスクリプション `subscription01`を作成します。

```text
az servicebus topic subscription create^
 --resource-group resource_group_for_python^
 --namespace-name servicebus111^
 --topic-name MyTopic111^
 --name subscription01
```

## 関数用の関連 Azure リソースを作成する

Azure ログインを実施し、サブスクリプションを設定します。  

```text
az login
az account set --subscription "*****-****-****-****-****"
```

リソースグループ`resource_group_for_python`に、ストレージアカウント`sasample111`を作成します。

```text
az storage account create^
 --name sasample111^
 --location japaneast^
 --resource-group resource_group_for_python^
 --sku Standard_LRS
```

リソースグループ`resource_group_for_python`に、関数アプリ`appsample111`を作成します。  
Pythonバージョンは本記事記載時点の最新バージョン`3.11`を指定します。  

```text
az functionapp create^
 --resource-group resource_group_for_python^
 --runtime python^
 --runtime-version 3.11^
 --functions-version 4^
 --os-type linux^
 --consumption-plan-location japaneast^
 --storage-account sasample111^
 --name appsample111
```

関数アプリ`appsample111`にシステム割り当て ID を追加します。

```text
az webapp identity assign^
 --name appsample111^
 --resource-group resource_group_for_python
```

下記のような出力が得られます。  
(`principalId`が関数アプリ`appsample111`のシステム割り当てID)

```text
{
 "principalId": "00000000-0000-0000-0000-000000000000",
 "tenantId": "11111111-1111-1111-1111-111111111111",
 "type": "SystemAssigned",
 "userAssignedIdentities": null
}
```

下記コマンドで関数アプリ`appsample111`にアプリケーション設定`ServiceBusConnection__fullyQualifiedNamespace`を追加し、Service Bus 名前空間`servicebus112.servicebus.windows.net`を設定します。  

```text
az functionapp config appsettings set^
 --name appsample111^
 --resource-group resource_group_for_python^
 --settings ServiceBusConnection__fullyQualifiedNamespace="servicebus111.servicebus.windows.net"
```

## ロールを割り当てる

ロール一覧を取得します。

```text
az role definition list --output table
```

下記のような出力が得られます。

```text
Name                                                        Type                                     Description
----------------------------------------------------------  ---------------------------------------  -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
AcrPush                                                     Microsoft.Authorization/roleDefinitions  acr push
API Management Service Contributor                          Microsoft.Authorization/roleDefinitions  Can manage service and the APIs
AcrPull                                                     Microsoft.Authorization/roleDefinitions  acr pull
・・・・
Azure Service Bus Data Owner                                Microsoft.Authorization/roleDefinitions  Allows for full access to Azure Service Bus resources.
Azure Event Hubs Data Owner                                 Microsoft.Authorization/roleDefinitions  Allows for full access to Azure Event Hubs resources.
```

`Service Bus Data Owner`権限を割り当てます。

```text
az role assignment create^
 --assignee "00000000-0000-0000-0000-000000000000"^
 --role "Azure Service Bus Data Owner"^
 --scope "/subscriptions/***-***-***-***/resourceGroups/resource_group_for_python/providers/Microsoft.ServiceBus/namespaces/servicebus112"
```

## ローカル関数の作成

`func init`コマンドを実行して、`LocalFunctionSurviceBusTopicProj` というフォルダーに関数プロジェクトを作成します。  

```text
func init LocalFunctionSurviceBusTopicProj --python -m V2
```

プロジェクトフォルダーに移動します。  

```text
cd LocalFunctionSurviceBusTopicProj
```

関数を作成します。  

```text
func new
```

下記のようにtemplateの選択プロンプトが表示されるので、ここでは`ServiceBus Topic trigger`を選択します。  

```text
Use the up/down arrow keys to select a template:
Blob trigger
CosmosDB trigger
EventGrid trigger
EventHub trigger
HTTP trigger
Queue trigger
ServiceBus Queue trigger
ServiceBus Topic trigger
Timer Trigger
```

下記内容を指定します。  

- Function Name:`servicebus_topic_func01`
- Service Bus Topic Name:上記で作成したトピック名`MyTopic111`
- Service Bus Subscripton Name:上記で作成したサブスクリプション名`subscription01`
- Service Bus Connection:`ServiceBusConnection`

最終的に下記内容が出力されます。  

```text
Use the up/down arrow keys to select a template:Function Name: [servicebus_topic_trigger] servicebus_topic_func01
Service Bus Topic Name: [servicebustopicname] MyTopic111
Service Bus Subscripton Name: [servicebussubscriptionName] subscription01
Service Bus Connection: [ServiceBusConnectionString] ServiceBusConnection
Appending to c:\tmp\LocalFunctionSurviceBusTopicProj\function_app.py
The function "servicebus_topic_func01" was created successfully from the "ServiceBus Topic trigger" template.
```

Azure の関数アプリ`appsample111`に関数プロジェクトをデプロイします。  

```text
func azure functionapp publish appsample111
```

## メッセージをAzure Service Busトピックに送信する

メッセージをAzure Service Busトピックに送信するサンプルコードです。

```python
import json

from azure.servicebus import ServiceBusClient
from azure.servicebus import ServiceBusMessage
from azure.identity import DefaultAzureCredential

# Service Bus 名前空間
FULLY_QUALIFIED_NAMESPACE = "servicebus111.servicebus.windows.net"

# トピック名
TOPIC_NAME = "MyTopic111"

credential = DefaultAzureCredential()

def send_message():
    print("run() start")

    servicebus_client = ServiceBusClient(
        fully_qualified_namespace=FULLY_QUALIFIED_NAMESPACE,
        credential=credential,
        logging_enable=True)
    
    sender = servicebus_client.get_topic_sender(topic_name=TOPIC_NAME)

    send_param = {'param1':'value1'}
    
    message = ServiceBusMessage(body=json.dumps(send_param))

    # send the message to the topic
    sender.send_messages(message)

print("start")
send_message()
print("end")
```

👇 上記コードの実行後に、関数アプリがトピックを受信していることを確認できます。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708851/f9b57695-f762-2c95-6da6-c092c7b88af5.png)

## 👇関連記事

- [Azure Functions でPython関数を作成してデプロイする](https://docs.saurus12.com/python/azure_function_python)
- [ローカル開発環境で Azure SDK for Python を利用する](https://docs.saurus12.com/python/azure_sdk_python)

## 👇参考URL

- [Azure CLI を使用して Service Bus トピックとそのサブスクリプションを作成する](https://learn.microsoft.com/ja-jp/azure/service-bus-messaging/service-bus-tutorial-topics-subscriptions-cli)
- [アプリケーション設定の反映](https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-how-to-use-azure-function-app-settings?tabs=azure-cli#settings)
- [Azure Service Bus トピックへのメッセージ送信とトピックのサブスクリプションからのメッセージ受信 (Python)](https://learn.microsoft.com/ja-jp/azure/service-bus-messaging/service-bus-python-how-to-use-topics-subscriptions?tabs=passwordless)
- [Azure Functions の Azure Service Bus トリガー](https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-bindings-service-bus-trigger)
- [Azure Functions における Azure Service Bus のバインド](https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-identity-based-connections-tutorial-2)
- [App Service と Azure Functions でマネージド ID を使用する方法](https://learn.microsoft.com/ja-jp/azure/app-service/overview-managed-identity?tabs=cli%2Chttp)

[keywords]  
Azure Service Bus Topic Python

[Azure Service Bus Topic を Python で送受信する](https://docs.saurus12.com/azure/azure_function_servicebus_topic)

更新日:2024/02/02