- 代理通常部署在两个隔离网络的中间,负责从一侧到另一侧的数据传输。
- 第一代代理的功能不足以满足当前技术趋势的需求。
- 开发人员总是在不牺牲前几代代理的速度和可靠性的情况下寻求更多功能。
- 新一代代理需要通过易于使用的管理面板、REST 接口或通过内置脚本支持进行编程来支持新功能的定制、扩展和开发。
- 对于要标记为可编程代理的代理,它们需要履行几个承诺和目标,包括支持扩展核心功能、动态逻辑等。
- 可编程代理应提供更容易的接口以与外部系统集成或适应更大的管理系统。

一个经常被问到的问题是“什么是可编程代理,我为什么需要一个?” 本文试图从不同的角度回答这个问题。我们将从对什么是代理的简要定义开始,然后讨论代理是如何在不同阶段演变的,解释它们响应的需求以及它们在每个阶段提供的好处。最后,我们将讨论可编程性的几个方面,并总结为什么我们需要可编程代理。
什么是代理?
代理服务器通常部署在两个隔离网络的中间,负责从一侧到另一侧的数据传输,因此它们看起来像一个网络。在最简单的形式中,代理是用户和互联网之间的网关,因为它自计算机网络诞生以来就存在。但是,代理不仅充当网络连接器,还支持其他功能和用例,例如:
- 路由。代理根据传输数据的特性将数据转发到不同的目的地。
- 负载均衡。在转发过程中,数据被分发到不同的目的地,以提高吞吐量并避免单点故障。第 4 层或第 7 层负载平衡是代理服务器的用例之一。
- 故障转移。当转发到给定目的地失败时,代理可以选择备用目的地,为请求者提供不间断的服务。
- 访问控制。代理可以决定允许通过哪些流量以及需要阻止哪些流量。Web 应用程序防火墙 (WAF) 就是一个典型的例子。
- 身份管理。访问控制通常基于身份信息,因此代理通常也具有身份管理功能。
- 网络加速。代理通过缓存数据来加速网络访问。
- 指标集合。Proxy 捕获数据统计数据并将其汇总到 Network Performance Monitor (NPM) 软件中,用于网络优化和网络规划。
- 信息安全。除了访问控制之外,代理还可以用于安全审计、TLS/SSL 卸载和数据加密,以满足安全要求。
在 ISO/OSI 模型的第 4 层和第 7 层工作的代理有时称为“路由模式”代理。大多数代理服务都是开源软件,占网络基础设施软件的大部分,提供不同领域的专业功能,例如特定协议的代理、负载平衡的代理、缓存加速的代理等。
代理软件演进

