My observation and thinking on cloud native software architecture

foreword
「クラウドネイティブインフラストラクチャ」の記事では、クラウドネイティブコンピューティングにはクラウドネイティブインフラストラクチャ、ソフトウェアアーキテクチャ、デリバリーおよび運用保守システムの 3 つの次元が含まれることを紹介しました。本記事では、ソフトウェアアーキテクチャの観点に焦点を当てて解説します。

私にとって、ソフトウェアアーキテクチャの主な目標は以下の課題を解決することです。

1. 複雑性の制御。ビジネスの複雑さゆえに、より良い手法を用いて開発組織の認知的障壁を克服し、より優れた分業と連携を実現する必要があります。分割統治や関心の分離などがこれに該当します。

2. 不確実性への対応。ビジネスは急速に変化し、ニーズも絶えず変わります。完璧なソフトウェアアーキテクチャであっても、時間の経過やチームの変化とともに、アーキテクチャの調整は避けられません。「デザインパターン」や「マイクロサービスデザイン」などの書籍を読むと、「結合分離」という言葉が至るところに見られます。アーキテクチャにおける確実なものと不確実なものの分離に注目し、アーキテクチャの安定性と適応性を向上させましょう。

3. システムリスクの管理。システム内の確実なリスクと不確実なリスクを管理し、既知の落とし穴を避け、未知のリスクに備えます。

クラウドネイティブアプリケーションアーキテクチャの目標は、ビジネス要件の変化や発展により良く対応し、システムの安定性を確保できる、疎結合で弾力的かつ回復力のある分散アプリケーションソフトウェアアーキテクチャを構築することです。本記事では、この分野での私の観察と考えを共有します。

Origination - 12 Elements Application
2012 年、Heroku の創設者である Adam Wiggins が Twelve-Factor App のマニフェストを公開しました。これは、エレガントなインターネットアプリケーションを構築するために従うべき基本的な原則と手法を定義したもので、多くのマイクロサービスアプリケーションアーキテクチャに広く影響を与えました。12 の要素は、アプリケーションの健全な成長、開発者間の効果的な連携、そしてソフトウェアアーキテクチャの劣化による影響の回避に焦点を当てています。その内容は、今日のすべての開発者が真剣に理解する価値があります。


Twelve-Factor App は、以下の点に役立つ優れたアーキテクチャガイダンスを提供します。

1. インターネット規模のアプリケーションをより良くサポートするために、水平方向にスケーラブルな弾力的なアプリケーションアーキテクチャを構築する。

2. R&D プロセスの標準化と自動化レベルを向上させ、R&D 効率を改善する。

3. 開発環境と本番環境の差異を縮小し、継続的デリバリーを用いてアジャイル開発を実践する。

4. アプリケーションのポータビリティを向上させ、クラウドデプロイに適応させ、リソースコストと管理の複雑さを軽減する。

疎結合アーキテクチャ設計

マイクロサービスの中核概念は、システム内の各サービスが独立して開発、デプロイ、アップグレードでき、各サービスが疎結合であるということです。クラウドネイティブアプリケーションアーキテクチャの概念は、アーキテクチャの疎結合をさらに強調し、サービス間の相互依存度を低減させることです。

API ファーストのアプリケーションアーキテクチャ設計
オブジェクト指向のソフトウェアアーキテクチャにおいて最も重要なのは、オブジェクトとそのインターフェイス契約を定義することです。SOLID 原則は、最も広く知られた設計原則です。

Single responsibility principle - 単一責任の原則

Open/closed principle - オープン・クローズドの原則

Liskov substitution principle - リスコフの置換原則

Interface segregation principle - インターフェイス分離の原則

Dependency inversion principle - 依存性逆転の原則

上記 5 つの原則の英語の頭文字を合わせると SOLID 原則になり、これにより高凝集・低結合で柔軟なアプリケーションアーキテクチャを構築できます。分散マイクロサービスアプリケーションアーキテクチャでは、API ファーストはコントラクトファーストの自然な拡張です。

