クックパッド開発者が明かしたマイクロサービス“切り出し”の実際とは?

2015年9月26日に開催された「Seasar Conference 2015」のセッション「【世界最大級】クックパッドの Microservices 化【WIP】」を聴講しました。マイクロサービスに関するコラム記事を書いた後でしたので、この話題が気になっていたのです。結果として、現場の開発者による生々しい話を聞くことができました。「等身大のマイクロサービス切り出しの現場」と言えばいいでしょうか。

【世界最大級】クックパッドの Microservices 化【WIP】
【世界最大級】クックパッドの Microservices 化【WIP】

講演者はショウジヨシオリさん。現在、クックパッドで開発者として働いています。

クックパッドのシステムは、「世界最大級のモノリシックRailsサービス」として知られています。今回は、その一部をマイクロサービスに切り分ける経験を語りました。講演資料が次のリンクから見られます。
https://speakerdeck.com/yoshiori/go-in-to-microservices-wip

講演資料では、規模感を示す数字として、Ruby on RailsのModelのクラス数が1851個であることを取り上げています。「Railsを知らない人は、Modelのクラス数=テーブルの数だと思ってもらえれば」(ヨシオリさん)。この数字からもわかるように「鬼のようにでかい」システムが動いています。

ビジネス領域で「縦に切る」か、機能で「横に切る」かを考える

最初に考えたことは「このシステムをどう切り分けるか」でした。一つの方法はビジネス領域の境界で「縦に切る」ことです。今回の講演では、この「縦に切る」やり方の例として「動画配信サービス」を切り出した経験について報告しました。

モノリシックな構成

もう一つの切り出し方は、機能の境界で「横に切る」やり方です。複数種類のサービスから共通の機能を切り出してAPIで呼べるようにする「Everything as a Service」の考え方です。講演ではマイクロサービスへの切り出しを実施するときに

「縦に切っているのか、横に切っているのか」

このことを必ず意識しないと混乱する、と指摘しました。

縦に切る

ドメイン問題とキャッシュ戦略問題が発生

「動画配信サービス」の切り出しは、実際にやってみると「結構大変」だったそうです。大きな問題として、(1) ドメインとクッキーの問題、(2) キャッシュ戦略の問題の2つを取り上げて紹介しました。

動画配信サービスを本体とは別のサービスとして切り出す場合、切り分けたサービスを(a)本体と完全に同一ドメインに置くか、(2)本体のサブドメインに置くか、(3)完全に別のドメインに置くか、という3種類の選択肢があります。実際には、この3種類の選択肢を全部試してみたそうです。

(a)の同一ドメインは、例えばcookpad.comが本体だとすると、動画サービスのために cookpad.com/videos といったURLを使うやり方です。この場合、クッキーも本体サービスと同じになり、別のアプリケーションなのに同じセッションクッキーを使ってしまう可能性があります。cssやimageのパスも同じになります。つまり、マイクロサービスとして切り出したはずなのに、別のサービスと依存関係がある部分が残ってしまいます。

(b) のサブドメインでは、URLは videos.cookpad.com といった形になります。この場合、(a) で挙げた問題は回避できます。ただし、SEO対策を考えると不利な場合があります。Google検索の結果は、同じドメイン内にあるサービスが通例1個しか出ないので、例えばクックパッド本体のあるレシピが検索結果のページに表示される場合、そのレシピを紹介する動画ページは、同じ検索結果には表示されなくなってしまうのです。

(c) の完全別ドメインでは、cookpad-video.jp といった別のドメインを使います。この場合は、上に挙げた問題は発生しません。

結局、同社では「技術的な見地からは(b)が一番いいが、SEOなど他の要素も考えて(c)にした」ということです。

次に、キャッシュ戦略の問題が発生しました。例えば動画サービスのトップページで、レシピを20個紹介するようにしていたとします。動画サービスを、単一リソースを返すAPIの形で切り出した場合、20回のAPI呼び出しが発生します。1回のAPI呼び出しから20msで結果が帰ってくるとしても、20回で400msという時間が発生してしまいます。これでは表示が非常に遅くなってしまいます。

この問題を解決するため、1回のAPI呼び出しで複数の問い合わせをできるようにしたいところです。ところが今度は「20個を問い合わせて18個しか一致しなかった場合、エラーを返すべきか、それとも取得できた18個を返すべきか」という問題が出てきます。このあたりは「まだまだ考える余地がある」部分で、試行錯誤を繰り返しているということです。

「より大胆な施策を導入できるようになった」

今回の試みにより、ビジネス的な意味でも効果が得られたそうです。動画サービスが、クックパッドのサービス本体から独立したシステムになったことにより、従来よりも思い切った施策を導入することができるようになりました。具体的にはpjaxを使い、画面にタッチするだけで画面遷移をせずに、即座に動画が再生される仕組みを実装しています(Androidブラウザで試すことができます)。本体から独立していることで、こうした大胆な変更を迅速に行えるようになりました。

講演の最後では、今回の取り組みの結果、サービス本体のModelのクラス数を「5個」減らすことができたことを報告しています。つまり「サービス全体を小さなマイクロサービスの集まりにする」といった大きな目標まではまだまだ距離がある様子です。とはいえ、新しい取り組みに挑戦したい開発者にとっても、ビジネスのスピードを上げたい立場からも、マイクロサービス化への取り組みには価値があることを示した事例報告だったと言えるでしょう。