Temporalというマイクロサービスオーケストレーションについて

2022-05-08

Employee performance vector created by vectorjuice - www.freepik.com

#はじめに

最近はワークフローをどう扱うかについて、調査を進めています。
その中で、興味深いオープンソースソフトウェアを紹介したいと思います。
Temporalというマイクロサービスオーケストレーションプラットフォームです。

#Temporalとは

Temporal is a scalable and reliable runtime for Reentrant Processes called Temporal Workflow Executions.

出典: Introduction to Temporal | Temporal Documentation

Temporal is a microservice orchestration platform which enables developers to build scalable applications without sacrificing productivity or reliability. Temporal server executes units of application logic, Workflows, in a resilient manner that automatically handles intermittent failures, and retries failed operations.

出典: temporal - Github

Reentrant Processesとありますが、再入可能ということです。
Wikipediaのリエントラントが参考になります。情報処理の教科書でもよくでてくる単語ですが、おおよそ単一プログラムにおける再入可能を説明していることが多いと思います。
近年では、マイクロサービスやネットワークを越えて複数のタスクを一連のワークフローの中で実行することが当たり前になりましたが、こうした環境における再入可能なプログラムを実現するのがTemporalだと理解しています。

どうやって実現しているかを最もわかりやすく説明してくれている動画があります。動画の途中から再生します。

https://www.youtube.com/watch?v=bjlFculKheI&t=1910s

#ワークフローとマイクロサービスにおける課題

先に紹介したYoutube動画では送金を題材に説明されています。
送金元口座から送金先口座に金額を指定して送金するというものです。
これを一つのワークフローとして考えると、2つのステップが存在します。

  1. 送金元口座から指定された金額分を減らす。
  2. 送金先口座へ指定された金額分を増やす。

このワークフローを信頼性の高く成功させるためには、どうような考慮が必要でしょうか。
Temporalを使わない場合を考えてみます。送金はマイクロサービスを通じて行うこととし、ワークフローのなかでは、トランザクションセーフではないこととします。

信頼性を高めるには、ステップ1,2が失敗する場合を考慮して、ワークフローロジックの中にリトライロジックを入れるでしょう。
また、ワークフローの実行プロセス自体がダウンした時を考慮して、ワークフロー自体をリトライするロジックをワークフローの呼び出し元に入れるでしょう。こう考えるとリトライは呼び出し元をたどって無限に入れないといけなくなってしまいます。

これを解決する方法の一つとして、メッセージングシステムを使うことができます。メッセージングシステムを使うと、処理が成功したらメッセージを消費し、失敗した場合はメッセージを消費しないことにより、再度同じメッセージを受信してリトライを実現することができます。
メッセージを受信する側では、受信したメッセージ処理のべき等性を担保する必要があります。
べき等性を担保するために、一般的にDBのトランザクションを使ったりして、2重処理を防ぎます。
これは、マイクロサービスが増えていくと至るところに同じようなべき等性を担保する仕組みが必要になります。

更に、ワークフロー自体がリトライされた時を考慮して、ステップ1,2が実行済みであるかを判定して、すでに実行済みであれば処理をスキップするか、結果情報だけを保存しておくように状態管理をするかもしれません。あるいは、もし、ステップ1,2自体の操作がべき等性を担保していれば、同じ情報(おそらくRequestIDのようなキー)を指定して前回成功時の結果情報を取り出すことができます。ただし、このRequestIDはどこかに保存しておかなければなりません。

途中でキャンセルしたい場合はどうでしょう。マイクロサービスアーキテクチャではSagaパターンで実装するかもしれません。

最後に、失敗してシステムが自動的にリトライ出来なかった場合、手動の運用対処をすることになるかもしれません。

たった一つのマイクロサービスを呼び出すだけでも、非常に考慮することが沢山あります。

こうした実装は煩雑で複雑になりがちで、テストをすることも大変困難です。

Youtube動画をみるとわかるのですが、Temporalは、こうしたマイクロサービスにおけるワークフローの課題を扱ってくれます。

この他にも、タイムアウトや、分散アーキテクチャシステムでのスケーラビリティや、他にもいろんな課題があるのですが、長くなるので割愛します。

#類似のサービスとは何が違うのか

Temporalと同等のサービスは思いつきませんが、私がワークフローの課題をどうやって解決するかをこれまで考えてきたなかで検討したものを挙げて比較してみたいと思います。

Apache Airflowは、データエンジニアリングパイプライン用のオープンソースのワークフロー管理プラットフォーム

とあるように同じワークフローでもユースケースが異なる。よりAirflowはデータパイプライン用途の印象が強いが、Temporalのほうはビジネスワークフローも書けるし、もちろんデータパイプラインも書くことができるだろう。
有向非巡回グラフでは、ループするようなワークフローを定義することはできないので本質的に異なると思われる。

このディスカッションは、AWS Step FunctionsとTemporalの違いを説明しています。DSLとコードでワークフローを実現する違いについて言及されています。Sagaパターンについても言及されています。コードで実現するほうが圧倒的にシンプルに書けるのがすごいです。

これはすでにワークフローとマイクロサービスにおける課題で述べたが、メッセージシステムを使ったリトライトリガーの実現をTemporalに委ねることができます。
また、ワークフローの状態管理もTemporalに委ねることができます。

実際にOAuth2のコード認可のフローを実装してみました。OAuth2ではstateという一時的なトークンを発行・検証することでCSRF攻撃を防ぐことが推奨されていますが、Temporalのワークフローにstateの状態を持たせることができるので、このためだけにDBを用意する必要なく実現できます。

これまでは、このためだけにKVSなどDBを用いることありましたが、Temporalを使うとナンセンスに思えてきます。実際にはTemporalはDBに依存しますが。

参考:https://auth0.com/docs/secure/attack-protection/state-parameters

#注意点

数個のワークフローを実装してみて、注意しないといけないなと感じた点です。

#まとめ

個人的には、Temporalは、ReactやVue.jsと同じくらいインパクトがあり、特にミッションクリティカルな要求があるシステムでは採用していく企業は増えていくと思います。シリコンバレーのテック企業では採用されている事例がいくつか掲載されています。日本の企業で採用しているのは、まだ聞いたことがないですが。
Temporalは、サンプルコードやドキュメントが充実しており、お気に入りになりました。