kakakakakku blog

Weekly Tech Blog: Keep on Learning!

マイクロサービス化を目指すなら移行パターンを学ぼう /「モノリスからマイクロサービスへ」を読んだ

2020年12月に出版された「モノリスからマイクロサービスへ」を読んだ.本書はタイトルの通り「マイクロサービス移行」に関連するトピックにフォーカスしている.マイクロサービスを学ぶならこの本!とよく紹介している「マイクロサービスアーキテクチャ」の著者 Sam Newman の続編となる.原著「Monolith To Microservices」は,2019年12月に出版されている.

僕自身は技術講師として「マイクロサービス」に関連した研修を担当していることもあり,本書は絶対に読もう!と楽しみにしていた(原著は読もう読もうと積読していた😇).今回は本書の翻訳を担当された島田さん (@snoozer05) とレビューを担当されたこまさん(@koma_koma_d) からご連絡をいただき,本書を献本していただいた.本当にありがとうございます!

モノリスからマイクロサービスへ ―モノリスを進化させる実践移行ガイド

モノリスからマイクロサービスへ ―モノリスを進化させる実践移行ガイド

  • 作者:Sam Newman
  • 発売日: 2020/12/26
  • メディア: 単行本(ソフトカバー)

目次

マイクロサービス化を目指すときに頭を悩ますトピックの1つはやはり「移行」だと思う.マイクロサービスを新規構築することも難しいけど,歴史のあるモノリシックアプリケーションを分割して本番障害にも気を付けながら移行することにはまた別の難しさがある.本書は以下に載せた目次からもわかる通り,本当に「移行」に関連するトピックにフォーカスしている.マイクロサービス化を目指すなら必読と言えそう!

  • 1章「必要十分なマイクロサービス」
    • 1.1 マイクロサービスとは
    • 1.2 モノリス
    • 1.3 結合と凝集
    • 1.4 必要十分なドメイン駆動設計
    • 1.5 この章のまとめ
  • 2章「移行を計画する」
    • 2.1 目的を理解する
    • 2.2 マイクロサービスを選択する理由
    • 2.3 マイクロサービスが悪いアイデアのとき
    • 2.4 トレードオフ
    • 2.5 みんなを連れていく
    • 2.6 組織を変革する
    • 2.7 段階的に移行していくことの重要性
    • 2.8 変更のコスト
    • 2.9 どこから始めればよいか?
    • 2.10 ドメイン駆動設計
    • 2.11 組み合わせモデル
    • 2.12 チームを再編成する
    • 2.13 うまくいっているかどうかを分かるには?
    • 2.14 この章のまとめ
  • 3章「モノリスを分割する」
    • 3.1 モノリスを変更すべきかどうか
    • 3.2 移行パターン
    • 3.3 パターン:ストラングラーアプリケーション
    • 3.4 機能を移行しながら振る舞いを変える
    • 3.5 パターン:UI 合成
    • 3.6 パターン:抽象化によるブランチ
    • 3.7 パターン:同時実行
    • 3.8 パターン:デコレーティングコラボレーター
    • 3.9 パターン:変更データキャプチャ
    • 3.10 この章のまとめ
  • 4章「データベースを分割する」
    • 4.1 パターン:共有データベース
    • 4.2 しかし、できない!
    • 4.3 パターン:データベースビュー
    • 4.4 パターン:データベースをラップするサービス
    • 4.5 パターン:サービスのインターフェイスとしてのデータベース
    • 4.6 所有権を移す
    • 4.7 データ同期
    • 4.8 パターン:アプリケーションでのデータ同期
    • 4.9 パターン:トレーサー書き込み
    • 4.10 データベースを分割する
    • 4.11 データベースとコードのどちらを最初に分割するか
    • 4.12 スキーマ分割の例
    • 4.13 パターン:テーブルの分割
    • 4.14 パターン:外部キーのコードへの移動
    • 4.15 トランザクション
    • 4.16 サーガ
    • 4.17 この章のまとめ
  • 5章「成長の痛み」
    • 5.1 サービスが増えれば痛みも増える
    • 5.2 所有権のスケール
    • 5.3 破壊的変更
    • 5.4 レポーティング
    • 5.5 監視とトラブルシューティング
    • 5.6 開発者体験
    • 5.7 あまりにも多くのものを実行している
    • 5.8 エンドツーエンドテスト
    • 5.9 全体最適と局所最適
    • 5.10 堅牢性と回復性
    • 5.11 孤児サービス
    • 5.12 この章のまとめ
  • 6章「終わりに」
  • 付録 A「パターン一覧」

