编程

在 Apache 中实现 HTTP2

773 2023-04-15 20:30:00

本文是如何在Apache httpd 中实现HTTP/2 的教程。这一特性已经可以在生产环境中使用。

HTTP/2 协议

HTTP/2 是世界上最成功的应用层协议 - HTTP 的演进版。它关注于网络资源的更有效利用。它并没有改变HTTP的基本原理,语义。仍然是请求、响应及header等。因此,如果你已经了解过HTTP/1,  你就已经懂了HTTP/2的95%。网上有许多关于HTTP/2以及它如何运作的文章。最为规范的当然是RFC 7540(同时也是最容易读的格式)。

不过,最好还是不要在最开始的时候就去读。最好还是先去明白它要做的是什么,然后再去读RFC了解它是怎么工作的。

首先,需要先了解一些新术语:

  • HTTP/2 是一个二进制协议(binary protocol)
  • 不同于 HTTP 1.1 的普通文本plain text。
  • h2 指的是 HTTP/2 over TLS (protocol negotiation via ALPN).
  • h2c 是 HTTP/2 over TCP.
  • frame  (帧?)是一个HTTP/2 连接的最小单位,它是按照frame类型由header 和八位字节的变长系列组成。详情可以参见官方文档。
  • stream 是HTTP/2连接内的一个双向的frame流。在 HTTP 1.1 中对应的概念是一个请求/响应信息交换。
  • HTTP/2 可以在同一个TCP 连接上实现多个流(multipule streams)[即多路复用],以避免HTTP1.1中经典的慢请求阻塞慢并避免为每个请求/响应重建TCP连接(HTTP1.1中的KeepAlive补丁部分解决了这一问题,但没有完全解决)。

Apache httpd 中的 Apache

HTTP2是由Apache自己的httpd模块实现,叫做mod_http2。它实现了RFC7540中所描述的一整套特性,并支持明文HTTP/2(http:),同时支持加密连接(https:)。明文叫h2c,加密则是h2。h2c允许直接模式和upgrade模式:通过初始的 HTTP/1 请求连接。

HTTP2的一个新特性是服务端推送。详情查看RFC文档对应段落。

编译支持 HTTP/2 的 httpd

mod_http2 使用 nghttp2 库作为它的实现基础。 要编译mod_http2,你至少需要在你的系统上安装libnghttp2的1.2.1以上版本。

当你配置 ./configure  你的Apache httpd 资源树时,你需要使用--enable-http2 作为额外的参数,以激活该模块的安装。如果你的 libnghttpd2 存放在非通常位置(无论在系统何处),你可以使用--with-nghttp2=<path>配置该路径。

虽然这对大部分人都是有效的,还是有人喜欢在该模块中静态链接到nghttp2。可以使用--enable-http2-staticlib-deps,它的原理和将openssl静态链接到mod_ssl相似。 

说到SSL,你需要了解大部分浏览器只通过https连接HTTP/2,因此你需要支持SSL的服务器。不仅如此,你还需要支持ALPN扩展的SSL库。如果你用的是OpenSSL 库,你需要用v1.0.2以上的版本。