English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

un

访客
1 / ?
返回课程列表

什么在每个 Web 服务前面

欢迎

如果你在浏览器中输入 example.com,你几乎很少直接访问运行应用程序的机器。你访问的实际上是将请求转发给真正处理请求的机器的机器。这台转发机器被称为 反向代理

这堂课将教你什么是反向代理、为什么几乎每个公共 Web 服务都隐藏在后面、以及边缘层同时承担的三种不同职责。

到此你将理解:

- 客户端、代理和源之间的区别

- 为什么源后面的代理保护、扩展和让你无需任何人注意就可以替换部分组件

- 反向代理一次承担的三种职责:隐藏源、终止 TLS 和在复制件之间分发负载

- 请求从浏览器到代理到上游的旅程,每一步都详细说明

到此你将自信地推理代理放置、边缘层的关注分离以及为什么一个无状态代理层可以无限扩展而一个源却无法扩展的原因。

前向代理 vs 反向代理

两种代理方向

两种代理都在两个方之间站立,转发流量。它们的区别在于 它们代表的方

前向代理:在客户端前面站立。客户端知道有代理;外部服务器看到的是代理地址,而不是客户端地址。企业出入口代理、内容过滤器和 SOCKS 代理都属于这一类。

反向代理:在服务器前面站立。外部世界(客户端)与代理地址进行通信;客户端不知道实际服务器隐藏在后面。几乎每个公共 Web 服务都使用了它。

助记词:前向代理隐藏客户端给服务器。反向代理隐藏服务器给客户端。

为什么关心方向? 工作、故障模式和安全边界都不同。前向代理关心它的用户联系谁;反向代理关心谁联系它的服务器。

客户端通过两种代理同时发送流量: client -> forward_proxy -> internet -> reverse_proxy -> origin.

一个小公司运行一个聊天应用。他们希望每个外部用户的请求都直接到达隐藏真实聊天服务器的机器。他们需要什么类型的代理,外部用户实际上连接到的是什么?

为什么边缘层次有这么多

边缘层次为所欲为

反向代理同时承担三项工作。其中任何一项都可以证明这一层的存在价值;而在相同地址上执行所有这些工作,解释了为什么几乎每个生产Web架构在前端都呈现相同的形状。

工作1:隐藏源。代理在公网IP上响应。后端位于无法通过互联网访问的私有IP上。想要攻击源的攻击者必须先攻破代理。

工作2:终止TLS。代理持有 example.com 的证书,并解密入站HTTPS请求。后端在代理后面的受信任网络分段上使用明文HTTP(或更简单的内部TLS)与代理通信。证书轮换、续订和密码策略都集中在一个地方。

工作3:负载分配。代理决定哪个后端处理每个请求。一个代理后面的后端形成一个池子;代理根据策略(轮循、最小连接数、基于头部的散列)为每个请求选择一个。增加容量意味着向池子中添加一个后端,而不是告诉每个客户端一个新的地址。

每项工作都是一个小程序。一起它们解释了为什么一个层次比如‘Caddy在Python应用前面’比Python应用本身更有设计价值。

反向代理承担三项工作:隐藏源、终止TLS、分配负载

为所有三项设计

您的团队在单个VM上运行一个小型API,Python进程监听8000端口。由于流量增长,一个VM无法保持同步,而且安全审计发现VM有公网IP并运行自己的TLS证书。

您决定在前面放置一个反向代理。画出布局:DNS指向哪里,证书存放在哪里,负载如何到达后端,以及原始VM发生了哪些变化?

走一遍新的架构。解决所有四个部分:DNS目标、TLS终止位置、负载分配策略和原始VM保留或丢失的内容。

在没有任何人注意的情况下更换一个组件

间接性买入自由度

计算机科学的一个老谚语是:每个问题都可以通过添加一层间接性来解决(除了太多层间接性的问题)。在分布式系统中,反向代理是最有用的间接性之一。

它为您购买了:

- 可以更换后端。 将应用程序从Python更换为Go?将从一个数据中心迁移到另一个数据中心?无缝部署新版本?所有这些都发生在稳定的公共地址后面。用户没有任何变化。

- 独立扩展。 代理层次在TLS层上的带宽和CPU上扩展,后端层次在应用程序工作上扩展。每个都在不同的机器上沿着自己的轴线生长。

- 故障隔离。 后端上的一次坏部署不会导致公共地址失效。代理仍然保持运行,您可以推出修复或回滚,世界在后端恢复时重新连接。

- 将横切关注点放在一个地方。 代理层面上的限流、地理屏蔽、请求日志、头部重写、缓存、响应压缩:所有这些都在代理层面上。后端代码专注于应用程序。

