TagWeb

Google Compute Engine 上で WordPress インスタンスを走らせる

このブログはもともとさくらのレンサバ上で動かしていたのだが、小さなブログひとつのためにレンタルサーバーを維持するのはオーバーキルだなという感じがしてきたので Google Compute Engine に移してみた。

移行は容易であった。cloud.google.com から自分のダッシュボードへ行き、Cloud Launcher から Bitnami の提供する WordPress パッケージを選ぶだけ。あとは古い WordPress からデータを移行して、ドメイン名からのひも付けを再設定すれば終了だ。

今のところ3日間利用して $0.5 しか課金が発生していない。ステマになってしまうが素晴らしいサービスである。

HTTP/1.1 が更新された

HTTP/1.1 just got a major update という記事が Hacker News 一面に出ていた。さっと訳す。正確性は保証しない。


IETF は、 HTTP/1.1 を更新するいくつかの新しい RFC を発表した。

RFC 7230: Message Syntax and Routing
RFC 7231: Semantics and Content
RFC 7232: Conditional Requests
RFC 7233: Range Request
RFC 7234: Caching
RFC 7235: Authentication
RFC 7236: Authentication Scheme Registrations
RFC 7237: Method Registrations
RFC 7238: the 308 status code
RFC 7239: Forwarded HTTP extension

これらは、従来の HTTP/1.1 を置き換えるものである。HTTP オタクとしては大事件だ。

15 年前に書かれた RFC 2616 こそ、皆が実装してきた仕様であり、読者もよく参照として利用してきただろう。

HTTPBis グループはこの仕様を少なくともここ7年間この仕様をアップデートする作業に費やしてきた。HTTP ほど後半に使われているプロトコルには様々なステークホルダーがおり、充足しなければならない意見も多くあったことが想像される。

まだ開発中の HTTP/2.0 も、これらの RFC を参照し、すべての定義をスクラッチから始めるよりも、これらの書類に単にリンクするだろう。

ここ数年、私もこれらの新しい使用書類のドラフトを使ってきた。元のものよりも参照しやすくなるのに時間がかからなかったからだ。

何が変わったか

最大の差異は、古い仕様と比べて、単純に文章量が多いということだ。理解しやすく、読みやすくなり、曖昧さもなくなった。

それから、仕様の核が6つの異なった仕様書に分割された。昔は HTTP のために RFC 2616 が、Basic および Digest 認証のために RFC 2617 があるだけだった。

この2つだけでも、API の作成者が仕様書を最初から最後まで読む意味はある。学ぶことはたくさんあるだろうし、よりよい HTTP API デザインへのインスピレーションが得られるだろう。

それから、308 ステータスコードが新しいスタンダードになった。これは4つ目のリダイレクト ステータスで、永久的なリダイレクトを意味する。308 を受け取ったクライアントは、リダイレクトをたどり、全く同じリクエストを行うことが期待されている。これは、クライアントが通常メソッドを GET に変更する 301 リダイレクトとは少し異なる。

RFC 7239 は Forwarded ヘッダーを標準化する。これは、 X-Forwarded-For や X-Forwarded-Proto などのヘッダーを置き換えるものだ。

以下、変わったことの全く網羅的ではないリスト。

  • 不意のホワイトスペースへの対処の明確化。これは HTTP レスポンス分割の脆弱性を解決するはずである。
  • サーバーあたりの接続数限界が排除された。
  • HTTP/0.9 のサポートがなくなった。
  • ISO-8859-1 のデフォルト charset がなくなった。
  • サーバーは、すべての Content-* ヘッダーを取り扱う必要がなくなった。
  • PUT リクエストでの Content-Range が明確に禁止された。
  • リファラーが存在しない際、Referer ヘッダーには about:blank を利用することが推奨されている。これは、「リファラーがない」と「リファラーを送りたくない」を区別するためだ。
  • 204, 404, 405, 414, 501 ステータスコードがキャッシュ可能になった。
  • 301 と 302 ステータスコードは、POST から GET へユーザーエージェントがメソッドを変更することを許容するように変更された。これは、皆が(間違って)既に実装していたもので、仕様側で実際の運用に沿うように変更を行ったものだ。
  • Location ヘッダーは、フラグメント アイデンティファイアと相対的 URI を含むことができる。
  • Content-MD5 がなくなった。

他に何か面白い変更があれば教えてくれ。

