Cookpad の本番環境で使用している Ruby が 2.0.0-p0 になりました

技術部・開発基盤グループの村田です。

クックパッドは本日から、本番環境を Ruby 2.0.0-p0 に移行しました。Ruby 2.0.0-p0 は 2013年2月24日にリリースされた Ruby の最新バージョンです。新しい Ruby を使って気持ち良く開発するために、できるだけ早く Ruby をバージョンアップしようと尽力してきた結果が実りました。

Ruby のバージョンアップでレスポンスが高速になった

クックパッドが Ruby 2.0.0 に対応したことで、ユーザと開発者の両者にとって、これまでよりも快適になっています。

Ruby のバージョン移行は、Ruby Enterprise Edition から Ruby 1.9.3-p392 を経由して Ruby 2.0.0-p0 へと段階的に実施しました。Ruby を Enterprise Edition から 1.9.3、そして 2.0.0 へとバージョンアップすることで、アプリケーションのレスポンスタイムが段階的に短縮されました。平均値で比較すると、Ruby Enterprise Edition から 1.9.3 へ移行することで約100ms短縮され、そして1.9.3から2.0.0へ移行することで更に約20ms短縮されています。

さらに、新しいリビジョンをデプロイするときに発生する一時的なレスポンス速度の低下も直ぐに解消するようになりました。クックパッドではサービス開発者が必要に応じてカジュアルにデプロイする開発体制をとっているため、日中に10回以上デプロイされる日もあります。このような開発体制をとっているため、直前のデプロイをロールバックするためのデプロイを実施することもたまにあります。そのため、デプロイ時のレスポンス速度低下が直ぐに解消してくれるのは嬉しい改善です。

移行までの流れ

Ruby 1.9.3-p392 への移行日は2月26日です。Ruby 1.9.3 への移行作業は通算すると (1人で) 4ヶ月ほどかかったことになるのですが、1.9.3 から 2.0.0 への移行作業は1ヶ月未満で完了しました。Ruby 2.0.0 への移行が楽だった理由は、Ruby 2.0.0 が 1.9.3 との互換性をだいたい保持していたからだと思います。

クックパッドでは、cookpad.com などの公開されているサービスのほかに、社内で使用するためのツールも Ruby on Rails で開発しています。いくつかのアプリケーションはモデルやライブラリなどのコードを共有しているため、特定のアプリケーションが使用するRubyのバージョンを上げる場合は、古いRubyでも動作する状態を保つ必要があります。現在、Ruby Enterprise Edition、1.9.3、2.0.0 の各バージョンが同時に動いてる状態になっています。

jenkins

この図はクックパッドで運用している Jenkins のトップページです。名前が黒塗りされていないジョブは、クックパッドのアプリケーションテスト、バッチシステムのテスト、カバレッジ計測、Ruby 1.8.7 での構文互換性チェック用のジョブです。このように、複数のRubyのバージョンを同時に使用してCIを運用しています。

移行作業で役立った工夫

複数のRubyで動作可能な状態を作るために、いくつかのテクニックを活用しました。

まず、複数の Ruby を適宜切り替えて動作確認をするため、rbenv のバージョン切り替え機能と、bundler の Gemfile を切り替える機能を活用しました。rbenv は RBENV_VERSION 環境変数を使用することで、使用する Ruby のバージョンを選択できます。bundler は BUNDLE_GEMFILE に Gemfile のファイル名を指定することで、Gemfile と Gemfile.lock の basename を変更できます。たとえば、Ruby 2.0.0 への移行作業をしている最中は、Gemfile.200 を Gemfile へのシンボリックリンクとして作成しておき、BUNDLE_GEMFILE=Gemfile.200 と RBENV_VERSION=2.0.0-p0 の2つの環境変数を指定して bundle install を実行すると、Ruby 2.0.0 で使用する Gemfile.200.lock が作成されます (このテクニックは jQuery のバージョンアップ作業でも活用されています)。

次に、アプリケーションコードから RUBY_VERSION や respond_to? を使った条件分岐を極力減らすため、モンキーパッチを応用して Ruby のバージョン間の非互換性を吸収し、必要なら警告を出力するライブラリを作成しました。このライブラリの詳細について、3月16日に開催された大江戸Ruby会議03で筆者が行ったトークで解説しましたので、詳しくはその資料をご覧ください。

参考資料: 大江戸 Ruby 会議03で、某レシピサイトの Ruby 1.9.3 対応で苦労した点を共有しました

さいごに

本記事では、クックパッドがRuby 2.0.0に対応したこと、それによってレスポンスタイムが改善したこと、そして、移行作業で役に立った工夫について紹介しました。

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/