这是Apache httpd中HTTP / 2实现的方法指南。此功能已投入生产,您可能希望接口和指令保持一致的版本。
HTTP / 2是世界上最成功的应用程序层协议HTTP的演进。它专注于更有效地利用网络资源。它不会改变HTTP的基本原理,即语义。仍然有请求,响应,标头等等。因此,如果您已经知道HTTP / 1,那么您也知道95%的HTTP / 2。
关于HTTP / 2及其工作原理的文章很多。当然,最规范的是其RFC 7540 (也以更易读的格式YMMV提供)。因此,您将在其中找到螺母和螺栓。
但是,就像RFC一样,先阅读并不是一件好事。最好是先了解 什么事情想要做,然后阅读有关RFC 如何它完成。http:// curl 的作者Daniel Stenberg 解释了一个更好的文档。它也以越来越多的语言提供!
太长了,没看过:在阅读本文档时,需要牢记一些新的术语和陷阱:
HTTP / 2协议由其自己的httpd模块(恰当命名为)实现
mod_http2
。它实现了RFC 7540所描述的全部功能,并支持明文(http :)上的HTTP / 2,以及安全(https :)连接。明文变体的名称为“ h2c
”,安全名称为“ h2
”。因为h2c
它允许直接
模式和Upgrade:
通过初始HTTP / 1请求。
为Web开发人员提供新功能的HTTP / 2功能之一是 Server Push。请参阅该部分以了解您的Web应用程序如何使用它。
mod_http2
使用nghttp2库
作为其实现基础。为了进行构建,mod_http2
您至少需要在libnghttp2
系统上安装1.2.1版本
。
当您./configure
使用Apache httpd源代码树时,需要将其' --enable-http2
'作为附加参数来触发模块的构建。如果您libnghttp2
居住在不寻常的地方(无论操作系统上是什么地方),都可以使用“ --with-nghttp2=<path>
”到“ ”来声明其位置configure
。
虽然这对于大多数人来说应该可以解决问题,但他们还是希望nghttp2
在此模块中使用静态链接的人。对于这些,该选项--enable-nghttp2-staticlib-deps
存在。它的工作原理与静态将openssl链接到的方式非常相似mod_ssl
。
说到SSL,您需要意识到大多数浏览器只会在https:
URL 上使用HTTP / 2 ,因此您需要一台具有SSL支持的服务器。不仅如此,您将需要一个支持ALPN
扩展的SSL库。如果您使用的是OpenSSL库,则至少需要版本1.0.2。
当您拥有一个httpd
内置版本时,mod_http2
您需要一些基本的配置使其生效。与每个Apache模块一样,第一件事是您需要加载它:
LoadModule http2_module modules/mod_http2.so
您需要添加到服务器配置中的第二个指令是
Protocols h2 http/1.1
这使安全变体h2成为服务器连接上的首选协议。要启用所有HTTP / 2变体时,只需编写:
Protocols h2 h2c http/1.1
根据您放置此指令的位置,它会影响所有连接或仅影响到某个虚拟主机的连接。您可以将其嵌套,如下所示:
Protocols http/1.1 <VirtualHost ...> ServerName test.example.org Protocols h2 http/1.1 </VirtualHost>
这仅允许在连接上使用HTTP / 1,但test.example.org
提供HTTP / 2的SSL连接除外。
在SSLCipherSuite
需要具有较强的TLS加密套件进行配置。当前版本的mod_http2
不会强制执行任何密码,但大多数客户端会强制执行。将浏览器指向h2
具有不正确密码套件的已启用服务器,将迫使其仅拒绝并退回到HTTP 1.1。这是第一次为HTTP / 2配置httpd时常犯的错误,因此请记住这一点,以避免长时间的调试会话!如果要确定要选择的密码套件,请避免使用HTTP / 2 TLS黑名单中列出的密码套件。
提到的协议顺序也很重要。默认情况下,第一个是最喜欢的协议。当客户提供多个选择时,将选择最左侧的一个。在
Protocols http/1.1 h2
最优选的协议是HTTP / 1,除非客户端仅支持h2,否则它将始终被选择。由于我们想与支持HTTP / 2的客户端对话,因此更好的顺序是
Protocols h2 h2c http/1.1
订购还有另外一件事:客户也有自己的偏好。如果需要,可以将服务器配置为选择客户端最喜欢的协议:
ProtocolsHonorOrder Off
使您编写协议的订单无关紧要,只有客户的订单才能确定。
最后一件事:不检查您配置的协议的正确性或拼写。您可以提及不存在的协议,因此无需进行Protocols
任何
<IfModule>
检查。
有关配置的更多高级技巧,请参阅 有关尺寸标注以及 如何使用同一证书管理多个主机的模块部分。
httpd随附的所有多处理模块均支持HTTP / 2。但是,如果您使用的是prefork
mpm,则会受到严格的限制。
在中prefork
,mod_http2
每个连接一次只能处理一个请求。但是客户端(例如浏览器)将同时发送许多请求。如果其中之一需要花费很长时间进行处理(或者是长时间轮询),则其他请求将停止。
mod_http2
默认情况下不会超出此限制。原因是,
prefork
今天仅在运行未准备用于多线程的处理引擎的情况下才选择该引擎,例如,将因多个请求而崩溃。
如果您的设置可以处理,那么配置event
mpm是当今最好的配置(如果您的平台支持)。
如果您确实遇到困难prefork
并想要多个请求,则可以进行调整H2MinWorkers
以使之成为可能。但是,如果破裂,您将拥有这两个部分。
几乎所有现代浏览器都支持HTTP / 2,但仅通过SSL连接:Firefox(v43),Chrome(v45),Safari(自v9),iOS Safari(v9),Opera(v35),Chrome for Android(v49)和Internet资源管理器(Windows10上为v11)(源)。
其他客户端以及服务器在“实现” Wiki上列出 ,其中包括c,c ++,common lisp,dart,erlang,haskell,java,nodejs,php,python,perl,ruby,rust,scala和swift的实现。
一些非浏览器客户端实现通过明文h2c支持HTTP / 2。最通用的是卷曲。
首先要提到的工具当然是curl。请确保您的版本支持HTTP / 2,并检查以下内容Features
:
$ curl -V curl 7.45.0 (x86_64-apple-darwin15.0.0) libcurl/7.45.0 OpenSSL/1.0.2d zlib/1.2.8 nghttp2/1.3.4 Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 [...] Features: IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP HTTP2
而对于真正深入检查Wireshark的。
所述nghttp2封装还包括客户端,例如:
Chrome浏览器通过特殊的net-internals页面提供详细的HTTP / 2日志 。Chrome 和Firefox还有一个有趣的扩展, 可以在您的浏览器使用HTTP / 2时可视化。
HTTP / 2协议允许服务器向从未要求的客户端推送响应。对话的基调是:“这是您从未发送过的请求,对此的响应将很快到达……”
但是存在一些限制:客户端可以禁用此功能,并且服务器只能对来自客户端的请求进行推送。
目的是允许服务器向最可能需要的客户端发送资源:属于客户端请求的html页面的css或javascript资源。css等引用的一组图像。
客户端的优势在于,它节省了发送请求的时间,该时间可能从几毫秒到半秒不等,具体取决于两者的位置。缺点是,客户端可能会收到缓存中已拥有的东西。当然,HTTP / 2允许尽早取消此类请求,但是仍然浪费了资源。
总结一下:关于如何最好地利用HTTP / 2的这一功能,没有一个好的策略,并且每个人都还在进行实验。因此,您如何在Apache httpd中进行实验?
mod_http2
检查响应标Link
头中是否存在某种格式的标头:
Link </xxx.css>;rel=preload, </xxx.js>; rel=preload
如果连接支持PUSH,则这两个资源将发送到客户端。作为Web开发人员,您可以直接在应用程序响应中设置这些标头,也可以通过以下方式配置服务器
<Location /xxx.html> Header add Link "</xxx.css>;rel=preload" Header add Link "</xxx.js>;rel=preload" </Location>
如果要使用preload
链接而不触发PUSH,则可以使用nopush
参数,如
Link </xxx.css>;rel=preload;nopush
或者您可以完全使用指令为服务器禁用PUSH
H2Push Off
还有更多:
该模块将记录每个连接已推送的日志(基本上是URL哈希),并且不会将相同的资源推送两次。连接关闭时,该信息将被丢弃。
有人在考虑客户端如何告诉服务器已经拥有的服务器,因此可以避免对这些服务器进行推销,但这在目前是高度试验性的。
已在其中实施的另一个实验性草案mod_http2
是“
接受-推送-策略头”字段,在该字段中,客户可以针对每个请求定义其接受哪种类型的PUSH。
PUSH可能并不总是触发人们期望或希望的请求/响应/性能。在网上可以找到有关此主题的各种研究,这些研究解释了优点和缺点以及客户端和网络的不同功能如何影响结果。例如:仅仅因为服务器推送资源并不意味着浏览器将实际使用数据。
影响被按下的响应的主要因素是模拟的请求。PUSH的请求URL由应用程序提供,但是请求标头来自何处?例如,PUSH accept-language
是否会请求标头,如果是,则标明什么值?
Apache会看原始请求,并在复制下面的头推请求(触发PUSH一): ,user-agent
,accept
,
accept-encoding
,。accept-language
cache-control
所有其他标题都将被忽略。Cookies也不会被复制。推送需要显示cookie的资源将不起作用。这可能是一个辩论的问题。但是,除非使用浏览器对此进行更清晰的讨论,否则请谨慎行事,不要将cookie暴露在通常不可见的地方。
推送资源的另一种方法是Link
在响应准备就绪之前将标头发送到客户端。这使用称为“早期提示”的HTTP功能,在RFC 8297中进行了描述。
为了使用它,您需要通过以下方式在服务器上显式启用它
H2EarlyHints on
(由于某些较旧的浏览器因此类响应而跳闸,因此默认情况下未启用该功能。)
如果启用此功能,则可以使用指令H2PushResource
来触发早期提示和资源推送:
<Location /xxx.html> H2PushResource /xxx.css H2PushResource /xxx.js </Location>
"103 Early Hints"
服务器开始处理请求后,这将向客户端发送响应。根据您的Web应用程序,这可能比确定第一个响应标头的时间早得多。