如何在 HAProxy 上启用 HTTP/2?

How can I enable HTTP/2 on HAProxy?

我们最近从 HTTP 转向了 HTTPS。由于我们已经迁移到 HTTPS,我们正在考虑迁移到 HTTP/2 以获得性能优势。

如上所述,浏览器和 LB 之间的请求是安全的 (HTTPS),而 LB 和应用服务器之间的通信仍然使用 HTTP

在当前设置下启用 HTTP /2 的可能性有多大? 我们能否在浏览器和 LB 之间启用 HTTP/2,同时保持 LB 和应用服务器之间的通信HTTP?

haproxy 还没有真正支持 http/2

它唯一的支持是检测 http/2 请求,并将 https / tcp443 tcp 流传递到支持 https 和 http/2

的服务器

这是别人的指南 http://m12.io/blog/http-2-with-haproxy-and-nginx-guide

2017 年更新:HAProxy 1.8 支持 HTTP/2

来自the 1.8 announcement

HAProxy 1.8 now supports HTTP/2 on the client side (in the frontend sections) and can act as a gateway between HTTP/2 clients and your HTTP/1.1 and HTTP/1.0 applications.

您的 haproxy.conf 中需要 h2 指令。来自 CertSimple's HAProxy HTTP/2 and dynamic load balancing guide:

frontend myapp
  bind :443 ssl crt /path/to/cert.crt alpn h2,http/1.1
  mode http

旧版本的 HAProxy

旧版本的 HAProxy,如 1.6 和 1.7 仅支持 pass-through HTTP/2 - 即,将流量引导到支持 HTTP/2 的单独应用服务器。这要复杂得多 - 请参阅有关如何执行此操作的其他答案。要终止 HTTP/2 并读取 HAProxy 上的流量,您需要 HAProxy 1.8。

如果您能够 运行 一些 NginXHaProxy,则以下内容应该适用于您的负载均衡器。 NginX 被(ab)用作纯 SSL 终结器,而不是全功能 Web 服务器,因此此 NginX 不提供任何内容。

Warning: This was done in a hurry, so nothing is verified that this really works. Some examples are missing, so sorry for the links.

我把这个想法命名为 Munchhausen 的著名照片,将自己和马从泥潭中拉出来:

孟希豪森方法

首先,do a H2 setup in HaProxy like in the answer of Scott Farrell 进行了以下调整:

frontend http-in
    mode http
    bind *:80
    option forwardfor
    default_backend nodes-http

frontend https-in
    mode tcp
    bind *:443 ssl crt /etc/ssl/dummy.pem alpn h2,http/1.1
    use_backend nodes-http2 if { ssl_fc_alpn -i h2 }
    default_backend nodes-http

frontend http-lo
    mode http
    bind 127.0.0.1:82
    #http-request set-header X-Forwarded-For req.hdr_ip([X-Forwarded-For])
    default_backend nodes-http

backend nodes-http
    mode http
    server node1 web.server:80 check

backend nodes-http2
    mode tcp
    server loadbalancer 127.0.0.1:81 check send-proxy

这会将 HTTP/2 连接循环回您的负载均衡器机器,并接受解码请求以通过 http-lo 再次进入负载均衡。

现在在 LB 本身上,启动 NginX 以在配置中侦听端口 81 实例终止 HTTP/2 连接并将其再次代理回您的负载均衡器。

在 NginX 中一定要:

  • 使用send-proxy-protocol in NginX

  • NginX

  • 中使用HTTP/2终止SSL
  • 透明地(又名。哑)代理一切回到HaProxy端口82

    # Sorry, example `NginX`-config is missing here,
    # but it includes something like:
    proxy_pass http://127.0.0.1:82;
    
  • 不要忘记在代理请求中通过 X-Forwarded-For header 包含 Client-IP (我不知道如何配置 NginX 以使用 "Send Proxy" 关于传出代理请求的协议)。

请注意,此设置大部分是静态的。更改的部分是关于所有这些域及其 TLS-certs.

HTTP/2 请求流的 ASCII 图片

     Browser
        |  HTTP/2
        V
     Loadbalancer HaProxy *:443
        |  frontend https-in
        |  backend nodes-http2
        |  send-proxy
        |  TCP (transparent, HTTP/2)
        V
     Loadbalancer NginX 127.0.0.1:81 
        |  HTTP/2 termination
        |  proxy_protocol
        |  proxy_pass 127.0.0.1:82
        |  Add header X-Forwarded-For
        |  HTTP
        V
     Loadbalancer HaProxy 127.0.0.1:82
        |  frontend https-lo
        |  Forward Header X-Forwarded-For
        |  backend nodes-http
        |  # DO YOUR LOADBALANCING HERE
        |  HTTP
        V
      web.server:80

是的,它通过 HaProxy 循环了 2 次,但是由于 HaProxy 的运行速度如此之快,它的运行速度快如闪电。

真正低效的部分是将 HTTP/2 header 解压缩为纯 HTTP headers ..