lasciva blog

開発して得た知見やwebビジネスのストック

「分散システムデザインパターン」を読んだ

分散システムデザインパターン ―コンテナを使ったスケーラブルなサービスの設計

分散システムデザインパターン ―コンテナを使ったスケーラブルなサービスの設計

目的、モチベーション

  • 分散システムの記事等を見たときに、サイドカー等の理解してないキーワードを散見するようになり、理解したかったため。
  • コンテナを使ったマイクロサービスを運用しており、理解を深めたかったため。
  • Faasなどのクラウドサービスの使い分けを把握したかったため。

全体の感想

シングルノードのときや、マルチノードのときなど幅広く取り扱われており、なんとなく単語レベルでは知ってるパターンの理解を深めることはできた。
インフラ寄りのデザインパターンがほとんどだが、アプリケーションにも関与していて開発しているときにも他の選択肢が増えて視野が広がった気がする。
マルチノードパターンでは、負荷対策などのためのスケール方法が多く記載されていて面白かった。
全体的に解決しようとしてる課題感は掴めたが、現場でSRE的な役割で運用してみないと。

目次

概要

1章 はじめに

分散システムが前提となった時代において、アルゴリズムオブジェクト指向などと同様にパターン化して公式化することが本書のゴール。

第Ⅰ部 シングルノードパターン

シングルノードパターンを使う理由

  • リソースの分離
  •  関心の分離・影響範囲の局所化
  • デプロイやロールバックを容易にする

2章 サイドカー

1台のマシン上で動く2つのコンテナから構成されるパターン。
ホスト名、ネットワーク、ディスクなど多くを共有する。

  1. サイドカーの例:レガシーサービスのHTTPS 対応
    • nginxなどのSSLのプロキシを挟んで、localhost上でアプリケーションを動かしてアクセスする。
    • アプリケーションがレガシーでHTTPSの対応が難しいときなど。
  2. サイドカーによる動的な設定
    • クラウドネイティブな場合、設定はAPIで更新する方が便利。
    • 既存のアプリケーションを拡張するよりも、サイドカーに設定を更新させるようにさせた方が容易なことがある。
  3. モジュール化されたアプリケーションコンテナ
    • コンポーネントのモジュール化と再利用性の例
    • プロセス情報を取得するためにAPIを提供する場合
      • 各アプリケーションで統一的に対応するのは言語が異なったりして困難。
      • サイドカーを利用して一貫したインターフェースで情報を提供できるようになる。

3章 アンバサダ

アプリケーションが外部サービスに接続する際に、プロキシとなるコンテナを経由させるコンテナグループを作るパターン。

1. サービスのシャーディングへのアンバサダの利用

Redis等でシャーディングさせてる際に、ノードを増やす度にアプリケーションをデプロイし直す必要がなくなり、ロジックを共通化できてアンバサダコンテナを独立してデプロイすることができる。

2. サービスブローカとしての利用

開発環境や、本番環境などで外部サービスのホストやポートの設定が異なる可能性が高いが、そのロジックをアンバサダコンテナに委譲できる。

3. 新システムの実験的運用やリクエスト分割への利用

バージョンアップなどで新システムを本番環境に導入する際にも、試験的に導入することができる。
例えばアンバサダの設定を変更して、既存のシステムを稼働させつつ、新システムにも同じリクエストを裏側で送って負荷を確認することができる。

4章 アダプタ

コンテナグループ外に対して、外部インターフェイスを提供する際にアダプタコンテナを経由して提供するパターン。

  1. 監視
    • 監視ツール用のインターフェースに変換することで、アプリケーションの責務を分けることができる。
    • 監視コンテナを提供する開発者と、アプリケーションの開発者を切り分けることができる。
  2. ロギング
    • 監視と異なり、ログはレベルごとにファイルが異なったり、標準出力してるだけのことがあり、フォーマットがバラバラ。
    • アダプタパターンで、モジュール化して再利用して、フォーマットを統一することができる。

第Ⅱ部 マルチノードパターン

6章 シャーディングされたサービス

1. シャーディングされたキャッシュ

シャーディングされてる場合は、一つのノードが死んだ場合に特定のユーザへのレスポンスが遅くなるリスクがあるため、キャッシュのレプリカを用意したほうが高可用になる。

2. シャーディング関数を試してみる

キーの選択
異なる国からリクエストがある場合、言語ごとにキャッシュを切り替える必要があるため、単にIPアドレスを元にハッシュを生成するのは良くない。

コンシステントハッシュ関数
ノードの数を増やすと再シャーディングする必要がある。このとき、シンプルなハッシュ関数だと再シャーディングのコストが高くなる可能性があるが、コンシステントハッシュ関数を使うと効率的に再シャーディングできる。

7章 スキャッタ・ギャザー

バックエンド内で、複数のノードを使って処理を分散させて高速化させるパターン。ただし複数のノードを使うことによるデメリットもある。

  • ノードごとのオーバヘッドがあるので、並列性を上げても必ずしも処理速度が上がるとは限らない
  • 落ちこぼれ問題(一部のノードでレスポンスが遅くなって全体のレスポンスが遅くなる問題)のため、並列度を上げても処理速度が上がるとは限らない。
  • 一つのノードで障害が起こると全体が止まるので、シャーディング毎にレプリカは必須。(バージョンアップを行う際などでノードは必ず止めないといけないタイミングがある。)

9章 オーナーシップの選出

マスタの選出の実装は困難なため、 etcdApache ZooKeeperConsulなどのコンセンサスアルゴリズムを利用する。

第Ⅲ部 バッチ処理パターン

Apache Kafkaを使ったPub/Subのパターンや、MapReduceフレームワークでの協調する手法が紹介されていた。

分散システムデザインパターン ―コンテナを使ったスケーラブルなサービスの設計

分散システムデザインパターン ―コンテナを使ったスケーラブルなサービスの設計