マイクロサービスな世界になったとき、自分たちのサービスは動いているけれど、依存しているとあるサービスがダウンしている(常にエラーを返してしまう)、といった場合にどうするか。
ひとつは、自分たちのサービスも一緒にダウンする。 これは簡単だけれども、自分たちのサービスが提供できなくなってしまう。つまり、また別のサービスが自分たちのサービスに依存している場合に、彼らにもエラーを返してしまう。例えば、すべてのサービスが同じアプローチを取っていると、たった一つのサービスが何らかの理由で一時的にエラーを返してしまうような状態になると、全体としてエラーになってしまう。 各サービスが独立して動けるほうがよいはずなので、これはちょっと困る。
もうひとつは、自分たちのサービスはダウンせず、引き続き機能を提供する。これはなかなか難しい。
何が難しいかというと、単純に自分たちのサービスを継続する、ということはできず、あるサービスからの返答が無いために、欠けてしまうデータ、欠けてしまう処理があるはずで、それをどう補うかを考える必要があることが難しい。
例えば、ECサイトの商品レビューをイメージしたとき、レビュー投稿のためには、ユーザサービス(認証認可サービス)を使い認証認可して、商品サービスを使って商品が正しく存在することを確認して、自分たち(レビューサービス)で初めてレビューのデータを保存できるような形になるんじゃないかなと思う。他にもありそうだけどいったん。
ここで、ユーザがいよいよ投稿するぞ!というタイミングで、商品サービスがダウンしてしまった場合、商品が存在するか判定ができないので、レビューサービスとしてはどうするかの判断が迫られる。
- エラーを返す
- 商品サービスがダウンする可能性が低い、短時間のダウンならこれでもいいかもしれない。
- 「一時的なシステムエラーです。あとでお試しください。」
- 下書きとして保存する
- レビューサービスとして、下書き機能を提供し、本投稿が出来なかった変わりに下書きに入れておきました。
- その機能がなければ作る手間があるし、機能が増えることでプロダクトは複雑になる。
- 「一時的なシステムエラーです。下書きに保存しました。」
- イベントを発行して、非同期でリトライする
- 反映されるまで時間がかかる場合があります、というようなもの。
- 全部後回しにできるので、ユーザ体験上はいいかもしれない。
- でもデータは保存されていないので、投稿したレビュー一覧、とかで見れない。
- 何食わぬ顔で保存する
- 投稿されたデータを完全に信頼することになる。
- 未発表の商品IDが指定されても保存できてしまうのが問題か…?
- レビューサービス上で商品の存在可否をキャッシュ
- キャッシュしてあればそれを使う、なければリクエスト。
- キャッシュと実態の不整合は起こりそうではある。
- ハイブリッド案
- レビューデータにis_validatedのようなフィールドをもたせる。
- バリデーションが出来ても出来なくてもデータはとりあえず保存する。
- バリデーションが出来ていなければイベントであとでバリデーションをする。
- バリデーションNGだったらデータを消す(非表示状態にする)
- VS 実装の手間、コスト
つまるところ、サービス単位では基本的にはダウンさせない、プロダクトとして通して見たときに何が出来ないとエラーになるのかその時の補填をどうするか、を考える必要がありそう(それはそう、とここまで書いておいて思った)
冒頭でマイクロサービス〜とかって話にしたけれど、よく考えれば、外部のAPIを使っているようなプロダクト、サービスは全部いっしょなんだよな。そのAPIに何かしらの理由で疎通できなくなることは十分に考えられるので、そのとき自分達が何をするか、どうできるか、と。
なんかここ、こういうパターンでサービス提供は継続できますよ、みたいな一般化ができそうな気もするけれどどうなんだろう??
あとそのまんまのワードでググると、Webフロントエンドないしブラウザ系の話と、サービス間の話と、2つの世界が出てくる。どちらも違う話のように見えるけれど、本質的には、ユーザに価値を提供するためにどうするか、で一緒っぽい。