読書：マイクロサービスアーキテクチャ（オライリー社）その1

MicroServiceについてお勉強読書をしたので、少しずつまとめていくことにする。

# 1章　マイクロサービスとは
　1章は、マイクロサービスの定義と特徴について挙げ、
　利点や他の手法との比較を概要レベルで述べている。

## マイクロサービスを定義づけるもの
　マイクロサービスを2つの定義について説明している。
### 小さく、かつ一つの役割
　マイクロサービスはサービスの境界をビジネスの境界に合わせ、特定の機能のコードがある場所を明確にする。
　明示的な境界を念頭に置くようにすることで、サービスを大規模にしてしまう衝動と、それに関連して生じる複雑さを回避する。
　どの程度小さくするのかを考える要素の一つは、チームが管理できるコードベース量であること。大きすぎる場合は分割を試みるべきである。
### 自律性
　サービスはそれぞれが独立して変更でき、コンシューマを変更する必要なく単独でデプロイできなければならない。
　サービスは何を公開し、何を隠すか考えなければならない。共有が多すぎると、呼び出し先サービスの内部表現と結合してしまう。すると自律性が損なわれてしまう。
　サービスはAPI経由で連携する。APIは技術に依存しないものを選び、技術の選択を制約しないようにする。
## 利点
　マイクロサービスの利点の多くは分散システムによるものである。さらに、サービス指向アーキテクチャの利点も併せ持つ。
### 技術異質性
　複数のサービスを連携させるシステムでは、サービス毎に異なる技術を使う決断が出来る。
　ただし、複数の技術の採用にはオーバーヘッドが伴うため、言語の選択に制約を課す組織もある(例：NetfrixとTwitterは主にJVMを使用)。
　適切なバランスを探すことが大切である。
### 回復性
　システムのあるコンポーネントに障害が発生しても、その障害が連鎖しなければ問題を分離し、残りの部分は機能し続けることができる。
　サービス境界がその隔壁となる。
　注意点として、回復性を適切に得るためには、分散システムが対処しなければいけない障害を理解する必要がある(例：ネットワーク障害)。
　障害への対処方法とエンドユーザへの影響を知る必要がある。
### スケーリング
　モノリシックサービスではすべてを一緒にスケールさせなければならないが、小さいサービスが連携するシステムでは、スケーリングが必要なサービスだけをスケールできる。
### デプロイの容易性
　巨大なモノリシックアプルケーションを1行変更すると、その変更をリリースするためにアプリケーション全体をデプロイしなくてはいけない。このようなデプロイは影響が大きくリスクが高い可能性があるため、実際には頻繁に行われることはなく、リリース間の差分が大きくなる。差分が大きくなれば、リスクは高くなる。
　マイクロサービスでは1つのサービスに変更を加えて、残りのシステムとは独立してデプロイできる。そのため、迅速なデプロイと、問題が起きた時の迅速なロールバックを実現できる。
### 組織面の一致
　大規模コードベースを大規模チームや複数の分散されたチームで作業する場合は問題が起こりやすく、生産性も低下する傾向がある。
　マイクロサービスでは1のコードベースで作業する人数を最小化し、チームの大きさと生産性を最適化する。
### 合成可能性
　分散システムとサービス指向アーキテクチャの利点として、機能を再利用する機会を広げることが挙げられる。マイクロサービスはこの利点を備える。
　マイクロサービスでは、外部の第三者がアドレス可能なシステムの接合部を公開していると考えられる。そのため、状況が変わったら別の方法で組み立てられる。
### 交換可能にするための最適化
　マイクロサービス手法を採用しているチームでは、コードベースが数百行くらいのためサービス全体の書き換えや削除に対する障壁が低くなる。
　巨大で扱いにくいレガシーシステムの場合、大きすぎてリスクがあるため、長期間置き替えられずにいる。
## サービス指向アーキテクチャ
　サービス指向アーキテクチャ(SOA: Service-Oriented Architecture)は、複数のサービスが連携して最終的な一連の機能を提供する設計手法である。
　SOAはソフトウェアの再利用性の促進を目指す手法である。例えば、2つ以上のエンドユーザアプリケーションが同じサービスを使用できる。
　だが、従来のSOAの大半の考え方は、大きなものを小さく分割する方法や、サービスが結合し過ぎないようにする実用的な方法について、十分に示せていない。
　マイクロサービス手法は実用的な面からSOAを適切に表現するための手法と考えるべきである。
## 他の分解テクニックと比較
　マイクロサービスに類似した他の分解テクニックは、同じ利点を実現できるのだろうか。
### 共有ライブラリ
　事実上あらゆる言語に組み込まれている、ごく標準的な分解テクニックである。
　ライブラリでは、ライブラリを中心にチームを組織化でき、ライブラリ自体を再利用できる。
　しかしいくつか欠点もある。
　技術的多様性が失われる。通常、ライブラリは同じ言語か、少なくとも同じプラットフォームで動作する必要がある。
　システムの各部を独立してスケールさせることは容易ではない。
　ダイナミックリンクライブラリを使っていない限り、デプロイにはプロセス全体をデプロイし直さないといけない。
　システムの回復性を保証するための、アーキテクチャ上の安全対策が確立できていないことが多い。
　共有ライブラリはコード再利用には有効だが、万能ではない。
### モジュール
　簡単なライブラリ以上の独自のモジュール式分解テクニックを提供する言語もある。そのような言語ではプロセス全体を停止せずにモジュールのデプロイが可能である。
　しかし、そのような言語のモジュールでも通常の共有ライブラリと同じ欠点がある。
　新たな技術を使う能力や独立してスケール出来る方法が厳しく制限されている。