全体的に読みやすく,気になる誤植もなかった.1点あるとすれば「分割」「分解」という言葉が混在して使われていて,意図的に使い分けているのか,原著の英単語に依存しているのか,判断できなかった.今回の書評記事においては,引用箇所を除いて「分割」に統一する.

www.oreilly.co.jp

マインドセット

本書を読む前に「2章 : 移行を計画する (P36)」に載っている以下の文章を読んでおくと良いと思う.何となく本書を読んでしまうと「なぜ移行パターンがこんなにあるのだろう?」「なぜここまで検討する必要があるのだろう?」「モノリシックアプリケーションに戻るべきでは?」と感じる場面があるかもしれない.いや誰しも感じるだろう.それほどに「マイクロサービス移行」に関連するトピックを深く学べるため,モチベーションを高く本書を読み進めていくことが重要だと思う.

マイクロサービスを使う理由を明確に持っていないことの問題点はさまざまだ。マイクロサービス化は、そのために投じる人員や費用という直接的な意味でも、フィーチャーの追加よりも移行作業を優先するという意味でも、多額な投資が必要になる。これは、移行のメリットを実感するまでに時間がかかるという事実によって、さらに状況を複雑にする。特として、それは移行に1年以上かけているにもかかわらず、なぜそれを始めたのかを思い出せなくなってしまうという状況へとつながってしまう。これはサンクコストの錯誤ではない。

達成したいことは何か?

「2章 : 移行を計画する」には他にも重要な内容が多く載っている.まず冒頭に「3つの重要な質問」が載っている.これは著者がマイクロサービス化を支援するときに実際に使っている質問とのことで,すぐに試せる.アジャイル開発でよく出てくる「エレベーターピッチ」「完了の定義」にも似ていて,マイクロサービス化を目指すメンバー間で認識を合わせておくことが重要だと思う.

  • ✅ 達成したいことは何か?
  • ✅ マイクロサービスの他に代替案はなかったか?
  • ✅ どうすれば移行がうまくいってるか分かるだろうか?

次に「マイクロサービスを選択する理由」「マイクロサービスが悪いアイデアのとき」という解説があり,特に「悪いアイデアのとき」は知っておくと良さそう.特に「サービス境界」を明確に見極められなかったり,プロダクトの需要を探るために多くのアイデアを試行錯誤しているフェーズのスタートアップではマイクロサービス自体が不適切になる可能性もある.

  • 😐 不明瞭なドメイン
  • 😐 スタートアップ
  • 😐 顧客の環境にインストールして管理するソフトウェア
  • 😐 もっともな理由を持たないとき

個人的には以下の文章には ( ゚д゚)ハッ! と気付かされた.過去の経験もあり「移行」こそ難しいと感じていたけど,あくまでこれは「技術的(設計思想的)な観点」「サービス継続的な観点」で考えていた.もし「適切にサービス境界を見極めて分割できるか」という観点で考えるとモノリシックアプリケーションでドメインに精通している方が良さそう.気付けて良かった!

システムを早々にマイクロサービスに分解すると、特にそのドメインに慣れていない場合には、コストがかさんでしまうことがある。多くの点で、既存のコードベースをマイクロサービスに分解することは、最初からマイクロサービスに向かおうとするよりもはるかに簡単だ。

組み合わせモデル

