マイクロサービスパターン[実践的システムデザインのためのコード解説] impress top gearシリーズ
- 作者:Chris Richardson,長尾高弘,樽澤広亨
- 発売日: 2020/03/23
- メディア: Kindle版
この本を読むまでの経緯
- クリーンアーキテクチャを読んだ記事でも書いたように、仕事でマイクロサービスの導入検討(どの粒度でサービス化するか、など)を行っていて、自分があまりにも「Railsでモノリスを作る」以外の選択肢について疎いと感じていた
- これまた前のエントリにも書いたが、そんな中で上司の id:gohan_pan_gohan (何このはてなid....)もこの本を最近読んでいる旨を1on1にて話してくれて、自分も読むことにした
- 一方で「クリーンアーキテクチャ」に書かれているような内容が前提となることも聞いていたので、先にクリーンアーキテクチャを読んでいた
この本について
- 原著は「Microservices Patterns: With examples in Java」のタイトルで2018/11/27に出版されていて、日本語版は2020/3/23に出版された
- 著者のサイトである https://microservices.io/ を基にしながら、架空のフードデリバリーサービス( Uber Eatsっぽい感じ)の設計/実装を検討してくいく
- 「マイクロサービスにおける○○」がひたらすらの500ページ超のボリュームで語られていて、マイクロサービス設計/実装における勘所を体系的に学べる
感想
「マイクロサービスパターン」がおもしろすぎる。"自分が理解できるレベルの全然知らなかったこと"がめちゃくちゃ載っている。
— うちやま (@highwide) 2020年8月28日
いま見返すと「理解できる」(理解できるとは言ってない)くらいに捉えてもらったほうがよさそうではある(逃げ腰)
ただ、本当に笑っちゃうくらい知らないことが多かった。
たとえば: サーガについて
モノリスで実現できていたRDBMSのトランザクションをどうやってサービス分割後に担保するかというのは、読む前からの気になりどころだったのだが、これに対しては「サーガ」というテクニックが紹介される。(余談:redux-sagaのsagaってそういうこと...?)
サーガは、1つのトランザクションでやりたかった処理が複数のサービスに散らばってしまった場合に、サービスごとのトランザクションを1つの「サーガ」という風に捉え、仮に個々の処理が失敗した場合は個々のサービスで「補償トランザクション」を実行することでロールバックするような仕組みと理解している。このとき、これらの個々のトランザクションをコーディネイトする責務をどこに持たせるかによって「コレオグラフィ」と「オーケストレーション」という2種類の作り方ができる。ただし、サーガはACID特性のうちIsolation(分離性)はサポートできないので、Lockなどの対処手法(countermeasure)を用いていく必要がある。
...と、やろうとしていることは理解できる(というか、わりと泥臭くやらなきゃいけないんだなという思いを新たにする)のだけれども、聞き馴染みのないキーワードによってそのパターンが既に一般化されていることを知る...というのがこの本で学べるおもしろさだった。
たとえば: Transaction log tailingパターンについて
非同期メッセージングやその一種であるPubSub自体は業務でも使われているシーンを見ていたり、その概念を理解しているつもりだったが、Transaction log tailingパターンというものには驚いた。
この技術が解決したい問題は以下のようなものだ
- メッセージのPublisherは「メッセージのPublishと、そのサービスのためのデータ保存とを、1つのTransactionの中で行いたい」(=メッセージ送信とDBの保存の部分成功/失敗を許容したくない)ケースがある
- そのために、メッセージキューとしてDBに作成した「OUTBOX」というTABLEを利用することで、キューの更新とドメインモデルの保存をRDBMSトランザクションの中で行える、とうTransactional outboxパターン*1というものが存在する
- このパターンを利用した場合、メッセージブローカーへのパブリッシュ自体は、OUTBOXテーブルの情報を取得するコンポーネントが必要になる
- シンプルにやるならばOUTBOXテーブルにSELECTクエリでポーリングするコンポーネントを用意すればいいが、場合によってはDBへのポーリングするコストが無視できないことがある
- そこで、RDBMSが吐くトランザクションログ(コミットログ)をテーリングして、変更を検知し、メッセージブローカーへのパブリッシュを行う
画像は micorservices.io - transaction-log-tailing より
僕の直感からすると「ログ収集とかそういうレベルでなく、アプリケーションがRDMBSの吐くログに直接依存している...って大丈夫!?」って思ったりもしたのだが、世の中にはそれを実現するためのDebeziumやLinkedIn Databusといったツールが存在していることも紹介されている。
さらにこの技術と相性がいいのが「CQRS」であると紹介されていて「えっCQRSってこの文脈で出てくるの?」といった驚きもあった。
「マイクロサービス」と「分散システム」
正直に言うと、上に挙げた技術やその他本書で紹介されているテクニックは、自分の日常業務にすぐさま取り入れたいと思う類のものだけでなく「そこまでやるの?」と感じるようなものも少なくない。
ただ、これまで「マイクロサービス」という言葉を日常的に口にする中であんまり意識していなかったことだが、本書を通じて「Microservices」とは結局「分散システム」なのだということを肌身に感じることができた。「自分たちのWebサービスのためのマイクロサービスではそこまではやらなくていいでしょ」とコストパフォーマンスの天秤を眺めている傍らで、高度な分散システムに続く道のりが続いていることを意識できたのは、すごく良かったと思う。
その上で、この本のスタンスも「はじめに」で書かれている通り
本書はマイクロサービス宣言ではありません。本書は、パターンのコレクションを中心として構成されています。(中略)パターンのよいところは、ソリューションの利点を説明するだけでなく、ソリューションの欠点やソリューションをうまく実装するために対処しなければならない問題点なども明らかにするところです。
とあるように、読み手に「分散システム全部盛り」をいついかなるときも要求するものではない。
自分の当初のモチベーションを満たす上でも、現実の業務に当てはめるためのパターンを「API合成」「テスト」「デプロイ」「セキュリティ」等々の面から学ぶ事ができた。GraphQLやKubernetes/Istioといった業務に直結しそうな技術の詳細な紹介もあったりして、マイクロサービス時代のWebアプリケーション開発を総ざらいできる本、とも言うことができるかもしれない。
その他の雑感
- サンプルコードがJavaで、著者の自作フレームワークが登場しがちなので、せっかくの実装例は目が滑りがちだった...。いざ自分が実装するときには読み返すことになるかもしれない。
- 日本語版の出版は2020年だが、原著は2018年なので、紹介されているツールは既に別の技術に取って代われられているように思えることもあった。「マイクロサービス時代のWebアプリケーション開発を総ざらい」と上で書いたが、賞味期限が短い箇所もそれなりに多そう。
- 各パートごとに紹介されるツールのNetflix率の高さよ...。よく知られるchaosmonkyが"壊してまわる"のは、こんな分散システムだったのかなという思いを馳せた。
- (思い出して追記) クリーンアーキテクチャを先に読んでたおかげで、こういう学びもあってうれしかった
「クリーンアーキテクチャ」の次に「マイクロサービスパターン」を読み始めて「何か1つ修正したいときに、複数サービスを修正する必要があるのは設計が良くない」っていうのが閉鎖性共通の原則で説明できることがわかって、クラス/モジュールの話がサービスに適用できるじゃんとうれしくなった。
— うちやま (@highwide) 2020年8月21日