Alternative Architecture DOJO

オルターブースのクラウドネイティブ特化型ブログです。

IoT HubからCosmos DBに直接データを送れるようになりました(パブリックプレビュー)

こんにちは、先日娘が「ルミエールでみるみるみるみーるの飴買って!」というので何のことかと思ったらミルキーのことでした。「ミルキーはママの味」と言いたかったようですがこれが通じた妻は凄いと思いました。

本記事はInfocom Advent Calendar 2022の9日目の記事です。弊社も今年春にインフォコムグループになりましたので参加してみました。

さて、先日、以下の通りIoT HubからCosmos DBへデータを送るカスタムエンドポイントがパブリックプレビューになったとの発表がありました。

azure.microsoft.com

これはIoT番長としては注目せざるを得ない機能ですね!早速触ってみたので紹介したいと思います。

IoT HubとCosmos DB

IoTの世界では、多くのデバイス(センサー)を設置し、そこから上がってきた大量のデータを保存・分析するということがよく行われます。この時、データを保存する先には以下の点が求められます。

  • 大量の同時接続で並列に送られてくる大量のデータ(個々のデータは小さいが同時接続数と書き込み頻度が多い)を高スループット・低レイテンシーで保存できる
  • 分析基盤からいい感じに参照できる

AzureではCosmos DBがこの用途には最適で、実際よく使われます。Cosmos DBに入れた後の分析は、例えばAzure Synapse Link for Azure Cosmos DBを使ってAzure Synapse Analyticsで行ったりします。

また、デバイスからデータを受け取るクラウド側の入り口(クラウドゲートウェイ)に必要とされる機能としては、代表的なところでは以下のようなものが挙げられます。

  • デバイスを管理し、接続時に認証する
  • 接続したデバイスからMQTTやHTTPなどでデータを受信する
  • 受信したデータを各種サービスにルーティングする

AzureではIoT Hubがクラウドゲートウェイとして使われることが多いです。

この2つを用いる場合、これまではIoT Hubに届いたデータをCosmos DBに送り込むには以下のような方法で行っていました。

いずれの方法も、届いたデータを保存したいだけなのに追加の構成や開発が必要なのはちょっとな・・・という気持ちは否定できませんでした。
そんなところにやってきたのが今回のアップデートです。直接送れるとか最高かよ!ということで早速試してみました。

やってみた

では早速試してみましょう。何かデバイスを用意してください・・・と言われても一般のご家庭にIoT Hubに繋がるデバイスはないでしょうから、ここではデバイスの代わりに公式のSDKに含まれているサンプルプログラムを使います。

gitからcloneして、サンプルプログラムをビルドします。

% git clone https://github.com/Azure/azure-iot-sdk-csharp.git
% cd azure-iot-sdk-csharp/iothub/device/samples/getting\ started/SimulatedDevice
% dotnet build

とりあえずIoT Hubにデータが送れることを確認しましょう。IoT Hubに、対称キーで接続するデバイス「test1」を登録し、プライマリ接続文字列を取得します。

デバイスの登録とプライマリ接続文字列の取得

ビルドしたサンプルプログラムに、取得した接続文字列を引数として渡して起動します。dotnetコマンドで起動するプログラムに引数を渡すときは、以下のように--のあとに入力します。

dotnet run -- -c "HostName=xxxxxxxxxx.azure-devices.net;DeviceId=test1;SharedAccessKey=xxxxxxxxxxxxxxxxxxxxxxxx"

実際に起動すると以下の画面キャプチャのようになります。このサンプルプログラムは停止するまでランダムな温度と気温のデータを送り続けますので、適当なところでCtrl + C を押して停止します。

サンプルプログラムの実行

データが正しく届いているか、ポータルからIoT Hubのメトリックスを見てみましょう。以下のようにメッセージ数が増えていれば正しく届いています。

IoT Hubのメトリック

さて、それではここからが本番です。
まずは保存先のCosmos DBを準備します。アカウント(SQL API)を作成し、データベースとコンテナを作成します。この時、パーティションキーは/partitionKeyとしておきます。

続いてIoT Hubのメッセージルーティングを設定していきます。「メッセージルーティング」から「追加」を押します。

メッセージルーティングの追加(1)

ルートの追加画面で、「エンドポイントの追加」で「Cosmos DB(preview)」を選択します。

メッセージルーティングの追加(2)

エンドポイント追加画面で、先ほど作成したCosmos DBのアカウント/データベース/コンテナを選択します。
「Generate a synthetic partition key for message」はデフォルトのままにします。
IoT HubからCosmos DBへの接続はマネージドIDも利用できますが、今回はデフォルトのキーベースでの接続のままにします。

メッセージルーティングの追加(3)

「作成」を押してエンドポイントを作成すると、先ほどのルート追加画面に戻ってきます。データソースは「デバイステレメトリのメッセージ」を選択し、ルーティングクエリは「true」(全てのデータをルーティングする)として保存します。

メッセージルーティングの追加(4)

これで設定は完了です。再度先ほどのサンプルプログラムを起動してデータを送信し、ポータルの「Cosmos DB>データエクスプローラー」でデータが届いているか確認してみましょう。

Cosmos DBにデータが届いている

無事届いていますね!
先ほどエンドポイントの追加画面でSynthetic Partition Key(合成パーティションキー)のテンプレートを{deviceid}-{YYYY}-{MM}としたので、パーティションキーにはtest1-2022-12(デバイスIDがtest1、実行したのが2022年12月)が入っています。デバイス側でデータ送信時に意識しないでも、エンドポイントの設定だけでCosmos DBのパーティショニングをいい感じに行えるのは便利ですね。

まとめ

今回はパブリックプレビューになった、IoT HubのCosmos DBへのカスタムエンドポイントを試してみました。非常に簡単にデータを送ることができ、とても便利そうでした!
もちろんこれまでのStream AnalyticsやFunctionsを用いる手法にもそれぞれ利点はありますが、単に届いたデータをそのままCosmos DBに保存したいという場合には強力な機能であると感じました。皆さんも是非試して頂ければと思います。

皆様のお役に立てば幸いです。