ScholarPackは、Strangler Fig Pattern (絞め殺しの木パターン) を使用してモノリスバックエンドから移行した。彼らは、顧客のニーズをターゲットにするために段階的な開発と継続的デリバリーを適用し、その間に、モノリスを絞め殺した。
Gareth Thomas氏は、Lean Agile Exchange 2020で、トラフィックの多いモノリスをマイクロサービスに移行することについて話した。
Thomas氏が説明したように、絞め殺しの木パターンがうまく機能することを可能にした重要な決定は、アプローチの順序だった:
プロジェクトが開始されたとき、プロダクションのFlaskアプリケーション (Zopeの代わりに選択されたフレームワーク) を作成した経験はありませんでした。最初にFlaskでグリーンフィールドプロジェクトを作成することが決定されました。これは、RestAPIに面した顧客です。これにより、既存の製品を変更するリスクなしに、デプロイメントとアーキテクチャに関する多数の問題を解決することができました。
これと並行して、「Wrapper」と呼ばれるものを開発しました。この境界サービスは現在、すべての顧客トラフィックとバックエンドサービスの間に位置しています。これにより、ユーザーからの変更を抽象化できます。Wrapperは透過的です。
Zopeから何も移動せずにWrapperを配置することで、内部サービス間のルーティングを解決する前に、すべてのユーザセッションとルーティングタイプの問題を解決できた。ドメイン名をScholarPackの顧客と連携する方法により、ドメイン名を小さなブロックでこの新しいサービスに移動することもできた。
その時点から、移行はニーズベースのアプローチに従っている、とThomas氏は述べた:
モジュールは、使用法ではなく、必要な変更に基づいて選択されます。私たちはZopeサーバの実行を維持することに非常に長けており、リスクの大部分はコードベースの変更に起因します。したがって、重要な機能は、モジュールを移行してから追加することで実行されます。すべての新しいモジュールまたは広範な新機能はFlaskで実行されます。Zopeはまだインフラストラクチャ内に存在しますが、現在はゆっくりと変化しています。
実行中のZopeモジュールの安定性により、移行を加速するためのビジネス上のニーズは限られている。Thomas氏によると、Zopeコードベース内での作業はリスクをもたらすが、その逆も当てはまる。Zopeコードは戦闘テスト済みで安定している。Zopeを削除する以外に実質的なメリットがないように安定した機能を書き直すと、バグや機能が失われるリスクが高まり、収益を生み出す作業からリソースが奪われる。
InfoQは、マイクロサービスへの移行についてGareth Thomas氏にインタビューした。
InfoQ: ScholarPackがモノリスバックエンドから移行することを決定した理由は何でしょうか?
Gareth Thomas氏: ScholarPackの元のバージョンは、Zopeと呼ばれるレガシーなPythonフレームワークに基づいていました。テクノロジーが進歩するにつれて、ScholarPackはアップグレードできなくなりました。ScholarPackとZopeは深く絡み合っており、新しいフレームワークへの変更は簡単な仕事ではありませんでした。Zopeから離れることは必須でしたが、完全な書き直しは失敗する運命にあるため、避ける必要があります。マイクロサービスの移行はビジネスの要件に適合し、段階的なアプローチを可能にしました。
InfoQ: サービスの開発にどのようなアプローチが使用され、どのように機能したのでしょうか?
Thomas氏: 私たちは、アプリケーションのデータベースをミラーリングした中央の「モノリシック」APIを使用して、サービスの開発にAPIファーストアプローチを採用しました。これは機能の周りに配置された名前ですが、それでも単一のサービスです。マイクロサービスの純粋主義者は私が知っていることに驚きます。しかし、これによりデータベースを変更せずに維持でき、複数のサービスに複雑なデータモデルを実装する必要がなくなりました。
このAPIが後ろにあるため、ほとんどのサービスは独自のHTMLを生成し、Wrapperを介してこれを顧客に送信します。
私はおそらくこれを一連のミニモノリス、ビジネスモジュールに分割されたもの、または単一責任サービスと説明します。私は責任の概念的な境界について考えるのが好きです。それを超えると、サービスは別のサービスに引き継がれます。これらの責任は、開発チームのニーズに応えるために、やや範囲は広く、間違いなく恣意的です。
私は、正しいアーキテクチャは1つもないと固く信じています。成功の唯一の本当の尺度は、プロダクション環境でソフトウェアを実行することです。その後、変更の容易さと安全性、そして副作用を制限し、アーキテクチャコンポーネント間の緊密な結合を実現する機能が重要になりますが、それは開発とデプロイメントを容易にするという点でのみです。
ScholarPackにはこれらのサービスがいくつかあり、「評価」、「報告」、「学生管理」、「保護者管理」などの幅広い責任範囲があります。場合によっては、これらはほぼモノリシックな製品であり、スタンドアロンのものとして販売される可能性があります。これらの分割を使用すると、システムのさまざまな部分をさまざまな速度で移行でき、大規模なデプロイメントのリスクを回避できるため、開発が容易になります。ただし、モジュールが非常に大きいと、技術チームの認知的負荷が軽減されます。開発者やシステム管理者なら誰でも、一連の機能の提供に使用されるすべてのコンポーネントを簡単に頭に入れておくことができます。小さなチームでは、この複雑さと認知的負荷の軽減は、物事をスピードアップするのに役立ちます。
そうは言っても、コード全体に将来的にサービスを分割できるようにするコード内の論理的な区切りとなる継ぎ目を残しています。これは、Flask Blueprintsを広範に使用し、サービス内の結合を減らすSOLIDの原則を順守することで支援されています。
各サービスは、許可システム、フロントエンド世代、およびAPIとの通信方法を理解する「スケルトン」と呼ばれる開始コードベースからフォークされます。共有ロジックは、一連の保守およびバージョン管理されたPythonライブラリ内にあり、その多くはオープンソースであり、GitHubおよびPyPiが利用できます。
InfoQ: 継続的デリバリーとインクリメンタル開発をどのように適用するのでしょうか?
Thomas氏: 各モジュールは小さく、自己完結型です。これにより、迅速なリリースサイクルが可能になり、パイプラインがデプロイメントをライブに推進します。
Zopeフレームワークの数少ない利点の1つは、ソフトウェアの脆弱性により、少しずつ作業し、頻繁に小さなリリースで出荷することを余儀なくされていることです。リリースされていないコードが数時間以上置かれていると、偶発的なリリースやコードの上書きなど、デプロイメントに関するインシデントが発生します。したがって、哲学は「書いたらすぐに出荷する」というものでした。
フィーチャートグルやアトミックリリースのようなものは第二の性質でした。したがって、Wrapperと新しいサービスアーキテクチャを設計したとき、フィーチャートグルは最初から組み込まれていました (最初のカットは少し粗雑かも)。したがって、プロジェクトの初期の頃から、コードはコミットされてから数時間以内に実行されるようにプッシュされていました。
Flaskのようなフレームワークに移行すると、コードに対して実際のチェックを実行できる「適切な」CIパイプラインが有効になります。プロダクション環境へのデプロイメントは手動で開始されますが、他のすべての環境のビルドとデプロイメントは、ブランチへのコミットによって開始されます。
目的は、リリースのリズムをZopeの場合と同じに保つことです。変更は小さく、大規模な「リリース」ではなく、1日に複数の小さなデプロイメントが行われます。次に、フィーチャートグルを使用してプロダクション環境で機能を有効にします。
InfoQ: 移行から学んだことは何でしょうか?
Thomas氏: 私たちが学んだことは次のとおりです:
- ルール1に従っていることを常に確認してください - 以前よりも優れていますか? 大規模なプロジェクトでは何度も、完璧は良の敵であり、私たちは完璧を求めていません。私たちはより良いものを探しています。動作し、保守可能で、ライブであるものは、日の目を見ることのない完璧なソリューションよりも優れています。
- 最高のアーキテクチャが登場します。マニフェストを引用していることは知っていますが、それは本当です。レガシー製品の移動に対する教科書の回答はありません。純粋主義者を惹きつける設計上の決定はたくさんありますが、このコンテキストでは、問題のブロックを解除し、システムを改善しました。これらの荒削りな部分、つまり作業を簡素化するために私たちが故意に負担した技術的負債は、CI、単体テスト、段階的リリースされた資産でスムーズになり、顧客はすでに改善されたエクスペリエンスのメリットを感じています。
- 正しい最初のモジュールを選択すると、プロジェクトが成功または失敗します。開始点として「書き換え」プロジェクトの完全に外側の何かから始めることで、多くの質問をローステークスの方法で解決することができました。最初の外部APIの構築で学んだことはすべて、新製品の構築に直接取り入れられました。
- ピボット。アイデアがうまくいかない場合は、後でではなく早く解き放ちます。サービスがそれ自体のデータを管理する必要があると信じていたため、多くの時間を失いました。その結果、共有する必要のある恐ろしいモデルが生まれました。結合は恐ろしいものでした。このアプローチを複雑にするレガシーがあったことを認め、コアAPIを使用することで、すべての結合が少なくなり、品質と速度が向上しました。