ゴー1.8へのHTTP / 2サーバープッシュ

標準ライブラリゴーでHTTP / 2サーバープッシュを使用する方法についての翻訳小さなチュートリアル。







はじめに



HTTP / 2は、HTTP / 1.xの問題の多くを解決するために発明されました。 ようにHTML、スクリプト、スタイルシート、画像、および - 現代のWebページには、追加のリソースを大量に使用しています。 HTTP / 1.xではこれらの各リソースは、明示的に別の要求を要求する必要があり、それは非常に遅いページの読み込みすることができます。 HTMLブラウザは、負荷にページ解析などの必要な新しいリソースについて学習を開始します。 ブラウザが別のリソースと単にアイドルかつ効果的に使用されていないネットワークに要求するまでその結果、サーバは待機します。







レイテンシの向上のために、HTTP / 2で、彼らは明示的に要求される前に、サーバーがブラウザのリソースを送信することを可能にするサーバープッシュのためのサポートを追加します。 多くの場合、サーバーは、追加のリソースがWebページを要求されますと、最初のページリクエストに応答して、それらを一緒に送信するために始めることができるものを事前に知っています。 これは、サーバがアイドル状態、およびページの読み込み時間を改善するネットワーク帯域幅の使用を最大化することができます。









PUSH_PROMISE -プロトコルのレベルでは、HTTP / 2サーバプッシュフレームの特殊なタイプで動作します。 フレームPUSH_PROMISEはすぐにブラウザによって要求されるサーバーの意見では、要求を、説明しています。 レシートPUSH_PROMISEすると、ブラウザはサーバはすぐにこのリソースを送信することを知っています。 後でこのブラウザは、リソースがあります要求し、それは新しいHTTP要求を開始するのではなく、プッシュを完了するためにサーバーを待ちます。 これは、ブラウザがネットワーク上で費やす合計時間を削減します。







ネット/ HTTPパッケージでサーバープッシュ



ゴー1.8は、サーバープッシュのサポート追加http.Serverを 。 この機能は、HTTP / 2でrabotkeサーバ場合に自動的に使用可能であり、また、HTTP / 2プロトコルを使用して、着信接続を開きます。 次のトリック-のいずれかのHTTPハンドラ、彼らはタイプのシンプルなタイプのキャスト変数をサポートするかどうかをチェックhttp.ResponseWriterインターフェイスにサーバープッシュhttp.Pusher。







サーバーがページのスクリプトapp.jsをレンダリングするために必要とされるであろうことを知っている場合http.Pusherこれに関連して、利用可能な場合、例えば、ハンドラが強制的に、サーバープッシュを使用してそれを送ることができます。