API は設計において優先されるべきです。ユーザーのニーズは複雑で変化しやすいことを知っています。たとえば、デスクトップからモバイルへの移行では、アプリケーションの表示方法や操作流程が異なる場合があります。しかし、ビジネスロジックの概念モデルとサービスのインタラクションは比較的安定しています。比較すると、API インターフェイスはより安定しており、特定の実装は反復的に実装し継続的に変更できます。明確に定義された API は、アプリケーションシステムの品質をより良く保証できます。

API は宣言的であり、自己記述的であるべきです。標準化された記述を通じて、API はコミュニケーション、理解、検証が容易で、開発の連携を簡素化します。サービスの消費者と提供者の並行開発をサポートし、開発サイクルを加速します。異なる技術スタックの実装をサポートします。たとえば、同じ API インターフェイスに対して、そのサービス実装は Java を採用し、フロントエンドアプリケーションは JavaScript を使用し、サーバーサイドアプリケーションは Golang を使用してサービス呼び出しを行うなどが可能です。これにより、開発組織はスキルスタックとシステム要件に基づいて適切な技術を選択する柔軟性を得られます。

API には SLA が必要です。サービス間の統合インターフェイスとしての API は、システムの安定性と密接に関連しています。SLA は API 設計の一部として考慮されるべきであり、デプロイ後に考えるものではありません。分散システムでは、安定性リスクは至る所に存在します。API ファーストの設計パターンを通じて、独立したサービスに対して安定性アーキテクチャ設計と容量計画を実施します。独立した API に対して障害注入と安定性ドリルを実行し、システムの安定性リスクを排除できます。

API の世界において最も重要なトレンドは、標準化技術の台頭です。gRPC は Google がオープンソース化した高パフォーマンスで汎用的、プラットフォーム非依存の RPC フレームワークです。階層化された設計を採用し、データ交換フォーマットは Protobuf(Protocol Buffers)プロトコルに基づいて開発されており、優れたシリアル化・デシリアル化効率を持ち、多くの開発言語をサポートします。トランスポート層プロトコルとして、gRPC は HTTP/2 を選択しており、HTTP/1.1 と比較して伝送効率が大幅に向上しています。さらに、HTTP/2 は成熟したオープン標準として、豊富なセキュリティとフロー制御機能、および良好な相互運用性を備えています。gRPC はサーバーサイドのサービス呼び出しだけでなく、ブラウザ、モバイルアプリ、IoT デバイスとバックエンドサービスのインタラクションもサポートします。gRPC は機能的に完全な RPC 能力を持つだけでなく、新機能をサポートする拡張メカニズムも提供しています。

クラウドネイティブのトレンドの下では、クロスプラットフォーム、クロスベンダー、クロス環境のシステム間の相互運用性の需要が必然的にオープン標準に基づく RPC 技術をもたらし、gRPC は時代の流れに適合してより広く使用されるようになりました。マイクロサービスの分野では、Dubbo 3.0 が gRPC プロトコルのサポートを発表しています。将来的には、gRPC プロトコルに基づいて開発されたより多くのマイクロサービスアーキテクチャが登場し、優れた多言語サポートを提供するでしょう。さらに、データサービスの分野でも、gRPC は優れた選択肢となっています。Alluxio の記事を参照してください。

さらに、API の分野では、Swagger(OpenAPI 仕様)と GraphQL が注目すべきオープン標準です。自社のビジネス要件に応じて柔軟に選択してください。本記事では繰り返しません。

イベント駆動型アーキテクチャの台頭
イベント駆動型アーキテクチャ(EDA - Event Driven Architecture)について話す前に、まずイベントとは何かを説明しましょう。イベントは、起きた事象や状態変化の記録です。これらは不変(変更・削除不可)であり、作成された順序でソートされます。関心のある当事者は、公開されたイベントをサブスクライブすることでこれらの状態変化に関する通知を受け取り、選択したビジネスロジックを使用してこの情報に基づいてアクションを実行できます。

イベント駆動型アーキテクチャは、疎結合のマイクロサービスシステムを構築するためのアーキテクチャアプローチです。マイクロサービスは非同期イベント通信を通じてインタラクションを行います。

