「Webを支える技術」から分散システムについて理解する


参考：[「Webを支える技術」の内容のまとめ](https://qiita.com/Lassieena/items/0241a4e7933df28a3151)

関連： https://roadmap.sh/backend

関連： https://qiita.com/nshibazaki/items/571031d88f1dac0618e5

## 第一部

### 集中システム

- 単一のコンピューティングリソース（メインフレームなど）で処理が完結する。

### 分散システム

- 複数のコンピューティングリソースが相互に通信をして処理を行う。
    - 階層化されて、役割が分担されている。３層アーキテクチャなど。
    - スケールアウト構成。コンピューティングリソースを増強させる目的で、並列に稼働させる。前段にロードバランサを配置し、負荷を分散させる。

### RPC

remote procedure callのこと。

モジュールを複数のコンピューティングリソースに分散させて配置させている際に、別のコンピューティングリソース上の処理を呼ぶことをRPCと呼ぶ。

よく知らんけど、[IDL（Interface Definision Language）](https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9%E8%A8%98%E8%BF%B0%E8%A8%80%E8%AA%9E)があって、そこからスタブが自動生成で用意されるので、そこ経由でRPCをしてくれるように実装がラップされている。

RPCの仕様は独自仕様だったりして、複数ベンダー製品の相互運用性は皆無であった。

### CORBA、DCOM

CORBAは分散オブジェクト技術の標準化された仕様のこと。RPCをする際、あたかもオブジェクトもメソッドコールをするかのようにできる、らしい。（同じくIDLがあって、スタブが用意されるので、そこ経由でRPCをしてくれるように実装がラップされている）

CORBAを使用して通信する場合、IDLがあるので、このIDLを使うと、異なるベンダーのCORBA製品を使っていても通信できるとか出来ないとか。

DCOM(Distributed Component Object Model、分散COM)も似たようなことを実現するための仕様。CORBAとDCOMは互換性なし。

また、どちらの仕様も汎用性を持たせようとしたため、仕様が肥大化・複雑化している。

### 2.3 Web以前の分散システムの問題点

RPC自体はNFSなどの仕様で今も使われている。だが、[「分散コンピューティングにおける落とし穴」](https://ja.wikipedia.org/wiki/%E5%88%86%E6%95%A3%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%AE%E8%90%BD%E3%81%A8%E3%81%97%E7%A9%B4) もあるように、RPCが適用できる範囲というのは、管理されたネットワーク内（イントラネット内）であり、インターネットという、ネットワークの管理主体が異なっているネットワークが複数つながっている場合、動作の前提が崩れてしまう。

それ以外にも以下のような前提を考える必要がある。

- 性能劣化の問題（Networkの遅延、オーバーヘッドがあること。）
- データ型変換の問題（マーシャリング、シリアライズなど、データ転送時にデータを変換したりする。その際に問題が起こりえる）
- インタフェースバージョンアップ時の互換性の問題
    - Webではインタフェースが一般に公開されてしまうため、誰が使っているのかわからない。そのため原則、前方後方互換性のあるインタフェースの変更の仕方をする必要があり、後方互換性のない変更をする場合は、新しくインタフェースを作るなどの配慮が必要。
- 負荷分散の問題
    - ステートフルな実装ではスケールアウト構成にできない。アプリケーション内に状態を持ってしまうと、その状態を複数サーバで共有できるようにしなければならない。なので、スケールアウト構成にするならば、状態はDB内に完結するように実装するなど、アプリケーション内に状態を持たせない必要がある。

また、書籍には記載がないが、文字コードの問題もある。
やりとりに使う文字コードはUTF-8になっているか。あるいはそうではないのか。
UTF-8に変換する際に文字化けが起こりえないか。
実装言語によって適切に文字コードが取り扱われるのか、MIME Typeが適切に扱われるサーバなどの実装なのかという問題も起こり得る。


### 2.6 Web APIをめぐる論争

#### SOAPとWS-*

CORBAみたいなことをXML技術をつかって再実装したものです。

SOAPはデータ交換をXMLを使って行うためのプロトコルです。 SOAP over HTTP(S)でという形で交換されることがデファクトと思われます。また、SOAPによるデータ交換を行う際には、IDLとしてのWSDLを用いてコントラクトを共有することが一般的です。コントラクトという概念は[契約プログラミング](https://ja.wikipedia.org/wiki/%E5%A5%91%E7%B4%84%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0) を参照のこと。要はインタフェース定義のことを指します。WSDLからコードを生成する開発スタイルをコントラクトファースト、コードからWSDLを生成する開発スタイルをコードファーストと呼びます。
（イメージしにくければ、2022年現在でいうと、Swaggerによって、WebAPIの仕様が実装から自動的にドキュメント化されているのと同じ感じと思ってもらっても大丈夫です。）

WS-*(だぶりゅーえす すたー)はSOAPを用いた通信について、トランザクション、認証認可等のセキュリティ、などの機能を追加する多数の仕様群を指すものです。

メリットデメリットは、CORBAやDCOMと大して変わりませんが、WS-Iという仕様によりベンダー実装間の相互運用性を担保しようとしている点が進歩している点です。

いずれにせよ、仕様が複雑すぎたり、ベンダー間の仕様の解釈の差などがあるため、異なるSOAPスタックを用いた通信が必要なのであれば、通信の検証は不可欠です。
なるべくなら、使用しないほうがいいです。

#### XMLとJSON

XMLはオブジェクトツリーをほぼ完全に表現することが可能ですが、表現が冗長になってしまします。
また、XMLを使うと、XMLSchemaなどでスキーマを拡張したりできるので、業界団体とかがデータ構造を標準化したいときに採用するケースがあります（例：HL7®、Ｃｈｅｍ　ｅＳｔａｎｄａｒｄｓ（ＴＭ））。が、EDIとか会社間で何か取り決めを明確にしたいとかがなければ、オーバースペックになります。
単にスキーマが必要なら、Protocol Bufferとかもっと簡易なIDL言語を先に検討するべきです。→[参考](https://qiita.com/yugui/items/160737021d25d761b353)



そのため、JSON がカジュアルに扱えて、大体のケースにおいてのデータ構造を表現できる形式として採用されています。
JSONでもJSON Schemaとかあるらしいですが、ちょっとよくわかんないです、すみません。

ただし、オブジェクトの循環参照がよくある場合はJSONだと不向きかと思われます。

### 2.7 すべてがWebへ

#### Ajax

ブラウザでマッシュアップするということを実現するために、必要な部分だけページを書き換えるという技術。XはXMLのことですが、今日日はJSONを用いていてもAjaxと呼ぶかと思います。

#### Comet

[Comet](https://ja.wikipedia.org/wiki/Comet)を参照。

ロングポーリングという通信形式にすることで、HTTP通信でリアルタイムな通知などを実現する技術。後続の技術にWebSocketがある。

### 3章 REST Webアーキテクチャスタイル

### 3.1 アーキテクチャスタイルの重要性

#### アーキテクチャスタイルとは

[「ソフトウェアアーキテクチャの基礎」](https://www.oreilly.co.jp/books/9784873119823/) の 第II部アーキテクチャスタイルによれば、

> フロントエンドやバックエンドのソースコードがどのように構成されているか（モノリスレイヤー、あるいは個別にデプロイされるサービスとして）、そしてそのソースコードがどのようにデータストアと相互作用するかについての包括的な構造

と定義しています。

また、同上によれば、アーキテクチャパターンとは

> アーキテクチャスタイルのなかで特定の解決策を形成するのに役立つ低レベルの設計構造と定義している（たとえば、一連の捜査やサービス間で高いスケーラビリティや高いパフォーマンスを実現する方法など）

と記載されています。

関連して、「Webを支える技術」の3.1章でも

> アーキテクチャスタイルとは別名「（マクロ）アーキテクチャパターン」とも言い、複数のアーキテクチャに共通する性質、様式、作法あるいは流儀を指す言葉です。

とあります。

どちらも、いったんはアーキテクチャレベルの話なんだな、という程度の理解で問題ありません。

なお、アーキテクチャスタイルは、日本語で訳すなら「システム方式」が近い言葉になると思われます。



#### 3.2 アーキテクチャスタイルとしてのREST

n層アーキテクチャで、クライアントとサーバが異なるコンピューティングリソースであることが前提。


#### 3.3 リソース

RESTにおける、データの名前とそのデータ表現・状態のこと。

データの名前はURIとして表現される。

リソースはHTML形式で取得する場合もあれば、JSON形式で取得する場合もある。ＵＲＩの最後の拡張子で取得する表現を選択できる。


#### 3.4 スタイルを組み合わせてＲＥＳＴを構成する

[「Webを支える技術」の内容のまとめ」-RESTについて](https://qiita.com/Lassieena/items/0241a4e7933df28a3151#rest%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6) を参照。

##### 覚えておきたいキーワード

- （広義の）[インタフェース](https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9_(%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93)#%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9)

- （ソフトウェアにおける）状態
    - 変数など、メモリ上に展開されるデータのこと。英語でいうステート(State)。状態によって振る舞いが変わる動作のことをステートフルな実装とよんだりする。逆に状態を持たない処理をステートレスな処理と呼ぶ。
    - 通常、ステートフルな処理を並列実行する場合、排他制御も必要になる。ステートレスな処理の場合は、並行処理する場合にはそういう配慮は通常不要。だが状態をRDBなど外に持たせている場合は、その部分についての排他制御などを考慮する必要がある。
    - 関連して、 （ソフトウェアにおける）[副作用](https://ja.wikipedia.org/wiki/%E5%89%AF%E4%BD%9C%E7%94%A8_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0)) も。また、副作用の反対語は？ そしてその意味は？

- セッション
    - ステートレスサーバと言いつつ、状態を管理する場合にはセッションを用いる。セッションとは何か？ 

- マッシュアップ、オムニチャンネル
    - 関連して、モバイルファースト

- [リモートファサード](https://bliki-ja.github.io/pofeaa/RemoteFacade/)、あるいは[腐敗化防止層](https://qiita.com/YasuhiroKimesawa/items/bf22f7a970d5ee29a111)
    - 下記のようなレイヤーのことを特にこのように呼ぶ。
    > 基幹系のレガシーシステムなど HTTP の インタフェースを実装していないシステムでも、レガシーシステムの前に Web アプリケーションサーバを挟んで HTTP のインタフェースを持たせることで、 ブラウザなどのクライアントと接続できる ようになります。

- キャッシュ
    - 不可解な不具合が発生する可能性がある。[こちら](https://qiita.com/nshibazaki/items/f39950a8336fbc83ae7e#%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%81%AF%E9%81%A9%E5%88%87%E3%81%8B)も参照のこと。

- https://qiita.com/shimataro999/items/a6c1ee4708bb2112610e
    - うまく機能するマイクロサービスのプラクティスとして参考になる。

- [SLA](https://ja.wikipedia.org/wiki/%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E6%B0%B4%E6%BA%96%E5%90%88%E6%84%8F)
    - マイクロサービスごとに、どの程度のトラフィックを前提としているのかなどを確認・合意しておく。他部署のサービスにいきなり負荷かけるのは良くない。

- [ITIL](https://ja.wikipedia.org/wiki/Information_Technology_Infrastructure_Library)
    - 勉強しなくてもいいですが、サービス運用のベストプラクティスとか、用語を知っておくと質の高いサービス運用（→DevOps）ができるようになるかも。変更管理、構成管理、問題管理あたり。

### 補題

#### 補題：クラウドサービスにおけるキーワード

- IaaS, PaaS, SaaS
    - コンピューティングリソースの利用モデル。所有より利用。電気、ガス、水道などのインフラと同じ。
    - 要件に応じて、下位レイヤのコントロールをどの程度得たいか？

- エッジコンピューティング

- サーバレス

- マネージドサービス

-　コンテナ：この場合はDockerコンテナ技術を指す
    -　JavaEEサーバにおける○○コンテナのような、JavaEEの特定機能を提供するソフトウェアのことではない。
    -　また、Solarisのコンテナ技術は実現していることは一緒ですが、技術的には関連がないはずです。

#### 補題：分散システムにおけるデータ更新パターン

とりあえず、冪等性、トランザクション（参考文献までは除く。参考文献のところは余力があれば。）、結果整合性、スターバックスは２フェーズコミットを使わない、のところまでをとりあえず抑えたい。
そこから先の話題は難易度上がってくるので、余力があれば取り組みたい。

- 冪等性（べきとうせい）
    - [情報工学における冪等](https://ja.wikipedia.org/wiki/%E5%86%AA%E7%AD%89#%E6%83%85%E5%A0%B1%E5%B7%A5%E5%AD%A6%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E5%86%AA%E7%AD%89)
    > ある操作を1度行っても複数回行っても同じ効果となることを言う。特に、何回行ってもエラーや不整合の状態が変わらない操作を指す。
    - 何度呼んでも問題ないように設計されていること。そのため、処理が不完全に終わってしまっても、システムが復旧してから、もう一回同じ処理を呼ぶだけでデータが完全な状態になるように処理が設計されている。
 
- トランザクション
    - [こちら](https://qiita.com/nshibazaki/items/f39950a8336fbc83ae7e#%E4%B8%A6%E8%A1%8C%E6%80%A7%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B6%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E7%94%A8%E3%81%84%E3%81%9F%E5%80%8B%E6%89%80%E3%81%AF%E3%81%82%E3%82%8B%E3%81%8B) も参照のこと。

- [結果整合性](https://ja.wikipedia.org/wiki/%E7%B5%90%E6%9E%9C%E6%95%B4%E5%90%88%E6%80%A7) (BASEトランザクション)
    - ACIDトランザクションよりも緩いトランザクション
    - [CAP定理](https://ja.wikipedia.org/wiki/CAP%E5%AE%9A%E7%90%86)

- [スターバックスは２フェーズコミットを使わない](https://code.google.com/archive/p/gregors-ramblings-ja/wikis/18_starbucks.wiki)
    - イベント駆動アーキテクチャを身近な例で紹介している。

- [TCCパターン](https://qiita.com/nk2/items/d9e9a220190549107282) と [Sagaパターン](https://qiita.com/yoshii0110/items/4ae10eb071565cb90b37)
    - Sagaパターンは筆者も知らなかった。TCCは聞いたことある。
    - イベント駆動アーキテクチャ（「ソフトウェアアーキテクチャの基礎」の２種類のトポロジー。ブローカーがSagaパターンに近く、メディエーターはTCCパターンが近い。）
    - 補償トランザクションとは？
    - TCCはApache Camel や Mule ESBのようなメディエーターを使うパターン（上記TCCの記事ではコーディネーターと記載）。
    - SagaパターンはApache ActiveMQやRabbitMQのようなメッセージブローカーを中心に使うパターン。

- [分散トランザクション](https://qiita.com/j-nishitani/items/c8deefd151de0f4e49b0#2phase-commit%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%8B)
    - 分散システムにおいてACIDトランザクションを保証する必要があるときにとる選択肢。[2フェーズコミット](https://qiita.com/hharu/items/8f429590caac90fee7ea)。
    - 配信保証（再送など）、順序保証の要件があるときもトランザクショナルにする必要がある可能性がある。
    - 分散トランザクションの登場人物
        - TPモニタないしはTM（トランザクションモニタないしはトランザクションマネージャ）
        - RM（リソースマネージャ）
            - RDBとMQ
        - ２フェーズコミットにおけるSPoF（単一障害点）はどこか？