在 Go 1.24 中使用 HTTP/2 Cleartext 服务器

Hacker News Top 工具

摘要

Go 1.24 在 net/http 包中引入了对 HTTP/2 Cleartext (h2c) 的原生支持,消除了之前使用外部包装包的需求。本文介绍了如何配置 Go HTTP 服务器以使用 h2c 与 Google Cloud Run 等服务配合工作。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/05/24 21:42

# 配置 Go HTTP 服务器以支持未加密的 HTTP/2 (h2c) | ClarityBoss 博客 来源:https://www.clarityboss.com/blog/go-http2-cleartext-h2c-cloud-run 在我们的应用中,我们使用了长寿命的服务器推送事件流(SSE)。这些连接的超时时间和生命周期都被设置得很长——在我们的配置中为 15 分钟。然而,Google Cloud Run 有一个已知问题(https://docs.cloud.google.com/run/docs/troubleshooting#client-disconnect),即当使用 HTTP/1.1 与后端服务通信时,客户端的断开连接事件不会传播到 Cloud Run。因此,我开始研究为服务使用 HTTP/2(https://docs.cloud.google.com/run/docs/configuring/http2)。 Cloud Run 在前端终止 TLS,但可以以 HTTP/1.1 或未加密的 HTTP/2(`h2c`)流量形式转发流量。通常,HTTP/2 始终使用 TLS,但 HTTP 客户端和服务器通常可以配置为使用该协议的未加密版本。Cloud Run 还要求你选择要使用的协议。这基本上就是 RFC 9113 第 3.3 节中所描述的“具有先验知识的 HTTP/2”设置。 ## 为 Go 服务器配置未加密的 HTTP/2 我们对 `h2c` 支持的首次实现早于 Go 1.24 的变更,我将在下面详细介绍这些变更。互联网上的大多数帖子和指南都会指向旧的过时方法,但我在下面已经包含了旧方法,以便更容易看到前后对比,并在需要时迁移你自己的代码。 ### Go 1.24 之前(旧方法) 要使用 `h2c`,你必须使用 `golang.org/x/net/http` 包,并进行复杂的设置。 `` import ( "net/http" "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" ) handler := ... // 现有的 `handler` 必须被包装,附加到服务器,然后进行配置 h2s := &http2.Server{} handler = h2c.NewHandler(handler, h2s) srv := &http.Server{ Addr: fmt.Sprintf("%s:%d", "", 9888), Handler: handler, ReadHeaderTimeout: 5 * time.Second, ReadTimeout: 10 * time.Second, WriteTimeout: 35 * time.Second, // https://cloud.google.com/load-balancing/docs/https/request-distribution#timeout-bes IdleTimeout: 620 * time.Second, } err = http2.ConfigureServer(srv, h2s) if err != nil { ... } `` ### Go 1.24+(新方法) 从 Go 1.24 开始,不再需要 `x/net/http2/h2c` 包装器,设置也更具可读性。你可以直接在 `http.Server` 上配置协议。 参考:Go 1.24 net/http 发布说明(https://go.dev/doc/go1.24#nethttppkgnethttp)。 `` handler := ... srv := &http.Server{ Addr: fmt.Sprintf("%s:%d", "", 9888), Handler: handler, ReadHeaderTimeout: 5 * time.Second, ReadTimeout: 10 * time.Second, WriteTimeout: 35 * time.Second, // https://cloud.google.com/load-balancing/docs/https/request-distribution#timeout-bes IdleTimeout: 620 * time.Second, } srv.Protocols = new(http.Protocols) srv.Protocols.SetHTTP1(true) srv.Protocols.SetUnencryptedHTTP2(true) `` ### 在部署前进行本地测试 测试非常简单。如果未正确设置未加密的 HTTP/2,以下命令将失败。 `` curl -i --http2-prior-knowledge http://localhost:9888 `` ## Terraform Cloud Run 配置 一旦你的 Go 服务能够使用未加密的 HTTP/2,就需要在 Cloud Run 中进行适当配置。如果你通过 Cloud Run 控制台操作,请遵循 HTTP/2 服务文档(https://docs.cloud.google.com/run/docs/configuring/http2)。我们通过 terraform 进行操作——以下代码片段提供了配置的总体思路。 `` # 许多与本帖无关的设置已省略。 resource "google_cloud_run_v2_service" "api" { name = "api" location = var.primary_region invoker_iam_disabled = true ingress = "INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER" template { containers { ... ports { name = "h2c" container_port = 9888 } } # 默认值为 80;对于空闲的 SSE 连接,我们可以轻松扩展到更高的值。 max_instance_request_concurrency = 200 # 默认值为 300 秒,但对于 SSE,我们希望允许长寿命连接。 timeout = "900s" } lifecycle { ignore_changes = [client, client_version, template[0].revision] } } `` 在负载均衡器层面不需要进行任何实质性的更改,因为与 Serverless NEG 通信时使用的是 HTTPS,并且在此过程中似乎可以正常将连接升级到 HTTP/2。此外,无服务器后端的默认超时时间为 60 分钟,而不是某些其他后端的 30 秒。

相似文章

Codex发现一个隐藏的HTTP/2炸弹

Lobsters Hottest

Codex发现了一个名为“HTTP/2炸弹”的远程拒绝服务漏洞,该漏洞针对主流Web服务器(包括nginx、Apache、IIS、Envoy、Pingora)中的HPACK压缩,通过将压缩炸弹与流量控制保持相结合,快速耗尽服务器内存。

使用 Go 的 net/http/httptrace 追踪 HTTP 请求

Hacker News Top

本文介绍了如何使用 Go 的 net/http/httptrace 包通过基于上下文的钩子追踪 HTTP 请求阶段(DNS、连接、TLS 等),并演示了构建 CLI 追踪工具和 RoundTripper 日志记录器。

httpx2 - Pydantic 的分支

Lobsters Hottest

Pydantic 复刻了 httpx HTTP 库,创建了 httpx2,以解决维护问题。原始分支 httpxyz 对此表示欢迎,并鼓励社区支持 httpx2。

就用Go

Lobsters Hottest

一篇带有强烈观点的开发者文章倡导使用Go编程语言,强调其简洁的语法、强大的标准库、高效的并发模型以及单二进制部署,作为对过于复杂的现代技术栈的实用替代方案。