イベント駆動型アーキテクチャは、イベントの生産者と消費者の完全な分離を実現します。生産者はイベントがどのように消費されるかを気にする必要はなく、消費者はイベントがどのように生成されるかを気にする必要はありません。生産者に影響を与えることなく、より多くの消費者を動的に追加でき、メッセージミドルウェアを追加してイベントを動的にルーティング・変換できます。これは、イベントの生産者と消費者にタイミング依存関係がないことも意味します。アプリケーションのダウンタイムによりメッセージをタイムリーに処理できない場合でも、プログラムはメッセージキューからこれらのイベントを取得し続け、回復後に実行を続行できます。このような疎結合アーキテクチャは、ソフトウェアアーキテクチャに高いアジリティ、柔軟性、堅牢性を提供します。

イベント駆動型アーキテクチャのもう一つの重要な利点は、システムのスケーラビリティを向上させることです。イベント生産者はイベント消費を待っている間にブロックされず、Pub/Sub モードを使用して複数の消費者がイベントを並行して処理できます。

イベント駆動型アーキテクチャは FaaS(Function as a Service)とも完全に統合されます。イベントトリガーされた関数がビジネスロジックを実行し、複数のサービスを統合する「グルーコード」も関数内に記述でき、イベント駆動型アーキテクチャのアプリケーションをシンプルかつ効率的に構築できます。

しかし、EDA アーキテクチャにはまだ多くの課題があります。

1. 分散疎結合アーキテクチャにより、アプリケーションインフラストラクチャの複雑さが大幅に増加します。クラウドベースのデプロイデリバリー方法とクラウドサービス(メッセージキュー、Function Computing サービスなど)により、アーキテクチャの安定性、パフォーマンス、コスト効率をさらに向上できます。

2. 従来の同期的な処理方法と比較して、非同期イベント処理にはイベントの順序付け、冪等性、コールバック、例外処理に関連する要件があり、全体的な設計はより困難です。

3. 多くの場合、複数システムにまたがる分散トランザクションサポートがないため、データ整合性の維持は非常に困難です。開発者は可用性と整合性のバランスを取る必要があるかもしれません。たとえば、イベントソーシングを使用して結果整合性を実現します。


4. 相互運用性。現実の世界ではイベントは至る所に存在しますが、異なる生産者はイベントを異なる方法で記述します。開発者は、イベントの発生元に関係なく、一貫した方法でイベント駆動型アプリケーションを構築できるようにしたいと考えています。CloudEvents は、イベントデータを共通かつ一貫した方法で記述する仕様です。CNCF Serverless ワーキンググループによって提案され、イベント駆動型アプリケーションのポータビリティを向上させます。現在、Alibaba Cloud EventBridge や Azure Event Grid などのイベント処理ミドルウェア、および Knative Eventing や Alibaba Cloud Function Computing などの FaaS 技術が CloudEvents に対応しています。

EDA 自体のアーキテクチャの利点により、インターネットアプリケーションアーキテクチャ、ビジネスデータとインテリジェンス、IoT などのシナリオで非常に幅広い展望を持っています。EDA のアーキテクチャについての議論はここでは続けません。

デリバリー志向のアプリケーションアーキテクチャ

クラウドネイティブソフトウェアアーキテクチャでは、設計段階でソフトウェアがどのように構築されるかに注目するだけでなく、最終目標から逆算して考える必要があります。ソフトウェアのデリバリーと保守をより良く行うために、ソフトウェアをどのように合理的に設計・実装するかに注力します。

アプリケーションと運用環境の分離

Twelve-Factor App では、アプリケーションと運用環境の分離が既に提案されています。Docker コンテナの登場により、この考え方がさらに強化されました。コンテナは軽量なアプリケーション仮想化技術です。コンテナ間でオペレーティングシステムのカーネルが共有され、秒レベルの起動をサポートします。Docker コンテナイメージは自己完結型のアプリケーションパッケージング形式であり、アプリケーションとその依存関係(システムライブラリや設定ファイルなど)を一緒にパッケージ化し、異なる環境間でのデプロイの一貫性を維持します。