さらに「2章 : 移行を計画する」を読み進めていくと「どこから始めればよいか?」という内容も出てくる.「ドメイン駆動設計」を使うことに前提に「イベントストーミング」でドメインモデルを洗い出したり,ドメイン関係図を作って依存の少ないサービスから分割したり,Music Corp という題材で学べる.誰しも「影響が少ないサービスから分割する」と考えると思うけど,本書に以下のように書いてあって,本質を見失わずにマイクロサービス化を目指す難しさを再認識できた.そこで最終的には「バランス」となり「組み合わせモデル」も紹介されている.「分解しやすさ」「分解による利益」の2軸でマッピングし,どちらも高いサービスを「分解の良い候補」に決める.

しかし、市場投入時間を短縮することが目標で、請求書機能がほとんど変更されない機能である場合には、請求書機能の抽出は時間の使い方として適していないかもしれない。したがって、何が簡単で何が難しいかという視点と、マイクロサービス分割がもたらすメリットという視点を組み合わせる必要がある。

関連する内容は前に紹介したブログ「How to break a Monolith into Microservices」にも載っている.合わせて読んでもらえると良さそう!

kakakakakku.hatenablog.com

また本書で紹介されていた「イベントストーミング」も気になる.Leanpub で購入できる「Introducing EventStorming」を読んでみよう.

leanpub.com

パターン一覧

「3章 : モノリスを分割する」からはマイクロサービス化に使える「移行パターン」の話が続く.その前に最後に載っている「付録 A : パターン一覧」を見ておくと良いと思う.本書で紹介されているパターン一覧をザッと確認できる.マイクロサービス移行に使えるテクニックに「パターン」として名前が付いていることに価値がある.特に以下は印象に残っている.

  • ストラングラーアプリケーション (Strangler fig application)
  • UI 合成 (UI composition)
  • 抽象化によるブランチ (Branch by abstraction, BBA)
  • 同時実行 (Parallel run)
  • デコレーティングコラボレーター (Decorating collaborator)
  • データベースをラップするサービス (Database wrapping service)
  • トレーサー書き込み (Tracer write)
  • 複数スキーマストレージ (Multischema storage)
  • 外部キーのコードへの移動 (Move foreign-key relationship to code)

なお,移行以外に「マイクロサービス」に関連するパターンは「A pattern language for microservices」に多く載っている.特に関係性まで整理されていて素晴らしい.何度も何度も見直している.

microservices.io

ストラングラーアプリケーション (Strangler fig application)

「ストラングラーアプリケーション」はよく知られていると思う.2019年に名称が「Strangler」から「Strangler Fig Application」に変更された経緯もあり,本書でも「ストラングラーアプリケーション」と表記されている.イチジクの木の特性を比喩にして「古いサービスと新しいサービスを共存させつつ置き換えていく」パターンと言える.本書では「ストラングラーアプリケーション」だけで約20ページもあり,詳細に解説されている.図解もあってわかりやすい.

martinfowler.com

抽象化によるブランチ (Branch by abstraction, BBA)

「ストラングラーアプリケーション」に関連して,もし既存システムの中で参照依存の多いサービスを置き換える場合は「抽象化によるブランチ (Branch by abstraction, BBA)」が使える.このパターンは Martin Fowler のサイトにも載っていたのに今まで知らなかった.「抽象化」は英語だと「Abstraction」になり,以下のステップで構成されている.古い実装と新しい実装を混在できるため,新しい実装を進める Git ブランチが長い期間残り続けることもなく,どんどんと master (main) に merge できる.よって「トランクベース開発」とも相性が良いと言える.本書には「抽象化によるブランチ」のわかりやすい図解もある.

  1. 置き換える機能の抽象を作る
  2. 作成した抽象を使用するように既存機能のクライアントを変更する
  3. 機能を改良した抽象の実装を新たに作る(この新しい実装が新しいマイクロサービスを呼び出す)
  4. 新しい実装を使用するように抽象を切り替える
  5. 抽象を後始末し古い実装を削除する

martinfowler.com

同時実行 (Parallel run)

