http://engineering.pinterest.com/post/94756298214/stealthy-shipping-with-atomic-deploys
1 comment | 0 points | by WazanovaNews 約3時間前 edited
Pinterestは、サーバの一部を本番から外し順次アップデートするという方式でデプロイをしています。それが起因してページ全体を無駄にリロードさせている状況を改善するための取り組みを紹介しています。
背景
- Pinterestのサイトでは、JavaScript + XHRにより、ページ内で必要なコンテンツだけが、クリックされた際に適宜更新されるようになっている。
- ユーザが最初にPinterestのサイトにアクセスすると、サーバはブラウザに対しJavaScriptのバンドルを読込ませ、そのバンドルがサーバにあるソフトウェアのバージョンとの一致を確認する仕組み。
- デプロイする際は、サーバの10%をオフラインにし、アップデート完了後、本番に戻すという作業を繰り返している。つまり、新しいバージョンのソフトを載せたサーバと古いものを載せたサーバが混在している状態になる。(Varnishの相対するバージョンが混在しているイメージ図)
- もしユーザのフロントエンドのソフトウェアがバージョンAだった場合、デプロイが開始されると、XHRでやりとりするサーバ側は既にバージョンBに更新されている可能性がある。それが検知されると、ページ全体がリロードされてしまい、必要な箇所だけが適宜更新されるスムーズなユーザ体験が担保できなくなる。更には、デプロイが完了するまでは、クリックした箇所でミスマッチが起きる度に、全ページ読込みが繰り返されてしまう。
アーキテクチャの変更
- ユーザがページ全体を再読込みするのを最大1回に抑えるために、アトミック性を担保できるシステムが理想。
- そこで、二つのPinterestのバージョンを、Varnishがうまく切り替える方式を採用。大量のトラフィックを扱えるwebフロントエンドのボックス(c3.8xlarges from c1.xlarges: 64 Pythonプロセスを実行できる。)を用意。新旧のバージョンは、nginxでそれぞれユニークなポートをアサイン。
- どのバージョンにいつ対応するかVarnishに知らせる仕組みを構築。ZooKeeperには「サーバセット」を用意し、nginxがどのトラフィックをさばいているか、Varnishが把握できるようにした。
- 例えば、古い方がバージョンA、新しい方がバージョンBとする。ユーザは、A or Bいずれもアクセス可能で、ページ全体を再読込みするまでは、アクセスしたときのバージョンを利用しつづける。そして、再読込み後は、必ずBを利用するようになる。
- 次にバージョンCをアップすると。
- 1. バージョンAに対応しなくなることを、ZooKeeperがVarnishに通知。
- 2. Varnishは、バージョンAの非対応を了解したら、レスポンスを返す。Aにいたユーザは、Bに向けられるようになる。
- 3. バージョンAをアンインストールして、バージョンCをインストール。
- 4. Cが利用可能になれば、Varnishに準備完了の旨を通知。
- 5. Varnishは、全てのノードがCに対応できるようになれば、レスポンスを返す。
- 6. デフォルトバージョンをBからCに切り替える。新規ユーザはデフォルトでCとなる。
改善
このグラフで確認できるように、ページ再読込みの回数を激減させることができた。従前は、週末はデプロイを控えていたので再読込み回数が少ないこともグラフから読み取れると思うが、平日はデプロイがユーザに影響を与えていたのが一目瞭然。新しい方式のおかげで、ユーザエクスペリエンスを損なうことなく、デプロイできるようになった。