コンテナはイミュータブルインフラストラクチャ(不変インフラ)の基盤として使用でき、アプリケーションデリバリーの安定性を向上させます。イミュータブルインフラストラクチャは Chad Fowler が 2013 年に提案した概念です。このモデルでは、インフラストラクチャのあらゆるインスタンス(サーバーやコンテナなどのさまざまなソフトウェアおよびハードウェア)は、一度作成されると読み取り専用状態になり、変更を加えることはできません。一部のインスタンスを変更またはアップグレードする必要がある場合は、新しいインスタンスのバッチが作成されて置き換えられます。このモードにより、設定管理の作業負荷を軽減し、システム設定の変更とアップグレードが確実に繰り返し可能であることを保証し、厄介な設定のドリフト問題を回避できます。また、デプロイ環境間の差異を解決しやすくし、継続的インテグレーションと継続的デプロイメントのプロセスをよりスムーズにします。より良いバージョン管理をサポートし、デプロイエラー発生時に迅速にロールバックできます。

コンテナの分散オーケストレーション・スケジューリングシステムとしての Kubernetes は、コンテナアプリケーションのポータビリティをさらに向上させます。Loadbalance Service、Ingress、CNI、CSI などの一連の抽象化により、K8s はビジネスアプリケーションが基盤インフラストラクチャの実装差異を隠蔽し、柔軟に移行できるようにします。このような機能により、データセンター、エッジコンピューティング、クラウド環境間でのワークロードの動的移行を実現できます。

アプリケーションアーキテクチャでは、IP、MAC アドレスなどの静的環境情報をアプリケーションロジックと結合させることを避ける必要があります。マイクロサービスアーキテクチャでは、ZooKeeper/Nacos を使用してサービスの登録とディスカバリーを実現できます。Kubernetes では、Service とサービスメッシュを通じてサービスエンドポイント IP への依存を軽減できます。さらに、アプリケーション状態の永続化も、分散ストレージまたはクラウドサービスを可能な限り使用して実装します。これにより、アプリケーションアーキテクチャのスケーラビリティと自己修復能力を大幅に向上できます。

自己完結型の可観測性

分散システムが直面する最大の課題の一つは可観測性です。可観測性は、システムの現在の状態を理解するのに役立ち、アプリケーションの自己修復、弾力的スケーリング、インテリジェント運用保守の基盤となります。

クラウドネイティブアーキテクチャでは、マイクロサービスアプリケーションは自己完結型であり、自己観測可能で、システムによって容易に管理・検出されるべきです。まず、アプリケーションは自身のヘルスステータスを可視化する能力を持つべきです。

Kubernetes では、ビジネスアプリケーションは liveness プローブを提供でき、TCP、HTTP、またはコマンドラインを通じてアプリケーションの準備状態を検出できます。HTTP タイプのプローブの場合、Kubernetes は定期的にアドレスを訪問します。アドレスの戻りコードが 200 から 400 の間にない場合、コンテナは健康でないと判断され、コンテナはキルされて新しいコンテナが再構築されます。

起動が遅いアプリケーションの場合、アプリケーションの起動が完了する前にトラフィックを導入しないようにします。Kubernetes はビジネスコンテナが readiness プローブを提供することをサポートします。HTTP タイプのプローブの場合、Kubernetes は定期的にこのアドレスを訪問します。このアドレスの戻りコードが 200 から 400 の間にない場合、コンテナが外部サービスを提供できないと判断され、リクエストはコンテナにスケジュールされません。

同時に、新しいマイクロサービスアーキテクチャには観測可能なプローブが組み込まれています。たとえば、Spring Boot 2.3 では、/actuator/health/liveness と /actuator/health/readiness の 2 つの新しい actuator アドレスが公開されています。前者は liveness プローブとして使用され、後者は readiness プローブとして使用されます。ビジネスアプリケーションは Spring システムイベントメカニズムを通じて Liveness State と Readiness State を読み取り、サブスクライブし、変更できます。これにより、Kubernetes プラットフォームはより正確な自己修復とトラフィック管理を実行できます。

さらに、アプリケーションの可観測性には 3 つの重要な機能があります。ロギング、モニタリング、リンクトレーシングです。