http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if pusher, ok := w.(http.Pusher); ok { // Push . if err := pusher.Push("/app.js", nil); err != nil { log.Printf("Failed to push: %v", err) } } // ... })
      
      





プッシュ方式は、/app.jsへの新しい要求を作成PUSH_PROMISEフレームでそれを収集し、クライアントに必要な応答を生成するサーバーの要求ハンドラを送信します。 彼らはそのフレームのために必要である場合は、2番目の引数は、追加のタイトルが含まれています。 /app.jsへの答えが違うのAccept-Endodingにする必要があります例えば、もし、PUSH_PROMISEは受け入れ-Endoding見出しが含まれている必要があります。







  http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if pusher, ok := w.(http.Pusher); ok { // Push  options := &http.PushOptions{ Header: http.Header{ "Accept-Encoding": r.Header["Accept-Encoding"], }, } if err := pusher.Push("/app.js", options); err != nil { log.Printf("Failed to push: %v", err) } } // ... })
      
      



http.ResponseWriter W、R * http.Request){ http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if pusher, ok := w.(http.Pusher); ok { // Push options := &http.PushOptions{ Header: http.Header{ "Accept-Encoding": r.Header["Accept-Encoding"], }, } if err := pusher.Push("/app.js", options); err != nil { log.Printf("Failed to push: %v", err) } } // ... })



http.Pusher);. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if pusher, ok := w.(http.Pusher); ok { // Push options := &http.PushOptions{ Header: http.Header{ "Accept-Encoding": r.Header["Accept-Encoding"], }, } if err := pusher.Push("/app.js", options); err != nil { log.Printf("Failed to push: %v", err) } } // ... })



"エンコード同意します"]、 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if pusher, ok := w.(http.Pusher); ok { // Push options := &http.PushOptions{ Header: http.Header{ "Accept-Encoding": r.Header["Accept-Encoding"], }, } if err := pusher.Push("/app.js", options); err != nil { log.Printf("Failed to push: %v", err) } } // ... })



app.js"、オプション); http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if pusher, ok := w.(http.Pusher); ok { // Push options := &http.PushOptions{ Header: http.Header{ "Accept-Encoding": r.Header["Accept-Encoding"], }, } if err := pusher.Push("/app.js", options); err != nil { log.Printf("Failed to push: %v", err) } } // ... })



V"、ERR) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if pusher, ok := w.(http.Pusher); ok { // Push options := &http.PushOptions{ Header: http.Header{ "Accept-Encoding": r.Header["Accept-Encoding"], }, } if err := pusher.Push("/app.js", options); err != nil { log.Printf("Failed to push: %v", err) } } // ... })





完全に動作する例あなたはここで試すことができます。







 $ go get golang.org/x/blog/content/h2push/server
      
      





このサーバーを実行しに行く場合のhttp:// localhostを:8080 、ネットワークは、お使いのブラウザでインスペクタを要求しapp.jsとのstyle.cssには、サーバーを「押し込んだ」されたことを示す必要があります。









最初の応答を押してください。



これは、メインの返信に何かを投稿する前に、Pushメソッドを呼び出すことは理にかなっています。 そうでない場合は、誤って答えを繰り返し生成するオプションがあります。 たとえば、あなたのハンドラを使用すると、HTMLコードの一部に対応して書き込みをすることを想像:







 <html> <head> <link rel="stylesheet" href="a.css">...
      
      





その後、プッシュ( "a.css"、nilを)呼んでいます。 しかし、ブラウザはすでにPUSH_PROMISE受信したフレームの前にHTMLスニペットを解析するための時間を持っていたかもしれないが、この場合には、フレームに加えて、a.cssに新しい要求を送信します。 サーバーは現在、二回a.cssへの要求にサービスを提供しなければなりません。 クライアントの体の排除にこの問題を解答を与える前にプッシュを呼び出します。







サーバープッシュを使用する場合は?



ここでは一般的な答え - ネットワーク接続がアイドル状態です。 HTMLのWebアプリケーションの送信を完了? 明らかに必要なリソースを提供し始め、あなたの時間を無駄にしないでください。 おそらく、あなたは、待ち時間を短縮するために、HTMLで直接リソースをインライン化? 代わりにインライン化、押してみてください。 リダイレクトページ、ほとんど常に複数のクライアントからの要求よりも - それはまた良い例です。 サーバープッシュが有用であることができ、さまざまなシナリオがたくさんあります - 私たちはそれらを習得し始めています。







それは落とし穴を言及しないように怠慢だろう。 他のウェブサイトからのものであることを、リソースやCDNを与えることはありません - まず、サーバープッシュの助けを借りて、あなただけのサーバーを所有しているリソースを与えることができます。 第二には、 - あなたは彼らが必要とするクライアントかどうかわからない場合、それは過剰なトラフィックの無駄となり、リソースを与えることはありません。 結果として - クライアントによって受信され、符号化された可能性があるリソースを与えないようにします。 そして、第三 - 素朴なアプローチ、「すべてのリソースを突き出す」は、通常、パフォーマンスの低下につながります。 いつものように、疑わしい場合には - 測定を行います。







より詳細の理解のためにいくつかの有用なリンク:







HTTP / 2プッシュ:詳細

HTTP / 2サーバープッシュと革新

H2OのプッシュでのCache-Awareのサーバー

パターンA PRPLの

HTTP / 2プッシュのための場所の親指のルール

HTTP / 2仕様でサーバープッシュ







おわりに



ゴー1.8標準ライブラリを使用すると、より効果的かつ最適化されたWebアプリケーションを作成することができ、箱から出してHTTP / 2サーバープッシュの機能を提供します。







あなたは、アクションでHTTP / 2サーバープッシュを見ることができますこのページで








All Articles