100万行オーバーのモノリシックRailsアプリをマイクロサービス化したクックパッドの手順

マイクロサービスの導入事例を、中の人が徹底的に語ります。クックパッドでは、100万行オーバーの超巨大なRuby on Railsアプリのマイクロサービス化に挑みました。アプリをいかに分離し、連携できるようにするか、など、同社が採ったマイクロサービス化の戦略を聞きました。

100万行オーバーのモノリシックRailsアプリをマイクロサービス化したクックパッドの手順

サービスを構成するシステムを分散・細分化するマイクロサービスアーキテクチャ。この手法を導入する企業は、徐々に増えています。しかし、マイクロサービス化のためのベストプラクティスを見出すのは難しいでしょう。どの企業も手探りの状態で、アーキテクチャ改善の取り組みをしているのが現状です。

では、巨大なサービスを持つ有名IT企業は、どうやってマイクロサービス化を推進してきたのか。その手法を学ぶことで、「マイクロサービス化を行うための道しるべ」が見えてくるのではないでしょうか。今回は、料理レシピ投稿・検索サービスクックパッドの「お台場プロジェクト」と呼ばれる事例を掘り下げます。

聞き手を務めるのは、株式会社ウルフチーフの代表取締役であり、アーキテクチャ設計のスペシャリストでもある川島義隆さん。話し手は、「お台場プロジェクト」の発起人である青木峰郎さんと、プロジェクトリーダーである外村和仁さんです。

「世界最大のモノリシックRuby on Railsサービス」とも言われているクックパッドを、細分化するための手法に迫ります。

1
外村 和仁(ほかむら・かずひと) 2hokaccha 3hokaccha(写真右)
ソーシャルゲームのバックエンド開発やWebフロントエンドの開発業務を経験後、2015年にクックパッドに入社。レシピサービスのサービス開発に数年携わった後、現在は技術部クックパッドサービス基盤グループにてモノリシックで巨大なRailsアプリケーションのアーキテクチャ改善業務に従事している。著書に『ノンプログラマのためのJavaScriptはじめの一歩』など多数。
青木 峰郎(あおき・みねろう)(写真中央)
ふつうの体育会系プログラマー。大学在学中にRubyをはじめとしたOSS開発にどっぷりつかる。2007年より並列分散RDBMSベンダーに勤務、並列処理に目覚める。2013年にクックパッド入社(現職)、データ分析サービス「たべみる」をエンジニアほぼ1人で実装。現在は技術部データ基盤グループに所属し、全社共通データ分析基盤の構築リード、お台場プロジェクトPMなどを幅広く手掛ける。『ふつうのLinuxプログラミング』『10年戦えるデータ分析入門』はじめ著書多数。
川島 義隆(かわしま・よしたか) 4kawashima (写真左)
株式会社ウルフチーフ 代表取締役。TIS株式会社にて19年半、様々な業種のシステムアーキテクチャ設計を担当し、2018年に退職、株式会社ウルフチーフを創業する。以降流しのアーキテクトとして、前職時代から書き溜めていたOSSプロダクトや技術記事を元に、様々な現場でアーキテクチャの設計や研修を実施している。

Ruby on Railsのバージョンアップに1年かかっていた

川島:今回のインタビューでは、「お台場プロジェクト」についてのお話を伺いたいです。このプロジェクトは何を目指したものだったのでしょうか?

外村 「お台場プロジェクト」は、cookpad_allというリポジトリのアーキテクチャ刷新・改善を目指したものです。これは、クックパッドが cookpad.com のドメインで提供しているレシピサービスです。みなさんが、いわゆる「レシピサービスのクックパッド」と聞いてイメージするものになります。

cookpad_allのリポジトリ内には、WebアプリケーションやAPIサーバ、管理画面、バッチなどのシステムが含まれています。これらのコード一式が「世界一のモノシリックRuby on Rails(以下、Rails)サービス」と呼ばれているものです。

コード行数としては、Rubyのコードが約27万行(テストを除く)、テストコードが約51万行、HTMLテンプレートが約14万行。つまりトータルで100万行ほどありました。

