• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • HTTP / 2指南

    这是Apache httpd中HTTP / 2实现的方法指南。此功能已投入生产,您可能希望接口和指令保持一致的版本。

    HTTP / 2协议

    HTTP / 2是世界上最成功的应用程序层协议HTTP的演进。它专注于更有效地利用网络资源。它不会改变HTTP的基本原理,即语义。仍然有请求,响应,标头等等。因此,如果您已经知道HTTP / 1,那么您也知道95%的HTTP / 2。

    关于HTTP / 2及其工作原理的文章很多。当然,最规范的是其RFC 7540 (也以更易读的格式YMMV提供)。因此,您将在其中找到螺母和螺栓。

    但是,就像RFC一样,首先阅读并不是一件真正的好事。最好是先了解什么事情想要做,然后阅读有关RFC 如何它完成。http:// curl 的作者Daniel Stenberg 解释了一个更好的文档。它也以越来越多的语言提供!

    太长了,没看过:在阅读本文档时,需要牢记一些新的术语和陷阱:

    • HTTP / 2是一种二进制协议,与纯文本的HTTP 1.1相反。后者是人类可读的(例如嗅探网络流量),而前者则不是。有关官方FAQ 问题中的更多信息。
    • h2是TLS上的HTTP / 2(通过ALPN进行协议协商)。
    • h2c是TCP上的HTTP / 2。
    • 是通信的最小单位的HTTP / 2连接内,包括一个首部,并根据帧类型的结构的八位字节的可变长度的序列。有关更多信息,请参见官方文档部分。
    • 是帧的HTTP / 2连接内的双向流动。HTTP 1.1中的对应概念是请求/响应消息交换。有关更多信息,请参见官方文档部分。
    • HTTP / 2能够在同一个TCP连接上运行多个数据流,避免了经典的HTTP 1.1头阻止缓慢的请求,并且避免了为每个请求/响应重新实例化TCP连接(KeepAlive修补了HTTP 1.1中的问题,但确实不能完全解决)。

    Apache httpd中的HTTP / 2

    HTTP / 2协议由其自己的httpd模块(恰当地命名为)实现mod_http2。它实现了RFC 7540所描述的全部功能,并支持明文(http :)上的HTTP / 2,以及安全(https :)连接。明文变体的名称为“h2c”,安全名称为“h2”。因为h2c它允许直接模式和Upgrade:通过初始HTTP / 1请求。

    为Web开发人员提供新功能的HTTP / 2功能之一是 Server Push。请参阅该部分以了解您的Web应用程序如何使用它。

    使用HTTP / 2支持构建httpd

    mod_http2使用nghttp2库作为其实现基础。为了进行构建,mod_http2您至少需要在libnghttp2系统上安装1.2.1版本。

    当您./configure使用Apache httpd源代码树时,需要将其'--enable-http2'作为附加参数来触发模块的构建。如果您libnghttp2居住在不寻常的地方(无论操作系统上是什么地方),都可以使用'--with-nghttp2=<path>'到宣布其位置configure

    尽管这对于大多数人来说应该可以解决问题,但他们还是希望nghttp2在此模块中使用静态链接的人。对于这些,该选项--enable-nghttp2-staticlib-deps存在。它的工作原理与将opensl静态链接到的方式非常相似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

    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>检查。

    有关配置的更多高级技巧,请参阅有关尺寸标注以及如何使用同一证书管理多个主机的模块部分。

    MPM配置

    httpd随附的所有多处理模块均支持HTTP / 2。但是,如果您使用的是preforkmpm,则会受到严格的限制。

    在中preforkmod_http2每个连接一次只能处理一个请求。但是客户端(例如浏览器)将同时发送许多请求。如果这些请求之一需要很长时间处理(或者是长时间轮询),则其他请求将停止。

    mod_http2默认情况下不会超出此限制。原因是prefork今天仅在运行未准备用于多线程的处理引擎的情况下才选择此选项,例如,将因多个请求而崩溃。

    如果您的设置可以解决问题,则配置eventmpm是当今最好的选择(如果您的平台支持)。

    如果您确实遇到困难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。最通用的是卷曲。

    调试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
    

    Mac OS homebrew notes

    brew install curl --with-openssl --with-nghttp2

    而对于真正深入检查Wireshark的。

    所述nghttp2封装还包括客户端,例如:

    • nghttp-用于可视化HTTP / 2框架并更好地了解协议。
    • h2load-对服务器进行压力测试很有用。

    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,则这两个资源将发送到客户端。作为网络开发人员,您可以直接在应用程序响应中设置这些标头,也可以通过以下方式配置服务器

    <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-agentacceptaccept-encoding,。accept-languagecache-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应用程序,这可能比确定第一个响应标头的时间早得多。

    如果H2Push启用,则也将在103响应后立即启动PUSH。H2Push但是,如果禁用,则仍将103响应发送给客户端。