参照

PageSpeed Insights によるモバイル分析 (勝手訳)

Google のモバイルに関するスピード向上のためのガイドラインである Mobile Analysis in PageSpeed Insights の一部を適当に訳したので公開する。これは個人的なもので内容の正確性とかは一切保証しないので注意してくれ。


PageSpeed Insights によるモバイル分析

PageSpeed Insights では、モバイルネットワークという劣悪な環境においてページを1秒以下で読み込むにはどうすればよいか、Google の推奨事項に基いて改善点を分析することができる。分析によれば、ページの読み込みに1秒以上かかってしまうと、ユーザの思考の流れは一旦絶たれてしまうという。これでは快適なネットサーフィンとは到底言えない。重要なのは、ユーザーがまだページに興味を抱いている間に、どんなネットワーク上でも最善の体験を提供すること、これだ。

もちろん、1秒以下というのは簡単なことではない。しかし朗報だ。ページのすべてを1秒以内に表示しなければならない、というわけではないのだ。その代わりに、Above-the-fold (ATF) と我々が呼ぶ、画面に最初に表示され、ユーザーの視野に最初に入ってくる部分を1秒で表示すればいい。あとは、ユーザーがそれを読んでいる間に、他の部分をレンダリングしてしまえば良いのである。

モバイルネットワークは遅い

どんなネットワークにも1秒以下で対応する、というのは並大抵のことじゃない。4G や 3G、あるいは 2G のどんなネットワークからもユーザはやってきうる。もちろんだがモバイルは遅い。はるかに遅い。我々は ATF コンテンツを1秒、つまり 1000 ms で表示したいのに、ネットワークのせいでかなりの時間を食ってしまう。一回ののラウンドトリップに、これだけの時間がかかってしまうのだ。

  • 3G なら 200-300 ms
  • 4G なら 50-100 ms

今のところ世界で一番メジャーなのは 3G だ。たしかに 4G も徐々に導入が進んできてはいるが、平均的なユーザーは 3G を利用していると考えるべきだろう。つまり、リクエスト1回につき、平均で 200 ms、0.2 秒かかると見積もるのだ。

そう考えると、DNS ルックアップで 200 ms、TCP ハンドシェイクのためのラウンドトリップでもう 200ms、そして実際の HTTP リクエストとレスポンスで 200ms かかるわけだ。もう 600 ms = 0.6 秒も経過してしまった。あと 400 ms しか残っていないではないか!

それでも1秒未満を達成するのだ

あとたった 400 ms でどうしろっていうんだ?サーバー側でレスポンスを生成し、クライアントサイドのコードを実行し、ブラウザーでコンテンツのレイアウトとレンダリングを行わなくてはならない。我々の野望は潰えたのか?いや、そうではない。こうすればいい:

  1. 200 ms 以下でレスポンスを返す: サーバーが最初の HTML を返すまでの時間からネットワークの転送時間を引いたものがサーバーレスポンスタイムだ。我々には時間がないので、これはできるだけ小さくしよう – 200 ms 以下が理想だ。

  2. リダイレクトの数の最小化: ひとつ HTTP リダイレクトを入れるたびに、ラウンドトリップをひとつかふたつふやすことになる(DNS ルックアップが必要ならふたつだ)。すでに見たように 3G 回線ではこれは致命的だ。その時点で数百 ms のハンデである。リダイレクトはできるだけ排除しよう─無くせるなら無くした方がいい。特に HTML 文書に関しては特に重要だ (“m.” とか “touch.” とかはクールじゃない)。

  3. ラウンドトリップの数の最小化: TCP がコネクションのキャパシティを予想するやりかた(スロースタート)のせいで、新しい TCP コネクションはクライアントとサーバーの間の帯域をフルで使うことができない。このせいで、サーバーは新しい接続の最初のラウンドトリップで最大 10 の TCP パケット (~14KB) を送ったあと、輻輳ウィンドウを拡大させ更なるデータを送信するためにクライアントがそれを確認するのを待たなければならない。この挙動を考えれば、ラウンドトリップの数を最小化するために、理想的には、ATF 内のコンテンツは 14KB 以下であるべきだ。そうすれば、たった一度のラウンドトリップでページを描写できることになる。それから、この「10パケット」という数字は最近のアップデート (IW10) で TCP 規格に追加されたものだということも知っておこう。もしこのアップデートにサーバーが対応していなければ、おそらく限界は 3-4 パケットだ。

  4. Above-the-fold 内の JS と CSS をインライン化する: ページをパースしている最中に非同期コードや外部スクリプトに出会ってしまうと、ブラウザは一旦パースを中止してそのリソースをダウンロードしなければならない。そのたびにラウンドトリップが増え、ページのレンダリングを遅くする。
    だから、ATF 内に表示される JS と CSS はインライン化するべきだ。補助的な機能をページに追加する JS や CSS は、ATF コンテンツが表示されてからロードすれば良い。

  5. ブラウザ側でコンテンツをレイアウト&レンダリングする時間を残す (200ms): HTML と CSS をパースして JS を実行するのには時間がかかるし、クライアント側のリソースを使う。デバイスの速度とページの複雑さに応じて、数百 ms かかってしまうことがある。このオーバーヘッドのために 200 ms 残しておこう。

  6. JS の実行 & 表示時間を最小化する: 複雑なスクリプト、非効率なコードのせいで数百 ms かかってしまうことがある。デベロッパーツールをうまく利用して、コードを最適化せよ。 Chrome Developer Tools のインテラクティブコース を受講するのがおすすめ。

