为什么 Azure Front Door 让我的 Next.js 应用加载耗时 90 秒(以及我如何修复)

发布: (2026年2月22日 GMT+8 00:17)
6 分钟阅读
原文: Dev.to

Source: Dev.to

请提供您想要翻译的完整文本(文章正文),我将把它翻译成简体中文并保留原有的格式、Markdown 语法以及技术术语。谢谢!

Problem

我们在 Azure Front Door Premium 私有链接后面,将 Next.js 应用部署到 Azure Container Apps
一切都是标准配置——没有任何特殊之处。

部署后,每个页面的加载时间约为 90 秒

  • HTML 文档能够正常加载。
  • API 路由响应快速。
  • 每个 JavaScript 块 正好卡住 90 秒,随后浏览器抛出 ERR_HTTP2_PROTOCOL_ERROR(底层 HTTP/2 流因 INTERNAL_ERROR (err 2) 而终止)。

注意: 此故障影响了 所有 块,而不仅仅是一部分。

环境

组件详情
AppNext.js 16 on Azure Container Apps(内部环境,Private Link)
CDN/WAFAzure Front Door Premium
Routes• API – /api/*
• 静态资源 – /_next/static/*
• 全匹配 – /*
Next.js configcompress: true(默认)
Health probes100 % 健康;小响应正常
SSR 页面 (/sign‑in, 78 KB)通过全匹配路由在约 300 ms 内加载 – 静态资源交付是问题所在

重现问题

相同的 JS 块 – 有无 Accept‑Encoding 的情况

# Without gzip — 303 ms, full response
curl -s -w "Total: %{time_total}s\n" -o /dev/null \
  "https://my-fd-endpoint.azurefd.net/_next/static/chunks/app.js"
#=> Total: 0.303414s
# With gzip — 90 seconds, incomplete, HTTP/2 stream error
curl -s -w "Total: %{time_total}s\n" -o /dev/null \
  -H "Accept-Encoding: gzip" \
  "https://my-fd-endpoint.azurefd.net/_next/static/chunks/app.js"
#=> Total: 90.245256s

两个请求都命中 相同的文件、相同的路由、相同的源
唯一的区别是:客户端请求 gzip 压缩。

响应头(gzip 请求)

HTTP/2 200
content-type: application/javascript; charset=UTF-8
content-length: 112049
cache-control: public, max-age=31536000, immutable
content-encoding: gzip
vary: Accept-Encoding
x-cache: TCP_MISS
x-azure-ref: 20260220T195031Z-157f99bd8b842q87hC1CPH...
  • content-length: 112049 带有 content-encoding: gzip
  • curl 只报告收到 8,527 字节,随后 HTTP/2 流因 INTERNAL_ERROR (err 2) 而终止。

SSR 页面(/sign‑in)– 正常工作

HTTP/2 200
content-type: text/html; charset=utf-8
vary: rsc, next-router-state-tree, next-router-prefetch, ...
cache-control: private, no-cache, no-store, max-age=0, must-revalidate
x-cache: CONFIG_NOCACHE
  • 没有 content-encoding
  • 没有 content-length(分块传输)。

源站 不对 SSR 响应进行 gzip,即使客户端请求也是如此。这就是 SSR 页面正常而静态块失败的原因。

我们尝试了

尝试更改结果
1禁用 Front Door 压缩 (compression_enabled = false)仍然出错 – 证明问题不是双重压缩。
2完全移除缓存块仍然出错 – 缓存不是原因。
3将转发协议切换为 HttpOnly(通过 Private Link 的 TLS)仍然出错 – TLS 开销不是问题。

结论: Front Door 无法正确转发已 gzip 压缩的源站响应;它会在恰好 90 秒后停止并终止连接,这与 Front Door 不可配置的 HTTP keep‑alive 空闲超时相匹配。

这种行为 并非 Private Link 特有。Microsoft 有一篇健康建议,描述了在 PoP 之间收紧 HTTP 合规性后出现的相同故障。他们的 Q&A 线程(一个,两个)指向相同的解决方案:禁用源站压缩

修复

  1. 在源端禁用压缩。
  2. Front Door 在边缘进行压缩

示例:Next.js

// next.config.js
const nextConfig = {
  compress: false, // Front Door will compress at the edge
  // …
};

module.exports = nextConfig;

示例:Front Door 路由配置(Terraform)

resource "azurerm_cdn_frontdoor_route" "static" {
  # …
  cache {
    query_string_caching_behavior = "UseQueryString"
    compression_enabled           = true
    content_types_to_compress = [
      "text/html",
      "text/css",
      "text/javascript",
      "application/javascript",
      "application/x-javascript",
      "application/json",
      "image/svg+xml",
      "font/woff2",
    ]
  }
}

其他平台

平台如何禁用压缩
Express移除/禁用 compression 中间件。
Azure App Service设置 WEBSITES_DISABLE_CONTENT_COMPRESSION=1
Nginx (behind AFD)关闭 gzipgzip off;)。

快速诊断

对同一资源运行以下两个 curl 命令:

# 1️⃣ Without compression
curl -s -w "TTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" \
  -o /dev/null "https://your-fd-endpoint.azurefd.net/your-asset.js"

# 2️⃣ With compression
curl -s -w "TTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" \
  -o /dev/null -H "Accept-Encoding: gzip" \
  "https://your-fd-endpoint.azurefd.net/your-asset.js"

如果第一个在毫秒内完成,而第二个卡住约 90 秒,则说明您遇到了此问题。
保存错误响应中的 x-azure-ref 头部——如果向 Microsoft 提交支持工单时会需要它。

预期的健康响应(修复后)

HTTP/2 200
content-type: application/javascript; charset=UTF-8
content-length: 41182
cache-control: public, max-age=31536000, immutable
content-encoding: gzip
vary: Accept-Encoding
x-cache: TCP_HIT
x-azure-ref: …

现在,源站发送未压缩的数据,Front Door 只压缩一次,资产会立即交付。

immutable
x-cache: TCP_HIT

没有来自源站的 content‑encoding。Front Door 在毫秒级从缓存中提供。若看到 x-cache: TCP_HIT 且没有卡顿,说明一切正常。

相关资源

0 浏览
Back to Blog

相关文章

阅读更多 »

Subnetting 详解

什么是 Subnetting?可以把它想象成把一栋大型公寓楼拆分成不同的楼层。每层 subnet 拥有自己的编号主机(hosts),以及建筑……