# 2章　進化的アーキテクト
## 進化するアーキテクト像
　ソフトウェア開発では急に要件が変更されることがあり、アーキテクトは完璧な最終製品を作成するという考え方を変え、代わりに適切なシステムが得られるようなフレームワークを作成することに重点を置くべきである。
　ITアーキテクトは「建築士」ではなく「都市計画家」と考えるべきである。
　都市計画家は建てる建物を決定するのではなく、都市を区画する。同様にアーキテクトは方向性を大まかに設定する必要があり、実装の詳細について関わるのは限定された場合のみとなる。
　アーキテクトはシステムが現在の目的にかなうようにする必要があるが、将来のプラットフォームにも適するようにしなければならない。そして、ユーザと開発者を等しく満足させるシステムにする必要もある。
## 区画指定
　都市計画家にアーキテクトをたとえた場合、区画はサービス境界、またはサービスの粒度の荒いグループになる。
　アーキテクトは区画間で起こること、つまりサービスが互いにどのように大差しているかを考えたり、システムの全体的な健全性を適切に監視できるようにすることに時間を費やすべきである。

## 原則に戻づいたアプローチ
　システム設計における判断を下す際に有効な手法として、フレーミング(枠づけ)がある。フレーミングを行うには、実現したい目標に基づいて一連の還俗とプラクティスを定めることである。
### 原則
　原則とは実行を目標に一致させるために作成した規則であり、時々変更される。
　原則の数は10未満が適切であり、多いほど重複や矛盾の可能性が高くなる。
### プラクティス
　プラクティスは原則を確実に実行する方法であり、タスクを実行するための詳細で実用的な一連の指針である。
　例えば、コーディング指針、すべてのログデータを集中して保存すること、HTTP/RESTが標準的な統合形式であること、などである。
　プラクティスは原則を支えるものであるべきである。
### 原則とプラクティスの結合
　　　十分に小さなチームでは原則とプラクティスを結合しても良いが、技術と実用的なプラクティスが異なる可能性がある大規模組織では、共通の一連の原則に対応した異なるプラクティスが必要になる場合もある。
## 必要な標準
　　システムの全体像を見失わずにここのマイクロサービスの自律性を最適化するためのバランスを探す必要がある。各サービスが持つべき明確な属性を定義することは、そのバランスを明確にする手段の一つである。
### 監視
　　　サービスをまたがったわかりやすいシステム全体の健全性のビューが不可欠である。すべてのサービスで健全性と一般的な監視関連のメトリックスを同じように出力することを勧める。
### インターフェース
　　　定義済みインターフェース技術は少数にするべきである。標準の数は1つが適切である。
### アーキテクチャ上の安全性
　　　不適切な振る舞いのサービス一つで全関係者に損害を与えないように、不健全な下流呼び出しから適切に身を守るようにしないといけない。例えば、各下流サービスに対して独自の接続プールを取得するように義務付けたり、各サービスに対してサーキットブレーカーを使うようにしたりといったことである。
　　　レスポンスコードに関しては、ルールに従って行動することも重要である。あるサービスがエラーに対して2XXを返したり、4XXと5XXを混同したりしている場合、安全対策が破綻する可能性がある。
　　　サービスが規則に正しく従っていない場合には、最終的に脆弱なシステムになってしまう。
## コードを介したガバナンス
　実行方法の合意を取ることを容易にする手法として、手本を使うこととサービステンプレートを提供する方法がある。
### 手本
　　　推奨したい一連の標準やベストプラクティスがある場合には、開発者たちに示すことが出来る手本があると便利である。これは、システムの優れた部分を真似するだけで大きく間違えることはなくなるという考え方である。
### カスタムのサービステンプレート
　　　一連の開発プラクティスのために、サービステンプレートをカスタム作成しておけば、チームが迅速に取り掛かれるようになり、また開発者が不適切な振る舞いをするサービスを作成しにくくなる。
　　　しかし、これはチームの言語選択を制約するかもしれない。社内のサービステンプレートがJavaだけをサポートしている場合、別の技術スタックを選んで自分自身で多くの作業を行うよりも、Javaを選択した方が無難だろう。労力の重複だけでなく、新しく実装したものが不適切であるリスクも高くなる。Netflixでは、サイドカーサービスを利用してこのリスクを軽減している。
　　　カスタムのサービステンプレートを使う場合は、そのテンプレートの責務を十分に考えるべきである。理想的には、カスタムのサービステンプレートの利用は単なるオプションにすべきだが、強制的に採用させたい場合には、開発者の使いやすさを中心に考慮しなければならない。押し付けられた強制的なフレームワークでチームのやる気や生産性が損なわれないようにするべきである。
　　　また、共有コードのリスクも認識しておく必要がある。再利用可能なコードを作成する中で、サービス間の結合の原因を取り込んでしまう恐れがある。
## 技術的負債
　　技術ビジョンを守れず、緊急の機能を提供するといった選択をする必要があるかもしれない。しかし、ビジョンから逸脱すると長期的にはコストになる。このトレードオフの理解に役立つ概念が技術的負債である。
　　技術的負債の原因は、近道したことだけではない場合もある。例えばシステムのビジョンが変更されたのに、システムのすべてがそれに対応していなかった場合である。
　　アーキテクトの仕事は全体像を検討し、そのバランスを理解することである。負債の水準と関与すべき箇所に関する展望を持つことが重要である。
## 例外処理
　　原則とプラクティスはシステム構築方法の指針となるが、システムがそこから逸脱した場合は、規則の例外となる判断を下すこともある。その場合は、例外の判断をログに記録し、十分な例外が見つかったら、いずれは原則やプラクティスを変更することが理にかなっている。
　　開発者にあまり自由がない、より組織化された組織では、導入された規則に人々が直面している課題を適切に反映させるために、例外の追跡が不可欠である。開発者の仕事の方法に多くの制約を加えている組織で働いている場合には、マイクロサービスは適さないかもしれない。
## 中央からのガバナンスと指導
　　アーキテクトはガバナンスにも対処する必要がある。ガバナンスはCOBIT(Control Objectives for Information and Related Technmology : 情報関連技術のコントロール目標)が優れた定義をしている。

