Apache 2.4系でHTTP/2サーバを構築してみるテスト。
HTTP/2の動作確認libnghttp2を作る際に、nghttpコマンドもインストールされています。これは、http/2に対応したクライアントです。このコマンドを使うと、動作確認ができます。 これは、/usr/local/binにインストールされているはずです。 h2c(非暗号接続)の場合HTTP/2のサーバを構築する場合、TLS(SSL)が絡まない分、h2cのほうが簡単に動きます。そのため、まずは、h2c(非暗号接続)から動作確認すると良いでしょう。 ただ、実際のWebブラウザは、非暗号接続のh2cに対応していない可能性が高いです。構築時の参考程度に考えておくといいかもしれません。 負荷分散装置といった、リバースProxyの後方で運用するWebサーバで、利用するといった用途が、メインかと思われます。
アップグレードnghttpコマンドに-uオプションを付けると、一旦、httpで接続してから、h2cにアップグレードをおこないます。 -vオプションは、おなじみの、verboseモードつまり、デバッグ情報が出ます。 こんな感じで使います。 $ /usr/local/bin/nghttp -uv http://example.com 次の実行例のように、HTTP Upgrade successの文字が出れば、成功 $ /usr/local/bin/nghttp -uv http://example.com [ 0.001] Connected [ 0.001] HTTP Upgrade request GET / HTTP/1.1 Host: example.com Connection: Upgrade, HTTP2-Settings Upgrade: h2c HTTP2-Settings: AAMAAABkAAQAAP__ Accept: */* User-Agent: nghttp2/1.3.4 [ 0.002] HTTP Upgrade response HTTP/1.1 101 Switching Protocols Upgrade: h2c Connection: Upgrade [ 0.002] HTTP Upgrade success …(省略)… このHTTPからのアップグレードは、最初のリクエストをHTTP/1.1で投げた後に、サーバからのレスポンスによって、アップグレード成功を確認して初めて、HTTP/2の恩恵にあずかれます。 それまでは、スピードが売りの、HTTP/2の利点がちょこっと失われます。特に、負荷分散装置といった、リバースProxyの後方で運用するWebサーバでは、もったいないことになります。 そこで、次のダイレクトモードが用意されています。
ダイレクトモードダイレクトモードは、HTTP接続後に、以下の24 bytesを送信することで、HTTP/1.1から、HTTP/2に切り替える方法です。 PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n HTTPからのアップグレードと違い、サーバからのレスポンスを待つことなく、HTTP/2を利用できます。 HTTP/2の利点を最初から生かしつつ、HTTP/1.1との互換も確保できます。 この機能は、httpd.confの、H2Directをonにすることで利用できます。
/usr/local/apache2/conf/httpd.confの一部
…(省略)… LoadModule http2_module modules/mod_http2.so <IfModule http2_module> LogLevel http2:info ProtocolsHonorOrder On Protocols h2c http/1.1 H2Direct on </IfModule> …(省略)… ただし、apacheモジュールによっては、このダイレクトモードの挙動では問題があるようです(参考:英語)。apache 2.4.17では、H2Directは、デフォルトでonでしたが、以降のリリースからoffになるかもしれません。 ダイレクトモードを利用する場合は、apacheモジュールとの互換性を確認の上、onとしてください。 コマンドとして、-uオプション(HTTPからのアップブレードを実行する)を使用せず、単純に $ /usr/local/bin/nghttp -v http://example.com とします。次の実行例のように $ /usr/local/bin/nghttp -v http://example.com [ 0.001] Connected [ 0.001] send SETTINGS frame 特徴的なメッセージが無いのですが、recv SETTINGS frameや、recv HEADERS frameが来ていれば、成功です。 ちなみに、httpd.confの、H2Directが offだと、以下の通り失敗します。
/usr/local/apache2/conf/httpd.confの一部
…(省略)… LoadModule http2_module modules/mod_http2.so <IfModule http2_module> LogLevel http2:info ProtocolsHonorOrder On Protocols h2c http/1.1 H2Direct off </IfModule> …(省略)… $ /usr/local/bin/nghttp -v http://example.com [ 0.001] Connected [ 0.002] send SETTINGS frame Some requests were not processed. total=1, processed=0と出て失敗します。
h2(TLS接続)の場合h2cの接続がうまくいっていれば、libnghttp2の機能に問題はないはずなので、あとは、TLS関連がうまくいっていれば、動作確認できます。 TLS接続の確認については、コチラをご覧ください。 nghttp2のインストールのところでも説明しましたが、自力でインストールしたOpenSSLを利用する場合、 $ source ~/.profile_ssl Add /usr/local/ssl/lib. として、OpenSSLのライブラリがインストールされている/usr/local/ssl/libを、ダイナミックリンクの対象とします。 コマンドオプションとしては、-uオプションを使わないのはh2cのダイレクトモードと同じです。h2c のダイレクトモードとの違いは、http://をhttps://に変えるだけです。 $ /usr/local/bin/nghttp -v https://example.coms これを実行して、次の表示がでれば、OKです。 $ /usr/local/bin/nghttp -v https://example.com [ 0.001] Connected The negotiated protocol: h2 …(省略)… The negotiated protocol: h2と出れば、成功です。 h2cの時とはちがって、数行みれば、成功したか、失敗したかわかります。 代表的な失敗は以下の2通りです。 次の実行例は、TLS接続で、ALPN拡張が使えない場合の応答です。 $ /usr/local/bin/nghttp -v https://example.com [ 0.034] Connected [ERROR] HTTP/2 protocol was not selected. (nghttp2 expects h2) 原因には、2つの可能性があって、ひとつは、サーバ側のmod_sslがOpenSSL 1.0.2よりも前のライブラリを使用している可能性があります。 もうひとつは、クライアント側のnghttpがOpenSSL 1.0.2よりも前のライブラリを使用している可能性があります。 Unix系のOSには、最初からOpenSSLが同梱されていることが多いので、OpenSSL 1.0.2よりも前のものがOSに同梱されている場合、両方疑ってみるといいと思います。このエラーは、時代とともに減ってはくるとはおもいます。 次の実行例は、従来のTLS/SSL接続となってしまった例です。 $ /usr/local/bin/nghttp -v https://example.com [ 0.034] Connected The negotiated protocol: http/1.1 [ERROR] HTTP/2 protocol was not selected. (nghttp2 expects h2) これは、クライアントに対して、ALPN拡張で提示されたプロトコルがHTTP/1.1(つまり従来のTLS/SSL接続)だったことを意味します。 このメッセージがでたら、/usr/local/apache2/conf/extra/httpd-ssl.confを確認します。 ProtocolsHonorOrderがOnになっているか?Protocolsの順番は正しいか?確認してください。
/usr/local/apache2/conf/extra/httpd-ssl.confの一部
<VirtualHost _default_:443> …(省略)… <IfModule http2_module> ProtocolsHonorOrder On Protocols h2 http/1.1 </IfModule> …(省略)… </VirtualHost>
Chromeで確認実際のブラウザでも確認してみましょう。GUIで動くブラウザは、TLS1.2のALPN経由(つまりh2)にしか対応していないことも多いので注意してください。 GUIで動くブラウザには、でデバッグモードだったり、デベロッパツールだったりが付いていると思います。chromeだと、URL欄右のプルダウンメニューから「その他メニュー」→「デベロッパツール」といきます。 ここで表示されたウィンドウの、Networkタブ を選択してから、F5キーを押します。すると下記のような表示になり、プロトコルを確認できます。 ![]() 3カラム目が、プロトコルを意味します。h2と出ていれば、OKですね。
|