代理服务器经历了不同的发展阶段:
配置文件时代
这一代代理完全基于配置。用户设置一些参数,在配置文件中配置规则,然后启动服务进程来执行这些规则。
配置DSL时代
静态配置文件难以表达复杂的逻辑,因此许多代理在配置文件之上引入了精简脚本功能。这些通常被称为“配置语言”或领域特定语言(简称 DSL),例如Haprxoy 的 ACL或varnish 的 VCL。
脚本语言时代
随着逻辑变得越来越复杂,通过配置语言表达它变得越来越困难。同时,当同一网络中使用的不同配置语言的数量达到一定阈值时,它们的管理变得困难。
例如,使用 shell 脚本可以编写简单的逻辑,但是当 shell 代码达到一定程度的复杂性时,通常需要升级到更结构化的脚本语言,如 Perl 或 Python。
这种语言带来了脚本的便利性和成熟的编程语言的结构优势。例如OpenResty (nginx + Lua) 和Nginx Plus (Nginx + NJS)。此类别还包括以多种应用程序编程语言实现的代理服务器,例如基于节点的StrongLoop Microgateway和基于 Java 的Spring Cloud Gateway,它们通常具有自己的脚本功能。
集群时代
脚本语言解决了模块化和结构化复杂逻辑所固有的复杂性。此时的另一个要求是将代理与其他管理控制工具集成,因此需要 REST 或类似接口。实际上,外部控制平面可以使用该接口来动态更新脚本中的逻辑。
同时,代理的使用已经从单个实例转移到代理集群。事实上,像Envoy和基于 OpenResty 的Kong这样的代理软件本身通常支持集群功能,以某种集中或共享的方式(通过 RDBMS 等)实现它们,同时还提供 REST 管理接口来管理配置。
对于这个时代之前的代理,集群管理通常可以通过配置管理来实现。配置管理工具还可以公开 REST 接口。例如,Ansible + Nginx实现了与云时代代理类似的功能。相比之下,集群时代的代理需要更多的组件来形成方案,而云时代的代理则消除了管理移动部件的负担,因此更受欢迎。
云时代
在云时代,代理以分布式方式部署。最常见的场景是为每个应用程序进程部署一个代理,遵循边车代理模式。
在集群模式下,对于不同的上游服务,通常会有不同的配置和策略,例如不同的认证方式和访问控制机制。随着上游服务的增长,这些不同的上游服务的配置在逻辑上是分开的,但在物理上运行在同一个代理进程中。这种方案有一些缺点:在同一个进程中运行更多的逻辑会带来更多的复杂性。另外,不同的上游服务共享CPU、内存等资源,相互影响。如果上游服务的脚本存在安全漏洞,其他上游服务的配置可能会被泄露,从而产生安全风险。
在云时代,各个上游服务的代理进程相互独立,相互隔离。分布式代理的采用为不同的上游服务使用不同的规则和策略打开了大门,即多租户能力。
各种上游服务不仅具有逻辑上独立的规则和策略。还提供物理隔离,允许在进程和接口级别进行精细管理。这种隔离在多租户环境中是一个很强的要求——不同的上游服务属于不同的租户,租户之间不应该相互影响,也不应该知道彼此的配置。
服务网格是这个时代的代表。服务网格由两个关键架构组件组成,一个数据平面和一个控制平面。与名称所暗示的相反,服务网格不是“服务网格”。它是一个代理网格,服务可以插入其中以完全抽象网络。典型的例子是istio+envoy、Linkerd + Linkerd 代理。
Pipy由本文的一位作者创建,是这个时代的产物,属于这一类。Pipy 是用于云、边缘和物联网的开源、轻量级、高性能、模块化、可编程网络代理。Pipy 非常适合各种用例,包括(但不限于)边缘路由器、负载均衡器和代理解决方案、API 网关、静态 HTTP 服务器、服务网格边车和其他应用程序。Pipy 正在积极开发并由全职提交者和贡献者维护,尽管仍是早期版本,但它已经过实战测试,并已被多个商业客户用于生产。
从上面的讨论可以清楚地看出,每个阶段都是对前一个阶段的改进。
代理软件需求及其演变
让我们再看看代理的演变,考虑他们的需求是如何演变的。
配置文件时代
第一代代理主要实现了用户与服务之间的网关功能,并提供了基本的可配置能力。海量数据的实时传输需要高吞吐量、低延迟和低资源占用。像所有软件一样,代理也需要支持模块化和可扩展性。
这个阶段的代理软件主要是用 C 语言开发的,就像在进程开始时动态加载的扩展模块一样。
总而言之,这个阶段的代理需求是连接性(网络能力)、易用性(可通过配置文件配置)、可靠性(对交叉链接设备的要求)、高性能和可扩展性。
配置DSL时代
第二代代理在可扩展性和灵活性方面得到了进一步的改进,例如一些动态数据采集和对采集数据执行一些逻辑决策的能力。基于 DSL 的脚本的引入进一步增强了可用性。对组合逻辑和动态数据检索的支持在提高可扩展性的同时提供了灵活性。
脚本语言时代
第 3 代代理相对于第 2 代代理的主要改进是可管理性、开发人员友好性和可编程性。
开发人员的生产力和维护大量脚本的复杂性要求这一代代理使用结构化的脚本语言,同时保持上一代的性能、低资源利用率和其他核心能力。
脚本功能被广泛使用,主要是因为很难使用 C 开发和维护扩展。确实,与编译语言相比,脚本语言更容易学习并提供更快的周转时间。
结构化和模块化脚本语言的使用迎来了可编程代理的时代,并要求代理提供两个级别的可编程性:使用 C 开发核心模块,以及使用脚本编写动态逻辑。换句话说,可编程代理为其用户提供了开发核心模块和动态逻辑的能力。
集群时代
第四代代理从集群支持开始,提高了可管理性。
借助 REST 接口,代理成为网络基础设施实现的一部分,也是基础设施即代码的起点。REST 接口除了提高代理的可管理性外,还有助于简化它们的管理。外部接口也是可编程代理的一个重要特性,而 REST 作为最常见的接口形式。
此时,可编程性包括三层:可编程核心模块、可编程动态逻辑和可编程外部接口。代理服务器集群的出现反映了可扩展性视角从功能扩展到资源扩展(用户可以将功能模块化到多个实例中,而不是编写单体脚本)的转变。REST 接口的出现为自助服务和托管服务提供了技术基础,例如用于配置和控制的控制面板。
云时代
第五代代理的演进是在云计算的普及和快速发展的推动下,带来了弹性、自助服务、多租户、隔离和计量的需求。
如果说第四代代理是针对系统管理员的,那么第五代代理就是针对云服务的。在完全保持前代代理软件特性的同时,第五代代理成为云就绪。
随着云计算向边缘的扩展,第五代代理需要支持异构硬件、异构软件和低能耗,以优化云与边缘的融合。
第五代代理也展示了可编程性的进步:从我们之前看到的核心模块、动态逻辑和外部接口到云能力、对分布、多租户和计量的支持。计量是多租户的衍生需求,一方面需要隔离,另一方面可以以尽可能小的粒度对资源进行计量。
让我们将上述讨论总结为表格格式,其中行对应于特定要求,列对应于不同阶段的代理。对于每个演化阶段,我们还在括号中提供了典型示例或已知软件。在每个单元格中,我们使用 * 表示这些功能是否可用以及可用程度(1-5,5 表示完全支持,1 * 表示基本支持)。
序列号 |
要求 |
配置(squid、httpd、nginx) |
配置语言(varnish、haproxy) |
脚本支持(nginx+Lua,nginx+js) |
集群(kong、envoy) |
云(istio + envoy、linkerd、pipy) |
评论 |
1. |
连接性 |
* * * * * |
* * * * * |
* * * * * |
* * * * * |
* * * * * |
云时代的连接始于 iptables 和 ebpf 等内核技术。以前,只有用户空间进程。 |
2. |
可靠性 |
* * * * * |
* * * * * |
* * * * * |
* * * * * |
* * * * * |
可靠性一直是代理服务器最基本的能力。 |
3. |
高性能 |
* * * |
* * * * |
* * * * * |
* * * * * |
* * * * * |
性能包括吞吐量、延迟、错误率和与平均值的偏差。常见的延迟指标是 P99、P999 等。早期的代理软件有长尾效应,所以P99以上的指标不如后来的软件。在返回相同内容时,具有高性能脚本的代理通常比其前辈表现更好。避免长尾的代理更稳定(与平均值的偏差更小),同时提供相同的性能。 |
4. |
灵活性 |
* |
* * |
* * * |
* * * * |
* * * * * |
与第四代相比,第五代代理显着增强了多协议支持能力,所以我们给这一代5星评价。而且,第五代的处理模型可以适应各种协议,比第四代提供更好的适用性。 |
5. |
可扩展性 |
* |
* * |
* * * |
* * * |
* * * * |
与灵活性类似,第 5 代代理支持多种协议,并为扩展核心功能或定制应用层(第 7 层)协议扩展开发提供了简单的扩展机制,因此我们给它比第 4 代多一星。 |
6. |
硬件兼容性 |
* * * * |
* * * * |
* * * * |
* * * * |
* * * * |
用 C 或 C++ 开发的代理通常具有更好的硬件兼容性和更活跃的社区,可以将应用程序迁移到新的硬件架构。为了硬件兼容性,使用 Rust、Go 和 Lua 开发的代理迁移速度相对较慢。 |
7. |
系统兼容性 |
* * * |
* * * |
* * * * |
* * * * |
* * * * * |
系统主要包括两个方面,一是操作系统,二是云平台。在操作系统兼容性方面,每一代代理都是相似的。但是,在云平台兼容性方面,第四代和第五代代理都提供了更好的云兼容性。相比之下,第五代和第四代的显着区别在于它们支持多租户的能力。 |
8. |
易于管理 |
* * |
* * |
* * |
* * * |
* * * * |
易于管理是系统操作和管理员角色的功能。第一代和第二代主要使用配置文件,在使用配置管理工具的基础上实现自动化和批量管理。在第三代中,除了管理配置文件,我们还需要进一步管理脚本文件。但从本质上讲,在易管理性上与第一代和第二代并没有太大区别。第四代提供REST接口,大大提高了管理的便利性。除了 REST,第五代代理通常提供基于云的控制平面来管理代理。它还提供多个外部接口,以满足其他管理需求,例如监控、审计和统计。 |
9. |
使用方便 |
* |
* |
* |
* * |
* * * |
前三代代理的主要用户是操作和系统管理员。到了第四代,管理员开始向用户提供一些功能,即服务模式开始出现。第五代考虑更多用户场景,提供更多租户能力。 |
10. |
易于开发 |
* |
* * |
* * * |
* * * * |
* * * * * |
围绕代理的开发包括两个方面。一是在代理内部,目的是实现功能;另一个是在proxy之外,目的是实现proxy的管理能力。前三代为内部开发提供了接口。最后两代提供内部和外部接口。第五代相比第四代带来的显着提升就是云接口。 |
11. |
核心接口可编程 |
* |
* |
* |
* |
* |
每一代代理都提供了扩展核心接口的能力,但是这些接口太低级,难以掌握。 |
12. |
功能扩展是可编程的 |
* |
* * |
* * * |
* * * * |
* * * * * |
提供更有效地扩展功能的能力是每一代代理都会变得更好的过程的一部分。它是可编程代理的核心指标。 |
13. |
协议扩展是可编程的 |
* * |
* * * |
前三代主要针对单一协议,或固定协议。从第四代开始,用户开始寻求对多协议和自定义协议的支持。在第五代中,协议扩展被认为是设计中的核心能力。 |
|||
14. |
模块化脚本 |
* * * |
* * * * |
* * * * |
第三代代理开始更加关注脚本结构。第四代和第五代尝试允许更结构化的编程,例如 Envoy 尝试通过 WASM 提供多语言支持;Pipy 引入高性能 JS 脚本以获得更好的结构 |
||
15. |
配置管理是可编程的 |
* * |
* * * |
前三代proxy配置对象主要是ops管理人员,外部配置管理工具都是基于这个前提。第四代支持 REST 管理接口。第五代还为配置管理提供了标准的云接口。 |
|||
16. |
资源扩展是可编程的 |
* |
* |
* |
* * |
* * * * |
前三代,proxy扩容主要是为了增加线程数或进程数。第四代为流程提供横向扩展能力,称为集群能力。在此基础上,第五代一方面提供横向扩展能力,另一方面提供资源受限能力,支持更细粒度的计量和计费。也就是说,它不仅支持增量扩展,还提供了缩减的能力。此外,所有这些功能都提供了编程接口。 |
17. |
租户扩展可编程 |
* * * |
云是与第四代代理同时出现的东西,而多租户作为云的核心特性,在第四代并没有得到很好的支持。第五代是在云计算的前提下设计的,考虑并为租户提供了编程自己的扩展的可能性。 |
上表中的第 11 到第 17 行是可编程代理的特定方面。这些方面也构成了为什么要使用可编程代理的问题的答案:
- 代理的内部功能可以扩展,包括底层核心能力、支持的协议、七层处理能力(转发、路由、判断、访问控制等)。Layer7 处理能力需要更便捷的编程方式,即脚本和结构化编程。
- 代理需要提供外部接口来集成到更大的管理系统(如云平台)中,包括配置管理、资源管理等。
- 代理需要为不同的角色提供可扩展的能力,包括操作、管理员、资源提供者和租户,所有这些都在一定程度上需要可编程性。
- 此外,与任何可编程组件一样,可编程代理需要随附的文档、开发手册、代码管理、依赖管理、构建和部署工具,并且最好是可视化开发和调试环境。只有完全满足这些要求,用户才能有效地管理网络流量和产生流量的服务。
概括
在本文中,我们试图回答什么是可编程代理。为此,我们从代理是什么及其关键特征的定义开始。然后我们扩展了我们的讨论,包括已经经历的进化代理,解释了在每个阶段添加的特性和功能。最后,我们通过将代理特征分成 17 个不同的类别并对每一代代理进行排名来总结我们对代理特征的讨论。这种分类使我们能够识别将代理标记为可编程所需的关键特征和属性。
解决企业获客难题,添加 微信:hvq698 备注:获客!
如若转载,请注明出处:https://www.yunxkee.com/9676.html