1. ロギング – ログ(イベントフロー):離散イベントを記録するために使用され、プログラム実行のある時点または段階に関する詳細情報を含みます。アプリケーションと OS の実行プロセスのログだけでなく、運用保守プロセス中のログ情報(操作監査など)も含みます。

2. メトリクス – モニタリング指標:通常は固定タイプの時系列データで、Counter、Gauge、Histogram などが含まれ、集計可能なデータです。システムのモニタリング機能は多層的で、コンピューティング、ストレージ、ネットワークなどのインフラストラクチャサービスレベルのモニタリング指標と、ビジネスアプリケーションのパフォーマンスモニタリングおよびビジネス指標モニタリングを含みます。

3. トレーシング - リンクトレーシング - 単一のリクエストの完全な処理フローを記録し、分散アプリケーションの開発者に完全なコールリンクの復元、コールリクエストの統計、アプリケーション依存関係の分析などの機能を提供します。これにより、開発者は分散アプリケーションアーキテクチャのパフォーマンスと安定性のボトルネックを迅速に分析・診断できます。

分散システムでは、安定性、パフォーマンス、セキュリティなどの問題がどこでも発生する可能性があり、インフラストラクチャ層、PaaS 層、アプリケーションなど異なるレベルをカバーするフルリンクの可観測性保証が必要です。異なるシステム間で可観測性データの相関、集約、クエリ、分析が可能である必要があります。

ソフトウェアアーキテクチャの可観測性分野は幅広い展望を持ち、多くの技術革新が生まれています。2020 年 9 月、CNCF はクラウドネイティブ可観測性の技術レーダーを公開しました。


その中で、Prometheus はクラウドネイティブアプリケーション向けの企業向けオープンソースモニタリングツールの一つとなっています。Prometheus は活発な開発者コミュニティとユーザーコミュニティを育成しています。Spring Boot アプリケーションアーキテクチャでは、micrometer-registry-prometheus の依存関係を導入することで、アプリケーションのモニタリング指標を Prometheus サービスによって収集できます。

分散トレーシングの分野では、OpenTracing は CNCF 下のオープンソースプロジェクトです。技術に依存しない分散トレーシングの仕様であり、開発者が自分のサービスに一つまたは複数の分散トレーシング実装を統合しやすくする統一されたインターフェイスを提供します。Jaeger は Uber のオープンソース分散トレーシングシステムで、OpenTracing 標準に準拠しており、CNCF からの卒業に成功しました。さらに、OpenTelemetry は有望な標準であり、OpenTracing と OpenCensus の 2 つのプロジェクトを統合して統一された技術標準を形成しようとしています。

多くのレガシービジネスシステムでは、既存のアプリケーションに完全な可観測性機能が備わっていません。新興のサービスメッシュ技術は、システムの可観測性を向上させる新しい方法となり得ます。データプレーンプロキシのリクエストインターセプトを通じて、メッシュはサービス間の呼び出しのパフォーマンス指標を取得できます。さらに、サービスの呼び出し元のアプリケーションは転送が必要なメッセージヘッダーを追加するだけで、サービスメッシュ上で完全なリンクトレーシング情報を取得できます。この方法は可観測性機能の構築を大幅に簡素化し、既存のアプリケーションを低コストでクラウドネイティブ可観測性システムに統合できるようにします。

Alibaba Cloud は豊富な可観測性機能を提供しています。XTrace 分散トレーシングは OpenTracing/OpenTelemetry 標準をサポートしています。ARMS(Application Real-Time Monitoring Service)はマネージド Prometheus サービスを提供し、開発者がシステムの高可用性と容量の課題を回避できるようにします。可観測性は AIOps の基盤であり、将来のエンタープライズ IT アプリケーションアーキテクチャにおいてより重要な役割を果たすでしょう。

Design for Failure - 設計における障害考慮
「マーフィーの法則」―「起こり得ることは必ず起こる」。分散システムはハードウェア、ソフトウェア、または内外の人的要因による影響を受ける可能性があります。クラウドコンピューティングは自社構築データセンターよりも高い SLA とより安全なインフラストラクチャを提供しますが、アプリケーションアーキテクチャの設計において常にシステムの可用性と潜在的な「ブラックスワン」のリスクに注意を払う必要があります。

