GitLabがRuby on Railsを使い続ける理由(翻訳)
Ruby on Railsを作ったときのDavid Heinemeier Hansson(DHH)が道しるべとしたのは、それまでに経験していたPHPとJavaでした(インタビュー)。DHHにとって、JavaのWebフレームワークはJavaが冗長で柔軟性が低く使いにくい点が好みでなかったものの、構造的に統一されている点が高く評価できるものでした。一方、PHPについては敷居の低さが好みだったものの、プロジェクトが泥沼化しがちな点をあまり好んでいませんでした。
- Java
- 使いにくい、構造化されている
- PHP
- 使いやすい、泥沼化しがち
敷居は低いが泥沼化する方と、構造化が進んでいるが使いにくい方という、2つの毒杯のどちらか1つを選ぶしかないかのようです。そういえば昔は、Unixのようなサーバー級OSは安定性に優れているが使いにくく、WindowsやmacOSのようなクライアントOSは使いやすいがしょっちゅうクラッシュするという区分けがなされていたものです。
以前は誰もがこの二律背反を諦めのうちに受け入れていましたが、NeXTが優美で使いやすく、バターのように滑らかなGUIを世に送り出してから状況が変わりました。今やその「サーバー級」のUnixが、美しいGUIデスクトップはもちろん、ほとんどのスマートフォンやスマートウォッチをも動かしています。
こうして、使いやすいものがクラッシュしやすかったのは歴史的な理由でたまたまそうだったに過ぎず、実際には関連がないことがわかってきました。Webフレームワークの取っ付きのよさと泥沼化についても同じことが言えます。取っ付きのよさと泥沼化は、互いに独立した軸なのです。
使いにくい | 使いやすい | |
---|---|---|
泥沼化しがち | PHP | |
構造化されている | Java |
これらの軸を互いに独立させてみると、ちょうど右下の欲しい部分に空きができます。ここに入るのは、使いやすく構造化されたWebフレームワークです。
Rubyは、堅牢でメタプログラミング可能なSmalltalkの流れを汲んでおり、Unixとの統合にも優れています。Rubyのこうした特性によって、Railsの作者であるDHHが表右下の欲しい部分をRailsで埋めるのに申し分ない言語であることが明らかになりました。
使いにくい | 使いやすい | |
---|---|---|
泥沼化しがち | PHP | |
構造化されている | Java | Ruby on Rails |
GitLab共同創業者のDmitriy Zaporozhetsは、彼自身を含む誰もがバージョン管理サーバーを動かせるソフトウェアに取り組んでみたいと考えていた頃、PHPの経験も積んでいたにもかかわらず、慣れ親しんだPHPにとらわれずにRailsを選んだのです。
DmitryがRailsを選択したのは先見の明か偶然だったのかはわかりませんが、DHHがRailsの目標である「親しみやすさと優れたアーキテクチャの両立」を達成できたことも追い風となって、Railsを選択したことはGitLabにとって大変有益なものとなりました。
モジュール性が望ましい理由
上のセクションではモジュール性が望ましい性質であることを仮定していますが、既に見たように単に仮定するだけでは危険です。なぜモジュール性が望ましいのでしょうか?そしてモジュール性が実際に望ましいのはどのような状況でしょうか?
1971年の論文『On the Criteria to Be Used in Decomposing Systems into Modules』(David L. Parnas)は、モジュラーシステムには以下の(望ましい)メリットがあると指摘しています。
- 開発グループが担当モジュールに専念でき、互いにやり取りする必要がほとんど生じないため、開発期間が短縮される
- 他のモジュールを変更せずにモジュールを大幅に改修することが可能になる
- システムを1モジュールずつ調査することが可能になる
開発グループ間のコミュニケーションを削減することの重要性については、後にFred Brooksも『人月の神話』で強調しています。「進捗の出ていないプロジェクトに人を追加するとさらに遅れる」ということわざが真実である主な理由として、人数が増えるとコミュニケーション上のオーバーヘッドが増大することが挙げられています。
マイクロサービスは不要
一般にモジュール性は、誰もが欲しくてたまらないものでありながら、手に入れるのがとても難しいものでもあります。ほとんどのシステムのデフォルトアーキテクチャは、言ってみれば巨大な泥団子も同然です。そういうわけで、現存する最大のソフトウェアシステムであるWorld Wide Webから設計者たちがインスパイアされたことを理解できます。World Wide Webは必然的にモジュール化され、それ以外の形で機能しようがないからです。
プロセスの異なるローカルソフトウェアを編成する方法(RESTアーキテクチャスタイルで組み合わせたマイクロサービス)は、OSを介して強制的にモジュール境界を区切るには良いのですが、コストがかなり高く、モジュール性を得る手法としては非常に強引です。
今や、無料の分散システムを運用する難しさとコストは著しく跳ね上がっています。有名な「分散コンピューティングの落とし穴」でもパフォーマンスや信頼性が低下する問題に言及しています。要約すると、決して失敗せずにナノ秒単位で処理できる関数呼び出しが分散されると、3〜6桁遅いネットワーク操作に置き換えられた挙げ句失敗するようになり、パフォーマンスと信頼性が大きく損なわれます。ツールのサポートが乏しい状況で複数のサービスにまたがる障害をトレースしなければならなくなると、障害の診断が非常に難しくなります。
マイクロサービスをまともに運用するには、相当スキルの高いDevOpsチームが必要です。これほど高度なスキルが必要な規模で運用すればマイクロサービスによる違いは実際にはほとんど生じませんが、これを読んでいるあなたがGoogleの中の人ではない可能性は非常に高いでしょう。
仮にこれらをすべて管理することが可能だとしても、問題の根源となる本質的な複雑さの上に、さらに分散による偶然の複雑さも積み上げられる点に注意しておくことが重要です。マイクロサービスは複雑さを軽減することはありません。そのうえ、期待していたモジュール性の改善もまるで保証されず、代わりに分散バージョンの泥団子の出来上がりです。
モノリスRails
Railsが優れたアーキテクチャを使いやすく生産性の高いものにしてくれたおかげで、GitLabはモジュラーモノリスを開発することが可能になりました。モジュラーモノリスは分散泥団子と正反対のアプローチです。構造化され、アーキテクチャが整備され、シングルプロセスとして実行される高度にモジュラーなプログラムであり、しかも可能な限り(いい意味で)「退屈なソリューション」になっています。
GitLabをモノリスとして構成することは私たちにとって計り知れないメリットがありますが、この構成を独善的に押し付けることはしません。アーキテクチャはニーズに沿うものであって、ニーズがアーキテクチャに沿うのではありません。Railsは私たちの目的において優れた技術ですが、それでもいくつかの欠点があり、パフォーマンスの問題もその1つです。しかし幸いなことに、パフォーマンスが実際に重要な部分はコードベースのごく一部です。私たちの場合、git操作についてはGo言語で内製したgitalyデーモンを使い、リポジトリに関係ない永続性についてはPostgreSQLを使っています。
オープンコア
おしまいに最も重要な点として、GitLabのモジュラーモノリスは「オープンコアモデル」というオープンソースソフトウェアで収益を得るためのビジネスモデルを、単なる理論から現実の利益に転じたことを述べておきます。これはRailsの力だけでできることではなく、素晴らしいコントリビューターやエンジニアの方々のおかげであることはもちろんですが、Railsが適切な土台を築いているからでもあります。
オープンソースソフトウェアから真の利益を得るには、コントリビューターが利用できるソースコードが扱いやすいものでなければなりません。さまざまな方面から貢献を受けてもアーキテクチャの整合性が崩れないように維持し、オープンなコンポーネントとクローズドコンポーネントの間に明確な境界線を引くには、コードが極めて高度に構造化されていなければなりません。これは「毎度おなじみのお説教」でしょうか?
適切なプラグインのインターフェイスを使う方がよいのでしょうか?それともマイクロサービス上にモデリングされたサービスインターフェイスにする方がよいのでしょうか?答えはどちらもNoです。どちらのアプローチも、「ソースコードを少し変更するだけで」デプロイや統合のハードルが上がってしまううえに、アーキテクチャに加える制約が厳格すぎることもしばしばです。将来どこが拡張されるかを事前にすべて予測するのは愚かの極みです。幸い私たちはそんなことはしていませんし、その必要もありません。
平凡なモジュラーモノリスを採用することで、多くのユーザーやサードパーティ開発者もコアプロダクトの機能強化に貢献できるようになり、驚異的なペースとスケーラビリティで技術革新が促進されるのです。
概要
原著者の許諾を得て翻訳・公開いたします。