为什么我们在负载均衡器前面放置了 CDN(以及为什么 cookies 才是真正的问题)

发布: (2026年3月13日 GMT+8 13:50)
6 分钟阅读
原文: Dev.to

Source: Dev.to

封面图片:为什么我们在负载均衡器前放置 CDN(以及为什么 Cookie 是真正的问题)

封面

上下文

我们正处于两个并行的变更之中:一次网站的全面重新设计和一次服务器迁移。这两项都有明确的计划范围,进展顺利……直到我们注意到在迁移后,一部分用户开始出现故障。并非全部用户,也不是始终如一。但已经足以构成真实的问题。

罪魁祸首:cookies

问题

之前的服务器随着时间累积了 cookies。新服务器引入了自己的 cookies。当用户在迁移过程中访问——仍在加载旧 cookies 并收到重新设计站点的新 cookies——时,合并后的负载超过了负载均衡器接受的最大大小:16 KB

此限制并非随意。它是大多数负载均衡器和 CDN 在 HTTP 层强制执行的硬性约束。一旦超出该限制,请求会悄然失败或被拒绝。

更复杂的是:域名并不在我们直接控制之下。它通过外部 DNS 提供商的 CNAME 指向负载均衡器。这意味着我们无法在不与第三方协调的情况下更改路由,也不能直接修改负载均衡器的配置。

为什么很困难

复杂的并不是技术修复,而是主要的限制:在更改期间我们不能对用户产生任何影响

错误 too_many_redirects 只会在拥有大 cookie 负载的用户出现——特定会话、特定浏览器、旧系统与新系统之间的特定路径——。一次完整的切换会让所有人面临风险。回滚也不是干净的选项,因为迁移已经部分上线。

我们需要一个解决方案,使其能够:

  • 在请求到达负载均衡器之前进行拦截。
  • 基于白名单清理 cookie(仅保留必要的)。
  • 只修改请求,不触发重定向。
  • 能够在不更改域名注册商和负载均衡器的情况下部署。

解决方案

我们在 DNS 与负载均衡器之间引入了 CDN 层,并将 CNAME 更改为指向 CDN,而不是直接指向负载均衡器。

在 CDN 的边缘,我们附加了一个 Lambda@Edge 函数,它会在每个传入请求上执行。它的工作很简单:读取 Cookie,应用白名单,删除其他所有内容,然后将干净的请求向下转发。

没有重定向。白名单中的 Cookie 不会丢失会话。无需更改应用代码或负载均衡器的配置。

最终架构如下:

[DNS → Firewall] → CDN → (Lambda@Edge) → Balanceador → Cluster

CDN 为我们提供了所需的边缘执行层。Lambda@Edge 函数让我们能够在请求层面进行精确控制。而且我们只修改请求的 header ——从不修改响应——,因此 too_many_redirects 循环从未触发。

我们学到的

  • 了解哪些是你能控制的,哪些不是。 域名不在我们的注册范围内。负载均衡器有固定的限制。用户已有的 cookie 不是可协商的。 在这些限制内工作塑造了每个决策。
  • CDN 不是目标,而是使能器。 我们添加它不是为了性能或缓存。我们添加它是因为它在我们需要的地方提供了可编程层:用户和负载均衡器之间。
  • 白名单比黑名单更安全。 与其尝试识别导致溢出的 cookie 并只删除那些,不如反转思路:定义哪些应该保留,删除其余的。更易维护,部署更安全。
  • 无停机的更改是架构决策,而不是部署技巧。 我们能够在不影响用户的情况下完成此更改并非运气:而是因为架构允许我们在不修改底层任何内容的情况下插入新层。

结论

好的架构并不总是关于最优雅的设计。有时是要了解你的系统之间如何相互作用,识别你真正拥有的杠杆点,并根据你当前的限制——而不是你希望拥有的限制——选择正确的资源。

一个 CDN 和一个小的 Lambda 函数解决了看似是 cookie 的问题。但它们真正解决的是控制问题。

0 浏览
Back to Blog

相关文章

阅读更多 »