こんにちは、上坂(@takashiuesaka)です。
今日はEventHubsの話です。Azure Machine Learningをゴリゴリと触っている身として常々思うのはやはりデータがクラウド上に上がってこないことには何もできないなぁということです。そうなるとよく聞くストーリーは
EventHubs ・・・ StreamAnalytics ・・・ 永続化サービス ・・・ 分析
っていう流れな訳です。
が、この最初のEventHubsってやつがなかなか手強い。いや、違う、EventHubs自体はわかってしまえばそれほど難しくないです。とても良く出来た構成です。ただAzureの説明がものすごく難解なんです。
私はこの「Azure Event Hubsの概要」と「イベント ストリーム指向のシステムの台頭」をひたすら読みましたが、あまりにわかりにくい説明に心が折れそうになりました。
この2つのドキュメントを読み込んで、テストして、自分なりに把握できた内容を今日は自分のメモがてら書いておこうと思います。どこまで正確なのかは正直わかりませんがどなたかの参考になれば!
まず言葉の整理から。ドキュメントを見ると、次のような単語が出てきます。
- Publisher/Subscriber
- Producer/Consumer
- 発行者
- Broker
EventHubs っていうのは要するにイベントの貯蔵庫です。ある一定期間イベント(という名の文字列)を貯めこみます。EventHubsにイベントを投げるやつのことを
- Publisher
- Producer
- 発行者(Producerの訳)
と文脈で使い分けているようです。また、貯めこまれたイベントを受け取る側のことを
- Subsciber
- Consumer
と呼んでいます。これらは必ずPublisher/Subscriberのように対になるように使うのは英語の特徴みたいなもんなのでしょうね。
Brokerというのは"仲介者"を意味する一般的な用語です。メッセージング系でよく用いられるようですが、要するにEventHubsにように間に入ってうまいことやってくれるやつのことです。だからEventHubsも一種のBrokerなわけです。
まずは基本からいきましょう。まず格納するイベントとはなんでしょうか。正確に言うとバイナリにシリアライズされた何か、です。もっと簡単に言うとイベントとは文字列である、と言い切ってしまって良いと思います。格納できるサイズの制限が結構厳しいのでそこはドキュメント見て確認しましょう。
次に知っておきたいのはEventHubsに格納されたイベントは受信しても消えない、ということです。EventHubsサービスに対して~日間保持する、という設定を管理ポータルでしますが、その日数が経過しないとイベントは消えません。キューとはちょっと感覚が違いますね。
さて、EventHubsは内部にPartitionというのものを持ちます。これが物理的に何かなのかはわかりませんが、投入したメッセージは1~最大32(初期値は8)のPartitionのいずれかに格納されます。
どこのPartitionに格納するのかは投入側が(擬似的に)決めることもできますが、EventHubsに任せた方が良さそうです。そもそもなんでPartitionというものが必要なのか、というとそれは受信側で同時に複数のイベントを受信できるようにしたいからです。イベントは投入するより受信するほうがやることが多くて大変です。だから受信側は複数のクライアントで並列処理させたいわけです。(クライアントというのは自分で作ったプログラムかもしれませんし、StreamAnalyticsかもしれないわけです。)
だけど、イベントの格納先が1箇所しかないと接続が奪い合いになってしまいます。だから受信側のプログラムが接続する先が複数あったほうが都合が良いわけです。
つまりPartitionの数は、受信側で並列で動かすプログラムの数にダイレクトに影響があります。ここ重要ですね。そしてイベントを投入する側はどこのPartitionにイベントを(要するに文字列のことですが)投入するのかを基本的に決めないほうが良いわけは、投入されたイベントにPartition間で偏りが出てしまうからです。というのも、1つのPartitionからイベントを受信できるのは1つの受信用クライアントだけだからです。折角並列処理させてもそれじゃあ全く意味ないですよね。
でもどうしてもある特定のイベントはこのPartitionに入れたい!という要件があった場合はどうしましょうか。結論、無理みたいです。できません。でも、どこかのPartitionにだけ特定のイベントを投入する、ということはできます。PartitionKeyというものを使います。
イベントを投げる時、PartitionKeyに任意の文字列をセットします。別のイベントを投げる時にもPartitionKeyにセットする文字列が同じなら、同じPartitionにイベントが格納されることは保証されます。でも、どこかはわからないのです。
ではPartitionKeyに何もセットしないとどうなるかというと、Partitionに対して順番にイベントが格納されます。ドキュメントではラウンドロビンと表現されています。実際にイベントを投げてみるとわかるのです、本当に順番に格納されるわけじゃないようなので、順番に依存した実装はしないようにしましょう。
さて、イベントの投入についてはこんな感じでしょうか。イベントの受信は次回にしましょう。