Configure HTTP/2 in Different Application Engines

预计阅读时间:4分钟

HTTP / 2是一种现代的二进制双工多路复用协议,旨在替代HTTP / 1.x.

Jetty,Netty和Tomcat引擎提供了Ktor可以使用的HTTP / 2实现. 但是,两者之间存在显着差异,并且每个引擎都需要其他配置. 为Ktor正确配置主机后,将自动激活HTTP / 2支持.

关键要求:

  • SSL证书(可以自签名)
  • 适用于特定引擎的ALPN实现(请参阅有关Netty,Jetty和Tomcat的相应部分)
  • 兼容HTTP / 2的浏览器(根据caniuse.com ,自2015年底以来,所有主流浏览器都支持它)

SSL certificate

根据规范,HTTP / 2不需要加密,但是所有浏览器都需要加密的连接才能与HTTP / 2一起使用. 这就是为什么有效的TLS环境是启用HTTP / 2的前提条件. 因此,需要证书才能启用加密. 为了进行测试,可以使用JDK的keytool生成它:

keytool -keystore test.jks -genkeypair -alias testkey -keyalg RSA -keysize 4096 -validity 5000 -dname 'CN=localhost, OU=ktor, O=ktor, L=Unspecified, ST=Unspecified, C=US'

下一步是配置Ktor使用您的密钥库. 请参阅示例application.conf:

application.conf
ktor {
    deployment {
        port = 8080
        sslPort = 8443
        watch = [ ]
    }

    application {
        modules = [ com.example.ModuleKt.main ]
    }

    security {
        ssl {
            keyStore = /path/to/test.jks
            keyAlias = testkey
            keyStorePassword = changeit
            privateKeyPassword = changeit
        }
    }
}

ALPN implementation

HTTP / 2要求启用ALPN( 应用程序层协议协商 ). 不幸的是,JDK的TLS实现不支持ALPN,因此您的应用程序引擎必须正确配置. 第一种选择是使用需要添加到引导类路径的外部ALPN实现. 另一个选择是使用OpenSSL本机绑定和预编译的本机二进制文件. 两种方法都容易出错,并且在配置时需要格外注意. 而且,每个特定引擎只能支持这些方法之一.

Jetty

Jetty支持JDK ALPN扩展,要使其正常工作,您必须为java 启动类路径添加一个额外的依赖项. 将其添加到引导类路径非常重要,因为将其添加到常规类路径不起作用.

另一个问题是确切的依赖版本取决于JDK版本. 例如,对于JDK 8u144,应使用alpn引导8.1.11.v20170118(有关完全兼容性,请参见https://www.eclipse.org/jetty/documentation/9.4.x/alpn-chapter.html#alpn-versions清单).

应该应用以下JVM选项(路径可以是相对的):

-Xbootclasspath/p:/path/to/alpn-boot-8.1.11.v20170118.jar

根据您的构建系统,您可能需要将依赖项复制到某些特定目录. 在Maven中,您可以在Gradle中使用maven-dependency-plugin (目标copy-dependencies )或Copy任务.

<build>
    <plugins>
        <plugin>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>unpack-jetty-alpn</id>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <phase>compile</phase>
                    <configuration>
                        <includeArtifactIds>alpn-boot</includeArtifactIds>
                        <stripVersion>true</stripVersion>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

如果以上所有操作均正确完成,Jetty将记录启用ssl,alpn和h2的日志:

INFO  org.eclipse.jetty.server.Server - jetty-9.4.6.v20170531
INFO  o.e.jetty.server.AbstractConnector - Started ServerConnector@337762cd{HTTP/1.1,[http/1.1, h2c]}{0.0.0.0:8080}
INFO  o.e.jetty.util.ssl.SslContextFactory - x509=X509@433defed(testkey,h=[],w=[]) for SslContextFactory@2a693f59(null,null)
INFO  o.e.jetty.server.AbstractConnector - Started ServerConnector@49c90a9c{SSL,[ssl, alpn, h2, http/1.1]}{0.0.0.0:8443}
INFO  org.eclipse.jetty.server.Server - Started @1619ms

Netty

在Netty中启用HTTP / 2的最简单方法是使用OpenSSL绑定( tcnative netty port ). 将API jar添加到依赖项:

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-tcnative</artifactId>
    <version>${tcnative.version}</version>
</dependency>

然后是本机实现(静态链接的BoringSSL库,OpenSSL的一个分支):

    <dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-tcnative-boringssl-static</artifactId>
        <version>${tcnative.version}</version>
    </dependency>

    <dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-tcnative-boringssl-static</artifactId>
        <version>${tcnative.version}</version>
        <classifier>${tc.native.classifier}</classifier>
    </dependency>

其中tc.native.classifier应该是以下之一: linux-x86_64osx-x86_64windows-x86_64 .

提供所有依赖项后,Ktor将在SSL端口上启用HTTP / 2支持.

Tomcat and other servlet containers

与Netty相似,要使HTTP / 2在Tomcat中工作,您需要本机OpenSSL绑定. 不幸的是,Tomcat的tcnative与Netty one并不完全兼容. 这就是为什么您需要稍微不同的二进制文件的原因. 您可以在此处获取它( https://tomcat.apache.org/native-doc/ ),也可以尝试Netty的tcnative. 但是,您必须猜测哪个确切版本与您的特定Tomcat版本兼容.

如果要将Ktor应用程序作为war包部署到服务器(servlet容器)中,则必须正确配置Tomcat服务器:

by  ICOPY.SITE