「ストラングラーアプリケーション」「抽象化によるブランチ」では,新しい実装を試して問題があれば切り戻すこともできるけど,よりハイリスクなサービスでは「同時実行 (Parallel run)」が使える.このパターンは古い実装と新しい実装をどちらも並行で実行して,結果を比較する(信頼する結果は古い実装).実装コストやパフォーマンス劣化などは気になるけど,本番環境で長い期間検証し続けられるという意味では使えそうな場面もありそう.他には「5% のみ」など,部分的にトラフィックを切り替えるなら「カナリアリリース」も使える.このように「同時実行」「カナリアリリース」「ダークローンチ」などをまとめた「プログレッシブデリバリー」という最近よく聞く言葉まで紹介されていて良かった.

なお「ストラングラーアプリケーション」「カナリアリリース」を組み合わせた具体的な移行例としては,AWS Summit New York の資料「Migrating monolithic applications with the strangler pattern」が参考になるので載せておく.

www.slideshare.net

データベースを分割するパターン

本書で存在感のある章は「4章 : データベースを分割する」かもしれない.移行の中でも難しく,モノリシックアプリケーションの歴史的な背景(技術的負債も含む)により分割しにくいことも多いと思う.本書では「データベース」に関連するトピックだけで約80ページも解説されている.研修でも「どうやってデータベースを分割すれば良いか?」「どうやって RDB から NoSQL に置き換えれば良いか?」という質問がある.今までに読んだ資料の中では「Managing Data in Microservices」は特に参考になるので載せておく.

www.slideshare.net

本書では「データベースを分割せずに工夫するパターン」「データベースを分割するパターン」が紹介されている.現実的にデータベースを分割できない場面もあるため,例えば「データベースをラップするサービス (Database wrapping service)」を使って,アプリケーションからデータベースを直接参照させずにサービス経由にするパターンがある.本書には「権限アプリケーションデータ」の例が載っていて参考になった.

他には「外部キーのコードへの移動 (Move foreign-key relationship to code)」もよく話題になるトピックだと思う.簡単に言えば,外部参照でテーブル同士が関連しているときに,データベースを直接参照するのではなく,アプリケーション側で API を使うように変更する.レイテンシーは気になるけど,要件次第ではあるし,そもそも「API 経由でデータを取得する」という実装に変化できることには大きい価値があると思う.特に JOIN に依存している場合など.

サーガ (Saga)

「4章 : データベースを分割する」の最後には「分散トランザクション」としてよく知られている「サーガ (Saga)」の解説が載っている.非同期的に整合性を取るようにトランザクションを実装しつつ,障害発生時には,再試行をしながら処理を継続する「前方回復」と,障害を元に戻す「後方回復」から選択できる.戻す場合は「補償トランザクション」と呼ばれる処理を実行する.

また「サーガ」には,コーディネーターを使う「オーケストレーションベースのサーガ」と運用責任を分散した「コレオグラフィベースのサーガ」の紹介があり,どちらも詳細に解説されている.また microservices.io も合わせて読んでおくと良いと思う.

microservices.io

本書に載っていた以下の表現は秀逸だった.「指揮と統制」「信頼と検証」!研修でも使えそう!

オーケストレーションベースのサーガが指揮と統制のアーキテクチャなら、コレオグラフィベースのサーガは信頼と検証のアーキテクチャだ。

まとめ

「モノリスからマイクロサービスへ」を読んだ.素晴らしかった!繰り返し読み直すことになりそう.本書はタイトルの通り「マイクロサービス移行」に関連するトピックにフォーカスしている.トピックが狭すぎると感じるかもしれないけど,それほどにマイクロサービス化を目指すチームにとって難しいトピックだし,指針となるパターンが1冊の本にまとまっていて,さらに日本語で読めることに価値がある.

本書で「パターン」を学んで,マイクロサービス化に成功した企業の事例などと組み合わせれば,今からマイクロサービス化に挑戦するチームに役立つと思う.個人的にもマイクロサービスに関連する研修で紹介できる内容が多くあった.

マイクロサービス化を目指すなら必読の1冊!読むべし!

モノリスからマイクロサービスへ ―モノリスを進化させる実践移行ガイド

モノリスからマイクロサービスへ ―モノリスを進化させる実践移行ガイド

  • 作者:Sam Newman
  • 発売日: 2020/12/26
  • メディア: 単行本(ソフトカバー)