第3部 過剰な自由と、壁の破壊 2009-2014
3本の線 — 言語・データ・アーキテクチャ — が同時に「制約を捨てる」方向へ振れ、3つとも授業料を払った時代。しかし4本目の線だけは違う。DevOps はこの時代に創設された。 過剰の時代は、同時に壁の破壊の時代でもあった。
言語 — 動的の絶頂と、最初の反省
Section titled “言語 — 動的の絶頂と、最初の反省”動的言語は絶頂を迎える。Node.js(2009)は JavaScript をサーバーへ持ち込み、「1言語で全部」の夢を見せた。npm(2010)は小さなパッケージを無数に組み合わせる文化を作り、その文化は後に left-pad 事件(2016)とサプライチェーン攻撃という傷を残す。
一方でマルチコア危機 — 2005年頃からクロックが上がらず、コア数だけが増える — が並行性を言語の主戦場に変えた。Herb Sutter の「The Free Lunch Is Over」(2005)がその宣言だ。スレッドとロックで書く並行プログラムは、人間が毎回注意してデッドロックとデータ競合を避ける規約の世界だった。メッセージパッシングの Erlang(1986年生まれ)が再評価され、そして Go(2009) が現れる。Go は二重の意味で時代への回答だった。CSP(Hoare、1978)による並行性の一級市民化(goroutine と channel)と、動的言語の疲れへの反省。静的型だが軽量、高速コンパイル、gofmt で書き方が一通りに収束する言語設計。「書き方を選ばせない」という選択は、第5部の「開発者は何も選ばない」の先駆である。
データ — 「スキーマレス=自由」の第二次授業料
Section titled “データ — 「スキーマレス=自由」の第二次授業料”Web 企業の規模が RDBMS の垂直限界を超え、NoSQL 爆発が起きる。理論的支柱は2つの論文だ。Google の BigTable(2006)は「行キーでソートされた巨大なマップ」を、Amazon の Dynamo(2007)は「常に書けるキーバリューストア」を示した。Dynamo 論文の動機は明快で、ショッピングカートはどんな障害中でも商品を追加できなければならない。一貫性より可用性。矛盾は後でマージする(ベクタークロック)。Cassandra(2008、Facebook)と MongoDB(2009)が実装を民主化した。
Brewer の CAP 定理(2000年の講演、2002年に証明)が流行語になった。分散システムは一貫性・可用性・分断耐性の3つを同時には満たせない。しばしば誤読された。「3つから2つ選べ」ではない。分断は選べない(起きる)ので、分断中に一貫性と可用性のどちらを捨てるかだけが選択である。Brewer 自身が2012年に「12年後の CAP」でこの誤読を正した。そして「スキーマレス」は自由の同義語として売られた。マイグレーションは要らない。フィールドを足したければ足せばよい。第2部の ALTER TABLE の恐怖を知っていれば、これがどれほど魅力的に聞こえたか分かる。
授業料は数年で請求された。スキーマは消えていなかった。アプリケーションコードの中に、暗黙のまま散乱しただけだった。 どのドキュメントにどのフィールドがあるかは誰も保証せず、2012年に書かれたドキュメントと2014年に書かれたドキュメントは形が違い、読む側は全世代の形を知っていなければならない。結果整合の読み取りは「たまに古い」バグとして表面化し、トランザクションを失った代わりにアプリ側で補償処理を手書きすることになった。構造を捨てた分の負債が、構造のない場所に積もった。
アーキテクチャ — 分散の民主化
Section titled “アーキテクチャ — 分散の民主化”Netflix が2008年の大障害(DB 破損で3日間 DVD を発送できなかった)を契機に、モノリスの解体と AWS への移行を公開で進めた。Hystrix(サーキットブレーカー)、Eureka(サービス発見)、Chaos Monkey(本番でサーバーをランダムに止める)。これらは全部、第1部の8つの誤謬を「信じない」ための道具である。ネットワークは信頼できないという前提を、コードに埋めた。
2014年、Fowler と Lewis がマイクロサービスと命名した。9つの特徴のうち、歴史的に重要なのは3つだ。コンポーネント化はサービスで(ライブラリではなく、独立にデプロイできるプロセス)、賢いエンドポイントと土管のパイプ(ESB への直接の反論)、分散データ管理(サービスごとに DB を持つ)。これは SOA の否定ではない。Don Box の4テネットを、ESB と WS-* を捨ててやり直したものだ。当時「SOA done right」と呼ばれたのは正確だった。
実行基盤が同時に揃った。Docker(2013)が「どこでも同じように動くプロセス」を、Kubernetes(2014、Google の Borg の公開版)が「それを大量に並べて動かす基盤」を与えた。12-factor app(2011、Heroku)がクラウドネイティブの規約を与えた。設定は環境変数に、プロセスはステートレスに、ログは標準出力に。
分散サービスの思想史 — 境界をどこに引くか
Section titled “分散サービスの思想史 — 境界をどこに引くか”マイクロサービスの命名は「どう分けるか」を語ったが、「どこで分けるか」は別の系譜が答えを持っていた。Eric Evans の『Domain-Driven Design』(2003)である。その中でも境界づけられたコンテキスト(Bounded Context)。「顧客」という語は、販売と請求とサポートで意味が違う。全社で統一しようとすると、誰にも合わない巨大なモデルになる(第2部の神クラスの、組織版)。だから語彙が同じ意味を持つ範囲でモデルを区切り、区切りの間は明示的に翻訳する。これは Parnas(変わりそうな判断を隠す)と Conway(会話の形が境界になる)の接合点である。マイクロサービスの境界は、DDD のコンテキスト境界に揃えろ — これが2014年以降の共通了解になった。
データを分けると、トランザクションが境界を跨げなくなる。ここで古い論文が復活する。Garcia-Molina と Salem の Saga(1987)。長いトランザクションを短いローカルトランザクションの列に分け、途中で失敗したら、それまでの各ステップの「補償トランザクション」を逆順に実行する。ロールバックはない。取り消しという業務操作があるだけだ。Pat Helland の「Life beyond Distributed Transactions」(2007)は、この世界観を正面から肯定した。無限にスケールするなら、2フェーズコミットは諦めろ。エンティティの中でだけトランザクションを許し、エンティティ間はメッセージで結ぶ。メッセージは重複して届くので、受信側は冪等でなければならない。
ここまでを並べると、分散サービスの思想は4つの層に整理できる。
| 層 | 問い | 答えを出したもの |
|---|---|---|
| 前提 | ネットワークを信じてよいか | 8つの誤謬(1994)、分散オブジェクト第一法則(2002) |
| 単位 | 何を分散の単位にするか | SOA の4テネット(2004)、API mandate(2002) |
| 境界 | どこで切るか | DDD の境界づけられたコンテキスト(2003)、Conway(1968) |
| 整合 | 境界を跨ぐ変更をどう整合させるか | Saga(1987)、Helland(2007)、CAP の正しい読み(2012) |
4層のどれを飛ばしても失敗する。1990年代は前提を飛ばした。2000年代の SOA は単位は正しく、実装で賢さをバスに集めた。そして2010年代の新しい失敗形は、境界と整合を飛ばしたものだ。
分散モノリス — 分散の代金だけ払う
Section titled “分散モノリス — 分散の代金だけ払う”サービスに割ったのに、同時にデプロイしないと動かず、DB を共有し、同期呼び出しが鎖のように連なる。サービス A が B を呼び、B が C を呼び、C が落ちると A が落ちる。レイテンシは鎖の長さの合計になり、可用性は鎖の各環の積になる(99.9% のサービスを10個直列にすると 99.0%)。これが分散モノリスである。分散の代金だけ払って、独立性を得ていない。
左も右もサービスは3つ。違いはサービスの数ではなく、DB を誰が持ち、呼び出しが同期の鎖か土管を通るイベントかである。
なぜ起きたか。境界を引く技術(ドメイン設計)より先に、境界を切る技術(コンテナ)が普及したからだ。 Docker は午後に覚えられるが、境界づけられたコンテキストを見つけるにはドメインを理解しなければならない。モノリスをディレクトリごとにコンテナに入れると、モノリスの内部結合がそのままネットワーク呼び出しになる。第1部の分散オブジェクトと同じ失敗を、今度は HTTP で繰り返した。
組織 — DevOps の創設(この線だけは過剰ではない)
Section titled “組織 — DevOps の創設(この線だけは過剰ではない)”2009年6月、Velocity カンファレンスで Flickr の John Allspaw と Paul Hammond が「10+ Deploys Per Day: Dev and Ops Cooperation at Flickr」を発表する。1日10回デプロイする。CAB の世界観では狂気の沙汰が、壁を壊した協働では日常だという実演。講演の後半は道具ではなく文化の話だった。尊敬、信頼、失敗への健全な態度、非難を避けること。聴衆の中にいた Patrick Debois が同年10月、ベルギーの Gent で最初の devopsdays を開き、DevOps という言葉が生まれた。
Humble と Farley の『Continuous Delivery』(2010)がデプロイパイプラインを体系化した。コミットから本番までを自動化されたステージの列にし、すべてのコミットをリリース候補として扱う。Infrastructure as Code(Puppet 2005、Chef 2009)が「サーバー構築という職人技」をコードに変換した。手順書を読んで人が構築するのではなく、コードが構築し、コードはバージョン管理され、レビューされ、テストされる。そして Etsy の blameless postmortem(2012、Allspaw)が障害対応の文化を反転させた。人を責めるのをやめ、システムを直す。 ミスをした人は、その時点で持っていた情報では合理的だったと仮定する。責めると情報が隠され、同じ事故が繰り返す。個人の注意力に依存する安全は安全ではない、という思想の運用版である。
他の3線が「自由へ振れて授業料を払った」まさにその時期に、組織の線だけは「壁と申請書」から「協働と自動化」への創設期だった。この非対称は覚えておく価値がある — 4線は常に同期しない。だからこそ編んで読む意味がある。
greenfield の現在形: internal-03 の3分岐(同期コマンド/Eventual/ReplicaView)は「分散を選ぶ前の質問表」であり、分散モノリスの予防装置。「分散はプロダクト境界(アカウント境界)でだけ」は第一次・第二次授業料の答え。outbox/inbox/冪等キー(#8/#9/#11)は、Saga と Helland の世界観を規約として前払いしたもの。メッセージは重複して届くという前提を、毎回思い出さなくてよい形にしてある。