　　　　ガバナンスは、利害関係者のニーズ、状況、選択肢を評価し、優先順位付けと意思決定を通じて方向性を設定し、合意した方向性や目的に対する実績、順守、進捗の監視を行うことで企業の目的が達成されるようにすること。

　　アーキテクトにとってガバナンスとは、構築しているものが技術ビジョンに一致していることを保証し、必要に応じてビジョンを進化させることである。
　　そのために必要なことは多くある。
　　開発を導く一連の原則を持ち、それらの原則を組織の戦略に一致させる必要がある。また、それらの原則が開発者を悲惨にする作業プラクティスを必要としないようにしなければならない。新技術についていき、適切なトレードオフを行うべきタイミングを把握する必要がある。また人々を支えるために、同僚たちが意思決定を理解し、それを実行するために参加する必要がある。チームと一緒に時間を費やし、判断の影響やコードも理解する必要がある。
　　通常、これは一人ではなくガバナンスグループで行われる。グループでは原則を議論し、必要に応じて変更していく。モデルの一つとしては、アーキテクトがグループを率いているが、グループの大部分は各デリバリチームの技術者(各チームのリーダー)から集められているモデルである。アーキテクトにはグループを機能させる責任があるが、グループ全体がガバナンスの責任を負う。
## チーム構築
　　システムの技術ビジョンを確実に実行するためには、作業を実行する開発者たちの成長を促し、ビジョンの具体化と実装に積極的に参加できるようにしなければいけない。
　　大規模なモノリシックシステムでは、開発者たちが向上して何かを所有する気概はほとんどないが、マイクロサービスでは独立したライフサイクルを持つ複数の自律的なコードベースがある。個々のサービスを開発者に所有させることで開発者を向上させることができ、同時に責任者の負荷を軽減できる。
## まとめ
　　進化的アーキテクトの主な責務をいかに示す。

#### ビジョン
　　システムが顧客や組織の要件を満たすのを助けるシステムの技術ビジョンを、明確に伝えるようにする。
#### 共感
　　顧客や同僚に対する自分の判断の影響を理解する。
#### 協調
　　できるだけ多くの仲間や同僚と関わり、ビジョンの定義、改良、実行に役立てる。
#### 適応性
　　顧客や組織の要求により技術ビジョンを変更するようにする。
#### 自律性
　　チームに対して標準化と自律性の実現との間の適切なバランスを見出す。
#### ガンバナンス
　　実装しているシステムを技術ビジョンに合わせる。