マイクロサービスアーキテクチャを読んで（１～３章）

# はじめに
[O'Reillyのマイクロサービスアーキテクチャ](https://www.oreilly.co.jp/books/9784873117607/)を読んでいます。
とりあえず１～３章について、読書メモとして残しておきます。

# 1. マイクロサービスアーキテクチャとは

## マイクロサービスの大きさについて
文中には曖昧にしか書かれていない。

> 月並みですが、「十分小さく、ちょうどいい大きさである」と答えることができます。
> （中略）
> あるコードが大きすぎると感じなくなったら、そのコードは十分に小さくなっていると言えるでしょう。

って、そんなことわかってるから・・・。

> サービスが小さければ小さいほど、マイクロサービスアーキテクチャの利点と欠点が最大化されます。

小さくすれば、相互依存関係にかかわる利点が増加するが、複雑度も増す。

## 自立性について
> サービス間のすべての通信はネットワーク呼び出しを経由し、サービス間の分離を強制し、密結合のリスクを回避します。

ただし、共有が多すぎると、呼び出し元のサービスが呼び出し先サービスの内部表現に結合する。（つまり、依存関係が強すぎると、依存先の内部表現に引っ張られていく）

> 適切に分離するには、サービスを正しくモデル化し、APIを適切にする必要があります。

## マイクロサービスアーキテクチャを採用する利点は？

### 各サービスに対して、個別の適切な技術を採用できる
サービス間で異なる技術を採用できる。結果、適切な技術の採用ができ、開発の効率化・適切なサービスの提供が可能になる。
モノリシックアプリケーションでは、新しい技術を採用するのはかなりしんどい（というか例えば言語レベルの変更とかは事実上無理）が、マイクロサービスだと低リスクのため新しい技術を試しやすい。

### 回復性が高い
> システムのあるコンポーネントに障害が発生していても、その障害が連鎖しなければ、問題を隔離してシステムの残りの部分は機能し続けることができます。

モノリシックなアプリケーションでは、サービスに障害が発生すると停止する。

### スケーリングがしやすい
小さいサービスだと、サービスを展開しやすい。また、マシンパワーも要求しなくて済む場合がある。

### デプロイが容易
モノリシックなアプリケーションの場合、たった１行の変更でも、システム全体をデプロイする必要がある。
そしてモノリシックなアプリケーションは、ちょっとの変更の影響範囲が大きくなる傾向がある。
マイクロサービスでは、サービスごとに変更を行うことができるので、結果的にデプロイのスピードが速くなる。もた、変更に伴うリスクも小さい。

### 生産性が高い
経験則として、大規模なアプリケーションに対して変更を行うより、小規模なアプリケーションに対して変更を行うほうが生産性が高い。

## マイクロサービスアーキテクチャは、SOA（=サービス指向アーキテクチャ）の方法論である

### `SOA (Service-Oriented Architecture)` とは
> サービス指向アーキテクチャは、複数のサービスが連携して最終的な一連の機能を提供する設計手法です。
> SOAにおけるサービスは通常、完全に別個のOSプロセスを示します。
> これらのサービス間の通信は、プロセス境界内のメソッド呼び出しではなくネットワークを介した呼び出しで行われます。

### SOAの利点は？
* 再利用の促進
	* ある１つのサービスを、２つ以上のエンドユーザアプリケーションから使用することができる
* 疎結合
	* 理論的には、対象のサービスをAPIさえ揃えておけば、自由に置き換えることが可能

### しかし現状・・・
現状は、適切にSOAを使っている案件は少ないとのこと。
これは、例えば以下の問題点を十分検討できていないから。

> * 通信プロトコル、ベンダミドルウェア、サービス粒度に関する指針の欠如
> * システムの分割場所の選択に関する間違った指針

### マイクロサービスアーキテクチャをSOAの方法論として使用すべし
SOAはそもそも、分割方法や分割粒度の大きさなどの明確な定義はされていないらしい。
XPやスクラムがアジャイルの方法論であるように、マイクロサービスアーキテクチャもSOAの方法論として捉えるべし。

## マイクロサービス以外の分解テクニック
以下の方法は、ケースバイケースだが、再利用の促進や疎結合という点においては劣っている。

### 共有ライブラリ、モジュール
欠点

* 通常、共有ライブラリを使用するためにはプラットフォームが同じであることを求められる。そのため、技術的多様性が失われる
* DLLでない場合は、共有ライブラリの変更＝全体の再デプロイとなる
* 独立してスケールすることができない
* サービス間の呼び出しが結合し、密結合しやすい（ネットワークを介すなどしていない限り）
* 結合できないように強制できないため、コードレベルで結合しやすい

### が、マイクロサービスが銀の弾丸というわけではない
マイクロサービスの欠点

* 分散システムに関連する複雑さがある
* 管理する方法も困難
* 今までのモノリシックな考え方ではうまくいかない場合がある（考え方を変える必要がある→変化が求められる→抵抗勢力が生まれる）
    * ⇒組織的な問題も発生するかも

# 2. 進化的アーキテクト
「ソフトウェアアーキテクト」（日本でいうならSEやSIが該当？）とは、建築業界の「建築士」とは意味が違う。
少なくとも、建築業界のやり方をソフトウェアに当てはめるのはナンセンスである。（厳密な設計→施工は不可能。建築の世界では橋の工事中に対岸が５０ｍ離れたり、花崗岩だと思っていたものが泥になったりすることはないが、ソフトウェアの世界ではそういうことが当たり前のように起こりうる）

ソフトウェアアーキテクトは、どちらかというと「都市計画家」に近い。区画を引き、各区画ごとのおおまかな方向性を決定することが求められる。

## 区画指定
> アーキテクトは、区画間で起こることに比べ区画内で起こることをそれほど心配する必要はありません。

サービスを区画と例えた場合、区画間は注意が必要。例えばサービス間のやり取りに複数の技術（`REST`と`Protocol Buffers`など）を使用すると、サービスは複数の交換方式をサポートする必要が出てくる。

## 監視
> サービスをまたがったわかりやすいシステム健全性のビューを作成できることが、不可欠です。
> これはシステム固有のビューではなく、システム全体のビューでなければなりません。
> これをできる限り簡単にするには、すべてのサービスで健全性と一般的な監視関連のメトリックを同じように出力することをお勧めします。

これはつまり「監視」という境界づけれたコンテキストを用意するということだろうか？

> 内部の技術を不透明にし、その技術をサポートするために監視システムを変更せずに済むようにしてください。
> ロギングは同じカテゴリに分類され、１か所に集める必要があります。

イベントソーシングのように、ログもイベントを発行して、「監視」BCがイベントを購読してロギングするようにすればよいということ？
ちょっと気になるのが、ロギングは横断的関心事＝各サービスで閉じた責務だと思っているので、サービスをまたいでロギングの責務を外部に委譲する（＝ロギング処理が外部に依存する）というのに違和感があるが・・・

# 3. サービスのモデル化方法
（ここでは`MusicCorp`という仮想オンライン音楽小売業者を例に説明している）

優れたサービスを実現するには、**疎結合**と**高凝集**の実現がポイントとなる。

## 疎結合
> マイクロサービスの本質は、システムのほかの部分を変更する必要なしに、あるサービスを変更してデプロイできることです。

サービス間を密に結合する統合方式を選択すると、失敗の元となる。
サービス間は必要最低限のことのみを把握するようにして、不要な結合をなくすべし。

## 高凝集性
振る舞いを変更したいときに、１か所で変更でき、その他をできる限り早くリリースできるようにすべし。
変更するために様々な個所を変更する必要があると、複数のサービスを同時にリリースする必要が出てくる。結果、リリーススピードが落ちる。

## 境界づけれたコンテキスト（BC）
DDDにおける重要な概念であるBCが、マイクロサービスの単位となる。
ここで、BCの切り分け方だが、著者は以下のように述べている。

> 私が好きな境界づけれたコンテキストの別の定義は、「明示的な境界によって強制される特定の責務」です。（参考:
http://bit.ly/bounded-context-explained）

リンクの意訳だが、「BCの切り分け方の基準は、実組織の部署として表現した場合に適切かどうか」ということだと認識している。

## 共有モデルと隠れモデル
あるモデルが、サービス間で共有する必要があるかないかを定義する必要がある。
共有する必要がないモデルは外部公開しないようにすべし。不要な結合を招く可能性がある。

## 時期尚早な分解
新規システムでは、最初からBCを見極めてサービスの単位を決めるのは難しいので、まずはモノリシックに作って、ドメインの理解が進むにつれて徐々にマイクロサービスに分離していくほうが安全。

## ビジネス機能
> 組織に存在する境界づけられたコンテキストについて考える際、共有するデータの関連ではなく、そのコンテキストが残りのドメインに提供する機能について考えるべきです。

[こちら](https://qiita.com/crossroad0201/items/23864b3b177fb1fce966)を参考にすると、

> コンテキスト境界を分離するときは、データの観点ではなく、そのコンテキストが外部に公開する振る舞いに注目したほうが良い。

とのこと。

## BCの入れ子構造について（ずっと下の亀）
BCの中にさらに粒度の小さいBCが見つかることがる。
この場合、さらにBCを分離するか、他のマイクロサービスからは入れ子構造を隠したままにする（つまり外見的にはBCを分離しない）かは、ケースバイケース。
だが、筆者は後者を推奨している。

理由：

* 分離前のBCを１チームが管理しているならば、組織構造とソフトウェアアーキテクチャの相互作用も考慮して、分離しないほうがよい
* テストを考えた場合、他のマイクロサービスが粒度の細かいサービスのスタブを作る必要がなくなる。用意するのは粒度の粗いAPIで済む

## 技術的境界
サービスの単位を技術レベルで分離するのはアンチパターンである。