体系的な安定性には、ソフトウェアアーキテクチャ、運用保守システム、組織的保証の面での総合的な考慮が必要です。アーキテクチャレベルでは、Alibaba Economy は非常に豊富な経験を持っており、防御的デザイン、リミッティング、ダウングレード、障害分離などがあり、Sentinel や ChaosBlade などの優れたオープンソースプロジェクトもコミュニティに貢献しています。

本記事では、クラウドネイティブ時代にさらに考えるべきいくつかの場所について述べます。私の要約は「障害は起こり得るし、必ず起こる。いつでも、どこでも。速く失敗し、小さく失敗し、頻繁に失敗し、速く回復する」です。

まず「障害は起こり得るし、必ず起こる」ですが、サーバーの置換可能性を向上させる必要があります。業界で非常に人気のある比喩があります。「Pets vs. Cattle」、ペットと家畜です。私たちはアーキテクチャの選択に直面しています。アプリケーションが稼働するサーバーを丁寧にサービスし、システムダウンタイムを防ぎ、問題発生時に全力で救出する必要があるのか(Pet)。それとも、各サーバーと各コンポーネントが障害を起こしてもシステムに影響を与えず、自己修復と置換可能な能力を持つことを保証するのか(Cattle)。クラウドネイティブアーキテクチャの提案は、障害の発生を許容し、各サーバーと各コンポーネントが障害を起こしてもシステムに影響を与えず、自己修復と置換可能な能力を持つことを保証することです。この設計原則の基盤は、アプリケーション設定と永続的な状態を特定の運用環境から分離することです。Kubernetes の自動化された運用保守システムにより、サーバーの置換可能性がより容易になります。

また「速く失敗し、小さく失敗し、速く回復する」。Fail fast は非常に直感に反する設計原則です。その背後にある哲学は、障害を避けられないならば、問題を早く露出させるほどアプリケーションの回復が容易になり、本番環境に入る問題が少なくなるというものです。Fail fast 戦略を採用した後、私たちの関心は、システム内の問題をどのように使い尽くすかから、どのように迅速に障害を発見し優雅に処理するかへとシフトします。私が十分に速く走れば、障害は私に追いつけません。 :-) R&D プロセスでは、統合テストを使用してアプリケーションの問題をできるだけ早く発見します。アプリケーションレベルでは、Circuit Breaker などのパターンを使用して、依存サービスの局所的な障害がグローバルな問題を引き起こすのを防ぎます。さらに、K8s のヘルスモニタリングと可観測性を通じて、アプリケーション障害の検出を実現し、サービスメッシュのサーキットブレーカー機能により、障害の発見、トラフィックスイッチング、高速自己修復の能力をアプリケーション実装の外に外部化し、システム機能によって保証できます。Fail small の本質は、障害の影響範囲、つまりブラストラジアスを制御することです。この原則は、アーキテクチャ設計とサービス設計の両方で継続的な注意を必要とします。

最後は「頻繁に失敗する」です。カオスエンジニアリングは、本番環境に定期的に障害変数を導入して、予期しない障害に対するシステムの有効性を検証するアイデアです。Netflix はマイクロサービスアーキテクチャの安定性の課題を解決するためにカオスエンジニアリングの概念を導入し、多くのインターネット企業にも広く使用されています。クラウドネイティブ時代には、より多くの新しい方法があります。Kubernetes により、障害を簡単に注入し、Pod をキルし、アプリケーションの障害と自己修復のプロセスをシミュレートできます。サービスメッシュを使用して、サービス間のトラフィックに対してより複雑な障害注入を実行できます。たとえば、Istio は応答遅延やサービス呼び出し障害などの障害シナリオをシミュレートし、サービス間の結合を検証し、システムの安定性を向上させるのに役立ちます。

Related Articles

Explore More Special Offers

  1. Short Message Service(SMS) & Mail Service

    50,000 email package starts as low as USD 1.99, 120 short messages start at only USD 1.00

phone お問い合わせ
Hi, I'm Alibaba Cloud AI Assistant!
I can help with questions and solutions.