こんにちは。 休日のゲームライフを充実させるため、せっせとエンジニアリングブログを書いています、ソフトウェアエンジニアのサイリュムです。
今回はpixiv.comのサーバ構成について簡単に紹介したいと思います。
国際版
pixiv.comのウェブアプリケーション部分はRuby on Rails 3.2系で作成しています。
ユーザとのやりとりを行うフロントエンド部分はRailsに任せ、データのやり取りや複雑なロジックは後述する内部APIに任せています。
nginx + unicorn
Rackサーバにはunicornを使っており、nginx + unicornな構成を取っています。 nginxとunicornはunix domain socketで通信を行うようにしています。WEBアプリケーションサーバに乗っている静的なコンテンツはnginxが返し、動的ページへのリクエストはRailsが処理して返す形式になっています。
APIとの連携
RailsからPHPで作成された内部APIをActiveResource経由で呼び出しています。
ActiveResourceは、ActiveRecordのようなインターフェイスでRESTfulなAPIにアクセスするためのラッパーです。ActiveRecordに比べるとメジャーではありませんが、少しの記述でActive Recordと同じようにRESTful APIにアクセスできます。
内部APIはRESTfulなAPIとなっているので、ActiveResourceを使うと比較的簡単に呼び出せるというわけです。
内部API
社内のサービスから共通のインターフェイスでアクセスできるように、バックエンドシステムとのデータのやり取りを行うAPIをPHP5.4系で動かしています。
この内部APIはRESTfulなインターフェイスを持っており、レスポンスをJSONで返すようになっています。 APIはオーバーヘッドを削減するため、少々気持ち悪いのですがpixiv.comのアプリケーションサーバのApacheで動かしています。
ページキャッシュ
Active ResourceはHTTPでリクエストを飛ばし、レスポンスを解析してデータモデルとして扱えるようにしてくれる便利な機能ですが、リクエスト毎にActive Resource経由でAPIにリクエストを飛ばしてしまうと、TCPコネクションなどのコストが嵩みレスポンスを返すのに時間がかかってしまいます。
pixiv.comではリクエストが多くなる部分は、なるべくキャッシュを作り、共有することでAPIの呼び出しを少なく押さえています。
例えばトップページは、ログインユーザの情報以外のすべての部分をキャッシュとして持っています。
セッション / キャッシュの冗長化
pixiv.comのセッションやキャッシュはKyotoTycoonに入れています。 KyotoTycoonはデュアルマスター構成で永続化できるmemcachedのように使っていますが、Activeサーバが落ちた場合にキャッシュが消失したり、セッションが切れたり、ログインできなくなると困るので、keepalivedでフェイルオーバーするようにしています。
全体構成図
まとめると以下のように国際版サーバは動いています。(死活監視などは省いています)
現状、内部APIとの通信はHTTPで行われており、localhostへの接続とはいえそれなりに通信コストがかかっているため、今後、内部APIはPHP-FPMで動かし、unix domain socket経由で叩けるようにしたいところです。