5

川島:アプリケーションが巨大であるがゆえに、「お台場プロジェクト」の推進前は開発・運用において大きな課題を抱えていたそうですね。どのような課題があったのですか?

青木 アプリが巨大すぎるため、cookpad_allに大規模な機能追加・変更ができないことが本質的な課題でした。あるコードを変更すると、意図しない箇所の機能が動かなくなってしまうんです。ライブラリのバージョンも迂闊には上げられません。依存が多すぎるため、更新がトリガーになって機能がおかしくなるケースがあるためです。

それから、Railsのバージョンアップが難しいことも大きな課題でした。バージョン2からバージョン3へのメジャーアップデートが一番きつくて、確か3~4人で1年くらいかかりました。3から4はもう少しマシでしたが、それでも1人が専任で半年はかかっていましたね。

川島:それは大変だ……。

外村 Railsが後方互換性のない機能更新を行ったことが原因で動かなくなるケースもありますし、アップデートに起因するエッジケースのバグを踏んでしまうケースもあります。それに、Railsのアップデートに追従していない古いgemが壊れたり、gemにモンキーパッチを当てて運用していたものが使えなくなったり。

これほど大きなRailsアプリケーションだと、バージョンアップに伴って数え切れないほどの問題が発生します。作業は一筋縄ではいきません。ようやく上げきった頃には、また次のバージョンが出ている、というくり返しでした。

6

川島:その状態では、永遠にバージョンアップの作業が続きそうですね。

青木 そうした課題を解決するために「お台場プロジェクト」はスタートしました。まずやったのは「改善したいことをリストアップする場所」としてGitHubにリポジトリを作ることでした。その活動が少しずつ実を結んでいき、マイクロサービス化に結びついていきます。

外村 つまり、もともとこのプロジェクトはマイクロサービス化を主眼にしたプロジェクトではなかったんです。あくまで巨大なモノリシックサービスを開発・運用する辛さを軽減するためのプロジェクトで、その手法のひとつとしてマイクロサービス化が有効だとわかった、という流れでした。

【マイクロサービス化戦略】まずはコードを減らすことから

川島:どのような部分から「お台場プロジェクト」を進めましたか?

青木 まず、辛さの根本原因を明確にするために、社内のさまざまなエンジニアに話を聞きました。全員が言っていたのが、コード量が多すぎるということです。

外村 そこで、まずは「いかにしてコード量を少なくするか」を主眼に置いて動きました。いらない機能や使われていない機能を探して、消していったんです。

青木 マイクロサービス化を行う際には、「機能をどう分割するか。何から着手すべきか」の議論が必ず起こりますし、社内調整にも苦労します。一方で、使われていない機能の廃止はメリットしかないので、反対意見も挙がりません。つまり、“プロジェクトの第一歩”に向いた作業なんです。

川島:とはいえ、使われていないコードを探すのも大変な作業ですよね。使われているコードを間違って消してもいけないですし。どのようにして、作業を進めていきましたか?

青木 本番環境で使われていないコードを、ツールで自動判定できれば作業が楽になります。そこで、「お台場プロジェクト」のメンバーとクックパッドのフルタイムRubyコミッターである笹田耕一さん、遠藤侑介さんで話し合い、どういう機能があるとコード削除に便利かを一緒に考えていきました。いくつかの機能を試し、最終的にできたのが「oneshot coverage{$annotation_1}」というRubyの新機能です。

この機能をオンにして一定期間測定することで、コードが実行された箇所のカバレッジを取ることができます。また、一度特定の箇所を通ったら二回目は計測されなくなるため、処理性能もほとんど劣化しません。

川島:Rubyを用いてサービス開発している企業にとって、このツールは汎用的に導入できそうですね。

【マイクロサービス化戦略】アプリ固有のバッドノウハウを減らす

川島:他にはどのようなことを実施しましたか?

青木 コード削除とほぼ同じタイミングで実施したのが、アプリケーション構造の整理です。cookpad_allはかつて、「動作モード」と呼ばれるトリッキーな実装がされていたんです。この「動作モード」をなくすことに取り組みました。

