Cedar-14へのUpdateについて
本題から外れますが、Herokuの利用に関する重要な情報を最初にお伝えします。
本稿を執筆中、実に4か月ぶりに本連載で制作しているHerokuのサンプルアプリケーションを更新しました。ところが、Herokuに更新をpushした際に次のような警告が表示されました。
! Cedar-10 will reach end-of-life on November 4th, 2015. ! Upgrade to Cedar-14 at your earliest convenience. ! For more information, check out the following Dev Center article: ! https://devcenter.heroku.com/articles/cedar-14-migration
書かれているとおりですが、Cedar-14の正式リリースに伴い、旧Cedarスタックは2015年11月に廃止されます。
旧Cedarで運用しているアプリケーションをお持ちの方は、Herokuサイト「Migrating to the Celadon Cedar-14 Stack」の説明に従って、早めにCedar-14に上げてください。
具体的には、
$ heroku stack:set cedar-14 -a YOUR_APP_NAME
を実行後、何らかの変更をgit pushすればOKです(stack:setしただけでは置き換わらないことに注意してください)。
Memcachedとは
Memcachedは、シンプルで高速なオブジェクトキャッシュシステムです。オープンソースソフトウェアとして配布されており、誰でも気軽にインストールして利用することができます。
また、Memcached自体をWebサービスとして提供する事業者もあります。Herokuでは以下のMemcached互換Add-onが提供されています。
これらのAdd-onを利用することで、自分でMemcachedサーバをホスティングすることなしにMemcachedの機能を利用できます。
サービスとしてMemcachedを利用することのメリットは、アプリケーションのホスト先としてオンプレミスではなくHerokuを選択したときと同じです。Heroku上のアプリケーションからAmazon EC2などに用意したMemcachedサーバを使用することはできますが、管理コスト(死活監視、バックアップなど)を考えると、ほとんどの場合Add-onを利用するほうがメリットが大きいと考えられます。
Memcachedだけでも複数のAdd-onが提供されているので、どれを選択すればよいか迷うかもしれませんが、これらはサービスの事業者が違うだけで機能的にはどれも同じです。異なるとしたら、事業者側が独自に提供しているGUI管理ツールの使い勝手でしょうが、Memcached自体がそれほど多くの管理用APIを提供していないので、さほどの違いはありません。
Add-on/プランを選択をする場合には、
- 価格
- メモリ容量
- 同時接続数
などを指標として決めればよいでしょう。筆者の場合、最も古くから提供されているAdd-onであるMemcacherを選択することが多いです。
いずれのAdd-onも開発用に無料プランが用意されているので、コスト不要で使い始めることができます。
HerokuでMemcachedが重要な理由
それはずばり、Herokuではオンメモリのサーバサイドセッションが使えないからです。
サーバサイドセッションとはログインユーザ情報などのクライアント(ブラウザ)ごとの個別情報をサーバサイドで保持する仕組みのことです。
情報量が少ない場合はCookieでも十分ですが、Cookieには4KBの制限がありますし、機密性の高い情報の場合はCookieに載せることさえできないこともあります。
また、セッション情報をいちいちデータベースから読み書きしていては、パフォーマンス上のコストが高くなりすぎてしまいます。そのため、多くのWebアプリケーションフレームワークでは、サーバのオンメモリにセッション情報を保持する仕組みが提供されていました。最も典型的な例は、Java Servlet APIのHttpSessionです。
この仕組みは、Webサーバをスケールアウトさせることが一般的ではなかった時代(1つのWebアプリケーションが1台のホスト上で運用され、アクセス数の増加にはスケールアップで対応していた時代)には有用でしたが、HerokuやAWSが台頭してアクセス数増加への対応にスケールアウトが使われるようになった現在においてはBad Practiceです。
なぜなら、スケールアウトした場合、同一クライアントからの連続するリクエストが、最初はサーバAで処理され、次のリクエストはサーバBで処理されるということが当たり前に起こるからです。サーバA側で保持されたセッション情報はサーバBでは見ることができないので不整合が発生し、アプリケーションが正しく動作しなくなります。
これを回避するためにセッション情報の保存先にサーバオンメモリではなく、外部の高速なキャッシュサーバが使われるようになったわけです。
近年では、Webアプリケーションフレームワーク側でもスケールアウトへの対応が考慮されるようになってきました。設定によって、サーバサイドセッションを扱う方法を従来のオンメモリ型から、MemcachedやRedisなどの外部ストレージを使用する方法へ変更できるものも増えています。
サーバサイドセッションとスケールアウトを両立させるもう1つの解として「Sticky Session」を使うという方法もあります。
Sticky Sessionとは、ロードバランサ側で、同一セッションでのリクエストは常に同じサーバに振り分けるようにする技術です。
Sticky Sessionを使用した場合、同一クライアントからのリクエストは常に同じサーバに転送されるので、他のサーバではそのクライアントのセッション情報は不要になります。
Sticky Sessionを使用するには、ロードバランサがSticky Sessionをサポートしていなければなりませんが、Herokuではサポートされていません。
AWSのELBはSticky Sessionをサポートしていますが、サーバのリプレースが簡単にできないなどの欠点があります。そのため、解法としてはMemcached(またはRedisなど他の外部ストレージ)を使う方法のほうが優れていると筆者は考えています。