Durable Functions の注意点
Durable Functions を試している際にちょっとハマったので、共有します。
※経緯などは自分のブログに書きましたが、Qiitaにもシンプルに注意点だけ投稿しておきます。
Azure Functionsの目玉ともいえる拡張機能、Durable Functionsについては以下を参照ください。
Azure Functions の 超イケてる Durable Functions を使ってみる
概要
Durable Functions では同一のストレージアカウント内に同じ関数名の関数を作ると衝突することがあるということです。
Durable Functionsではオーケストレーター関数やアクティビティ関数を呼び出し、関数間で情報をやり取りすることで複雑なフローを可能にしますが、複数の関数アプリで同一のストレージアカウントを使いまわすと、別アプリに同じ関数名の関数があると、別アプリの関数であるにもかかわらず衝突し、呼びたいほうの関数が呼べない、ということが起きてしまいます。
なぜ衝突するのか
Durable Functionsを使ったFunction Appを作成すると、ストレージアカウント内に「タスクハブ」が作成されます。
これは論理的なコンテナーで、同一のタスクハブに属した関数同士が情報のやりとりを行うことができるようになります。
参考:Durable Functions におけるタスク ハブ - Azure
そして、Durable Functionsでは、オーケストレーター関数やアクティビティ関数のコールを、このように関数名の文字列で行います。
var instanceId = await starter.StartNewAsync("SampleFunc", input);
そして、Durable Functionsを使ったアプリを何も考えずそのまま作ると、すべてデフォルトのタスクハブ名DurableFunctionsTaskHub
として作成されてしまいます。
ということで、必然的に同一タスクハブ内に同名の関数が存在すれば衝突してしまうというわけです。
手元で確認したところ、どうも競合する関数名のうち古いほうが呼ばれてしまうようでした。
対処法
①:別のストレージアカウントを使う
別のストレージアカウントを使えば、タスクハブは別のものになるので、衝突しなくなります。
②:タスクハブ名を明示的に指定する
同一のストレージアカウントを使いたい場合は、タスクハブ名を明示的に指定すれば、その名前になってくれます。host.json
に以下のように書けばOKです(Functions 2.xの場合)。
{
"version": "2.0",
"extensions": {
"durableTask": {
"hubName": "MyTaskHub"
}
}
}
なお、「デフォルトのタスクハブ名がアプリ名から決まるようにしてほしい」というissueも出ているようです。
Task hub name should default to the function app name · Issue #383 · Azure/azure-functions-durable-extension
まとめ
Durable Functions の良さは、本来複雑な実装・管理が必要な処理も、通常のプログラミングを行うかのように記述できる点です。
しかし、通常のプログラミングではあたりまえの「アプリや名前空間、クラスが異なれば同一のメソッド名を用いてもよい」という常識は、Durable Functionsでは通用しません。
内部の動作を知っていれば当然の動きですが、特に複雑な処理を作る場合などは、裏側の管理の仕組みなども意識しながら使わないといけませんね(これはDurableに限らずどんな開発でも当てはまる話)。
逆に、別アプリでもタスクハブが同じなら関数間で情報をやりとりできる、ということです。
関数名の競合にさえ気を付ければ、ここはむしろメリットにもなりえますね。
↓とのコメントをいただいたので、ここはやらないほうがよさそうです。
多分ですけど複数のFunction AppでTaskHubを共有すること自体だめだと思うので記事の最後の部分はいらないかなぁって思います
— かずき@スマブラはリンク (@okazuki) 2019年3月8日
Queueのメッセージを使って関数の動きとか色々してるはずなので、Queueが共有されると変な動きしそう