注意:もちろん、これはすべての最適化の網羅的なリストではない。パフォーマンスチューニングのためにできることは他にもいろいろある。詳しくは PageSpeed Insights をチェックせよ!特に以下がオススメ。

FAQ

  • 4G だとどうなんよ?

4G マジオススメ。ラウンドトリップのレイテンシが減る。見りゃわかるけど 3G では1秒の半分以上がこのせいで使われてるわけだからな。でも、上で書いたけど、ネットワークとしては今でも 3G が主要だから、かわいそうな 3G 民のことをちゃんと考えてやってくれ。

  • jQuery 使ってるんだが。

うん、そういう JS ライブラリを使ってる奴が多いのはわかる。色々と機能とかアニメーションとか追加できて捗るよな。しかし、こういうことは ATF コンテンツを表示させてからロードすればいいのだ。JS を実行するタイミングを再考せよ。

  • JS フレームワークを使ってるんだが。

コンテンツが JS を利用してクライアントサイドで生成される場合は、まず、JS をインライン化して無駄なラウンドトリップを減らせ。それから、サーバーサイドでレンダリングを行うことで最初のページロードのパフォーマンスは上がる。JS テンプレートはサーバー側でレンダリングし、結果を HTML にインラインで挿入、その後アプリがロードしてからクライアントサイドテンプレートを利用せよ。

  • SPDY とか HTTP 2.0 とかについて詳しく

どちらも TCP 接続をより効率化することでページロードのレイテンシを減らすために努力している。多重化とかヘッダ圧縮とか優先制御とか。SPDY にまず対応し、時が来たら HTTP 2.0 にスイッチするのがオススメだ。

  • どの CSS が一番重要なのかわからん

クロームデベロッパーツールを使え。捗るぞ。

  • めんどくさいから自動化できんのか

おう、商用のものも、オープンソースのものも、ウェブパフォーマンス最適化のための製品はいろいろあるぞ。具体的には このページ を見れ。

  • どういうふうにサーバーをチューンしたらいいんだ?

まずサーバーが最新の OS を走らせていることを確認しよう。TCP の輻輳ウィンドウの拡張 (IW10) に対応するためには、Linux kernel 2.6.39 以上が必要だ。ほかの OS についてはドキュメントを見れ。
サーバーレスポンスタイムの最適化については、何がボトルネックになっているのかを診断するためにアプリケーションモニタリングのためのソリューションを導入すれ。スクリプトの実行なのか、データベースコールなのか、RPC リクエストなのか、それともレレンダリングなのか…。いいか、目標は 200 ms だぞ。

  • Content Security Policy

CSP を使っている場合は、デフォルトのポリシーをアップデートする必要があるかもしれない。

まず、HTML 要素内の CSS 属性を避ける。不必要なコードの重複に繋がるし、CSP を利用しているとデフォルトではブロックされる。JS をインライン化する場合は、ポリシーに “unsafe-inline” を追加して実行を許可する必要がある。デフォルトでは全部ブロックだからな。


以上だ。誤訳があったら教えてくれ。

© 2017 The Long Wait

Theme by Anders NorénUp ↑