在 http 模式下对 HTTP/2 后端服务器的 HA 代理支持

Posted

技术标签:

【中文标题】在 http 模式下对 HTTP/2 后端服务器的 HA 代理支持【英文标题】:HA Proxy support for HTTP/2 backend servers in http mode 【发布时间】:2018-07-06 03:51:11 【问题描述】:

我有一个支持 HTTP/2 并在 TLS1.2 上运行的 tomcat 9.0.2 服务器。下面是 server.xml 中的连接器配置

<Connector port="8443" protocol="org.apache.coyote.http11.Http11Nio2Protocol"
    address="0.0.0.0"
    maxThreads="150" SSLEnabled="true" asyncTimeout="10000" maxHeaderCount="50"
    maxPostSize="1048576" scheme="https" secure="true" compression="force" 
    compressionMinSize="2048" maxConnections="10000">
    <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
    <SSLHostConfig protocols="TLSv1.2">
        <Certificate certificateKeystoreFile="$keystore.file.path"
            certificateKeystorePassword="$keystore.password"
            certificateKeyAlias="$server.cert.alias"
            certificateKeystoreType="$keystore.type" />
    </SSLHostConfig>
</Connector>

我使用的是 HA Proxy 1.8,配置如下

frontend  mydomain-ux
  mode    http
  bind    <ip>:8080 ssl crt /etc/certs/mydomain.com.cert.pem
  http-request set-var(txn.path) path
  acl mydomain hdr_end(host) -i mydomain.com
  use_backend mydomain_server if mydomain  

backend  mydomain_server
  mode    http
  server  mydomain_backeend_server <server-ip>:8443 ssl

由于我有多个基于主机的后端,我不能使用 TCP 模式并通过 HTTP/2 SSL 终止

有没有办法在后端模式 http 中终止 HTTP/2?

【问题讨论】:

【参考方案1】:

据我所知,HAProxy 不支持后端的 HTTP/2。他们只有recently announced front end support。 (2019 年 1 月 18 日编辑 - 自 v1.9 中添加 - https://www.haproxy.com/blog/haproxy-1-9-has-arrived/)。

即使没有后端 HTTP/2 支持,可以在 HTTPS 上终止前端,然后通过 TCP(不使用 HTTPS)转发到后端,并且 可以 可以使用 HTTPS 的 SNI 部分来执行您想要的可选路由(顺便说一句,这是完全未经测试的):

frontend  mydomain-ux
  mode    tcp
  bind    <ip>:8080 ssl crt /etc/certs/mydomain.com.cert.pem alpn h2,http/1.1
  use_backend     mydomain_server      if  ssl_fc_sni mydomain.com
  use_backend     mydomain_server2     if  ssl_fc_sni mydomain2.com 
  default_backend mydomain_server

backend  mydomain_server
  mode    tcp
  server  mydomain_backeend_server <server-ip>:8081

这将允许您的后端在端口 8081 上使用 HTTP/2,但不使用 HTTPS(端口 8443),甚至可以在 1.8 之前的 HAProxy 上工作(当添加了前端 HTTP/2 支持时)。但是,这意味着您的 Tomcat 需要在没有 SSL 的情况下进行设置。

HAProxy 也不建议使用 SNI 主机进行路由,如 this answer 和 mailing thread it refers to 中所述。另外,SNI 支持并不是普遍的(尽管从所有实际意图来看,除非支持像 XP 上的 IE8 这样的非常旧的浏览器)。

您应该问自己的另一个问题是if you really need HTTP/2 in the backend or if just supporting this at the HAProxy level is enough?

【讨论】:

根据建议,我会等到后端服务器严重需要 HTTP/2。接受了答案,但我现在没有尝试规定的配置。 是的,这就是我推荐的。当有严重需求时,HAProxy 可能会在后端原生支持它。老实说,上面有点破解。 haproxy 1.9 发布并支持后端 HTTP/2 haproxy.com/blog/haproxy-1-9-has-arrived > 开启后,您可以在后端服务器上使用 HTTP/2。将 alpn h2 添加到服务器行(或 alpn h2,http/1.1,如果您希望让 HAProxy 与服务器协商协议)。 谢谢。更新了答案以反映这一点。【参考方案2】:

我在 Barry Pollard 上一篇文章的基础上做了一个完整的 h2 管道基础,并进行了一些修改,现在它的工作已经足够好,可以在开发中使用。需要进行一些进一步的测试来清除生产路径。但至少它的工作。

浏览器不支持 h2 明文 (h2c),因为 google 希望每个人都使用 ssl,但它在 2 个 httpd 服务器之间工作正常(使用 apache 测试,但不使用 nginx 或 tomcat 或其他任何 httpd)。

frontend  mydomain-ux
  mode    tcp
  bind    0.0.0.0:443 ssl crt /etc/ssl/tdl.pem  alpn h2,h2c,http/1.1
  bind    0.0.0.0:80  alpn h2,h2c,http/1.1
  use_backend     mydomain_server     if  ssl_fc_alpn -i h2 
  default_backend mydomain_server

backend  mydomain_server
  mode    tcp
  http-request add-header X-Forwarded-Proto https
  server  mydomain_backeend_server 1.1.1.1:80
  server  mydomain_backeend_server2 1.1.1.2:80

这是我从后端 access_log 看到的:

1.1.1.3 - - [17/Jan/2019:10:57:49 -0500] "GET / HTTP/2.0" 403 3985 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/ 537.36(Khtml,如 Gecko)Chrome/71.0.3578.98 Safari/537.36"

【讨论】:

模式 tcp 和 http-request 在同一个后端?那一定是错字吧?

以上是关于在 http 模式下对 HTTP/2 后端服务器的 HA 代理支持的主要内容,如果未能解决你的问题,请参考以下文章

TCP 模式下基于 AWS ELB 的 HTTP2

如何在禁用客户端类创建的情况下对解析服务器模式进行建模

设计模式-单例模式下对多例的思考(案例:Server服务器)

Windows 2016 IIS 上 HTTP/2 的混合模式

如何在 dotnet core 中为 HttpClient 指定 HTTP/2“先验知识”模式?

http 工作模式与模块