はじめに
HTTPやSMTP、HTML、CSS、XML、JSONなどWebを支える基礎的な技術は、比較的単純な仕様で構成されているため、Webサービスはどのようなプログラミング言語を使っても開発することが可能です。かつてはC言語とSQLだけで開発し、それをApacheのモジュールとしてコンパイルすることでWebサービスとして稼働する構成も、そうめずらしくありませんでした。現在ではPHP、Ruby、Perl、Go、Java、Scala、Kotlin、JavaScriptと言語の種類は豊富にありますし、そこにRDBMS、NoSQL、アプリケーションサーバ、フレームワーク、外部APIサービス、クラウドインフラサービスのことまで考えると、Webサービスを開発するために必要な構成要素の組み合わせは、無限と言っても過言ではないでしょう。
Webサービスは利用者に便利に使ってもらい、利用者あるいは広告主から対価をいただくことによって事業として成立します。しかし、エンジニアはつい興味本位で新しい技術に飛びついてしまいます。私も例外ではありません。趣味としてWebサービスを開発するのであれば、好きなように技術を選択して乗り換えることもできますが、事業としてスケールさせるとなると、そうはいきません。
株式会社ビズリーチの主力事業、ビズリーチシステムのメイン言語はJavaです。本稿では、社内で最も古くからあるシステムの1つをJavaで開発し、事業として顧客に提供し続ける中で培ってきた戦略と技術を、前後編にわたって紹介します。
Twelve-Factor App
いきなりの聞き慣れない単語に戸惑う方もいらっしゃるでしょう。「The Twelve-Factor App」とは、Adam Wiggins氏(当時のHeroku社CTO)が提唱した、Webサービスを開発するための原則です。 この戦略はJava言語に限定した話ではありません。こちらのサイトで現在も公開され、日本語を含む13か国語に翻訳されています。
最初に提唱されたのは2011年ですが、個人的には2017年現在も色あせていないと感じます。「あのツールが便利らしい」「このフレームワークも便利そうだ」といってあれこれ調べたり試したりするうちに「このツールの設計思想はThe Twelve-Factor Appのあの章に書いてあったことに通じるものがある」と感じることがめずらしくないためです。12章もあるのですが、実際はすべて短い文章とサンプルが書いてあるだけの論文です。全て読み切るのに30分とかかりませんので、ぜひ一度目を通してみてください。
ビズリーチシステムは、12-Factor App戦略がまだ存在しないか、知られていない時期から開発と運用が続いています。だからといって、その後に提唱されたこの戦略に沿えないわけではありませんでした。プロダクトを少しずつ改善してゆくなかで、全12章のうちのどれかだけでも適用すればよいのです。章の順番を気にする必要もありません。
ここからは、12-Factor App戦略のなかでもビズリーチシステムで大切にしてきたデプロイ戦略、ログ出力、テスト、バージョンアップについて言及します。
デプロイ戦略
あらかじめインストール済みのTomcatやWebLogicなどに向かってwarファイルをデプロイするのが、Java/Webアプリケーションの標準的なデプロイ戦略です。しかし、12-Factor App戦略では、そうした手法は推奨されていません。The Twelve-Factor Appの第7章「ポートバインディング」では、こう説明されています。
Twelve-Factor Appは完全に自己完結し、Webに公開されるサービスを作成するために、コンテナが実行環境にWebサーバーランタイムを注入することを頼りにしない
難解ですが、ご安心ください。引き続きこんな例も書かれています。
これは一般に、依存関係宣言を使ってWebサーバーライブラリをアプリケーションに追加することで実装される。Webサーバーライブラリの例として(中略)Javaやその他のJVMベースの言語におけるJettyなどがある。
なるほど、「アプリケーションサーバが必要なのであればJettyのような内部組込型を使いましょう」ということです。
ビズリーチシステムではJettyではなくtomcat-embedを選択しました。
Tomcat tomcat = new Tomcat();
といったコードが
public static void main(String ... args){}
というエントリーポイントから呼び出されるように書かれています。Tomcatの上でアプリケーションが動くのではなく、アプリケーションの中でTomcatが動きます。これによって、デプロイ先のサーバ上にはあらかじめTomcatが存在する必要はなく、JREさえあればよいことになります。
また、The Twelve-Factor Appの第2章「依存関係」には「Twelve-Factor Appは、いかなるシステムツールの暗黙的な存在にも依存しない」とあります。この原則に沿うとJREすらもアプリケーションの一部として捉えるべきだということになります。CIサーバ上でのアプリケーションのビルド過程で、MavenやGradleによるwar/jarファイルの生成だけでなくJREと起動スクリプトまで含めたアプリケーション構造の全体をzipなどでパッケージングし、サーバに設置・解凍したら、同梱しているシェルスクリプト1本で起動できるようにすべきです。さらにはDockerのようなコンテナ型仮想化技術の利用にもつながっていくでしょう。