川島:「動作モード」とは何ですか?

青木 ひとつのRailsアプリケーションが、動作しているホスト名に応じてWebアプリケーションになったり、APIサーバーになったりするという変わった仕組みです。ひとつのアプリの中にWebアプリとAPIサーバーの設定が混在しているので、どの設定がどちらのものかを調べるのにも一苦労でした。

7

青木 ローカル環境でアプリを動かすのも大変でした。ホスト名を見てモードが切り替わるんですが、ローカル環境のホスト名は基本的にlocalhostじゃないですか。だから、localhostに別の名前を付けなければ、モードを切り替えられないという独自のノウハウがありまして。

川島:独自仕様を詳しく知らないと、開発がそもそもできないですね。

青木 はい。その状態はなかなか辛いので、構造をすっきりさせることにしました。

川島:どのようにして分割していったのですか?

青木 「動作モード」の削除にあたっては、アプリケーション本体のコードが機能単位でディレクトリ分割されていたことが幸いしました。命名を元に分離を行うことができたからです。APIサーバーは独立したアプリケーションにして、さらに古いAPIサーバーのコード削除も合わせて実施したことで、アプリケーション構造をすっきりさせることに成功しました。

8

外村 cookpad_allは10年以上も運用されていたため、歴史があるからこそ独自の運用ノウハウが蓄積されていたんです。その辛さを改善することが、このフェーズでは重要視されていました。

青木 「できるだけ普通のRailsアプリケーションにしよう」というキャッチフレーズで、プロジェクトを進めていましたね。

【マイクロサービス化戦略】まずは分離しやすい部分からお試しで

青木 次フェーズとして、cookpad_allからスマホアプリのA/Bテストなどに使われている機能を分離しました。この時点では、マイクロサービス化を行うかどうかは決めかねていたため、まずは試験的に、私が当時所属していたチームの持っていたシステムを分離する方針をとったんです。

川島:最初に分離する機能の候補はいろいろあったと思いますが、その機能を選んだ理由は何ですか?

青木 いくつか理由がありました。ひとつは、その機能はトータルのコード行数が1000行もない、ごく小さなAPIであったことです。依存ライブラリの種類も少なく、APIの数も2~3個くらいでした。しかも利用しているデータベースはRedis1個だけで、そのRedisは他サービスからは使われません。APIの独立性も高くcookpad_allとの通信もありませんでした。

川島:さまざな面で、分離するには都合のいいものだったわけですね。

9

青木 その機能の分離がうまくいったことで、サービス分割(=マイクロサービス化)が実現できそうなことや、分離に成功すればアプリケーションの大幅な機能変更も容易になることの道筋が立ちました。

青木 余談ですが、実はクックパッドは3~4年ほど前、マイクロサービス化に失敗しているんです。正確には、課金や広告配信などのシステムは綺麗に分離できたんですが、それ以外のシステムにおいて良くないサービス分割をしてしまいました。

分離したけれどうまくいかず元に戻したり、分離したことでかえって開発・運用の手間が増える事態が多発しました。「お台場プロジェクト」の初期フェーズでマイクロサービス化を主眼として打ち出さなかったのは、そのときの経験から「マイクロサービスは良くないのでは」という雰囲気が社内にあったためです。

川島:なぜ、当時はマイクロサービス化に失敗してしまったのだと思いますか?

青木 もっとも連携の多い部分を切ろうとしたからでしょうね。分割を行う前に「どの部分を分割すべきか」をまず分析すべきだったんですが「これからはマイクロサービスが主流だ。どんどん分割しよう」と進めてしまったのがよくなかった。

マイクロサービス化に着手する場合、最初はまず分離しやすい部分から手をつけるのが良いと思います。

【マイクロサービス化戦略】データベースが切れていればサービスも切りやすい

エンジニアHubに会員登録すると
続きをお読みいただけます(無料)。
登録のメリット
  • すべての過去記事を読める
  • 過去のウェビナー動画を
    視聴できる
  • 企業やエージェントから
    スカウトが届く