没有代理,所有这些问题都必须在应用程序进程内部解决。有了代理,它们都在一个层面上,一个团队负责。

成本:需要操作额外的一层。成熟的团队接受这个成本,因为代理层本身在无状态和水平扩展方面运行;将一个代理替换为两个不需要任何协调。

通过代理进行蓝绿部署

您的团队在反向代理后面运行API版本1的三个后端虚拟机(蓝色池)。您想部署版本2,并在出现问题时在30秒内快速回滚。

您启动三个运行版本2的后端虚拟机(绿色池),与蓝色池并排运行,但尚未将任何流量路由到它们。

解释一下反向代理是如何让您从蓝色切换到绿色的同时,快速回滚,以及如果应用程序直接暴露给客户端而没有代理,这将不可能发生。

从浏览器到后端,再到回复

跟踪一个请求的全过程

通过一个反向代理前面的后端池,跟踪一次https://api.example.com/users/42的HTTPS GET请求。

跳 1:DNS解析。浏览器向解析器询问api.example.com。解析器返回代理的公网IP(例如,203.0.113.10)。浏览器打开一个到203.0.113.10:443的TCP连接。

跳 2:TLS握手。代理为api.example.com提供证书。浏览器验证证书,两者达成会话密钥一致,并打开加密通道。

跳 3:在TLS内发送HTTP请求。浏览器发送GET /users/42 HTTP/1.1\nHost: api.example.com\n...。代理解密请求字节。

跳 4:后端选择。代理根据api.example.com查询其上游池,并选择一个后端(例如10.0.0.21:8000),使用其负载均衡策略。

跳 5:上游请求。代理(可能重新使用)打开一个纯HTTP连接到10.0.0.21:8000,转发请求。代理在途中可能重写头部:添加X-Forwarded-For: <client-ip>,正确设置Host:,去除跳跃式头部,如Connection

跳 6:后端处理。后端应用读取请求,查询数据库,构建JSON响应。

跳 7:上游响应。后端将响应发送回代理作为纯HTTP。

跳 8:边缘响应。代理可能对响应进行重写或压缩,将其重新加密通过TLS会话,并将其发送给浏览器。

跳 9:连接生命周期。TLS会话通常保持打开状态以便下一个请求(HTTP/2在一个连接上多路复用多个请求)。代理到后端连接通常保留以便重用。

每个公共网服务都遵循这个形状的某种变体。了解跳跃可以让你推理出延迟累积的位置、日志应放置的位置以及故障可能隐藏的地方。

请求生命周期:浏览器,DNS,代理,TLS,上游,后端,响应

时间都去哪儿了?

A 用户抱怨 API 感觉慢。你测量并发现请求总共耗时 850 ms。后端服务器日志显示应用程序在 40 ms 内处理了请求。代理日志显示代理在工作过程中耗时 50 ms (TLS 握手 + 路由 + 响应写入)。

其他 760 ms 去向何在?至少列举两种候选者,生活在代理与后端处理时间之外,并解释每种如何在测量中出现。

为新服务设计最小边缘架构

合成

您已经了解了前向代理与反向代理的区别,反向代理一次处理三项工作,隐藏源原因每次需要更改时都能收获,请求如何在边缘逐跳地通过。

现在应用它。

一小组团队计划推出一个新的服务称为 notes.example.com。用户将阅读和写入个人笔记。该团队将在启动时运行两台后端虚拟机,并预计在未来一年内扩展到十台。他们希望为用户提供 HTTPS,逐步发布新版本,并且不公开后端 IP。

为 notes.example.com 设计边缘架构。涉及:DNS 指向的位置,TLS 证书存储位置,请求如何到达后端,请求从两台到十台后端增长时发生的变化,以及您将在边缘而不是在应用程序内部添加的交叉关注领域(例如限流、日志记录、头部重写等)。

本课程的下一步

本课程的下一步

本课时建立了 边缘层形状。这门课程的四个课时继续扩展:

- 无状态水平扩展: 为什么代理层(及其后面的后端)可以廉价扩展,以及在洪峰期间如何根据复制数量进行-sizing。

- 入口/出口分离: 为什么处理同时处理入站和出站流量的单个代理 ultimately 失败,以及如何将层次分开。

- 故障模式与爆炸半径: 如何一个配置更改蔓延成停机,以及如何编写无责行动项以防止重发。

- 可观察性与容量: 在边缘处如何衡量指标以在用户之前发现问题。

每个课程都是独立的。一起它们给你一个关于大规模Web集群的工作思维模型。

配套课程:geometry_of_proxies_and_origins 将本课的所有内容都转化为有向图并探索图论对请求路径的启示。

好极了。向前。