简介:Envoy 是由 Lyft 开源的高性能网络代理软件。相比于 Nginx、HAProxy 等经典代理软件,Envoy 具备丰富的可观察性和灵活的可扩展性,并且引入了基于 xDS API 的动态配置方案。目前,Envoy 被广泛应用于新兴微服务网关与服务网格之中作为核心数据面。而本次分享将从网易数帆实践出发,介绍网易数帆是如何基于开源 Envoy 构建高性能、易扩展、可观察的云原生微服务网关 函谷 (Hango)的。

函谷开源地址:
github.com/hango-io/hango-gateway

1 云原生微服务网关

微服务网关是微服务架构中最为核心和关键的组件之一,负责微服务集群中服务 API 统一暴露和出入口流量管理。举一个具体的例子,在微服务集群中可能同时存在上百个微服务,其中有些是内部依赖,有些则需要对外暴露 API,为外部客户端提供服务。如果让各个微服务自身负责 API 的暴露,那一个微服务集群可能会同时有几十个流量出入口,大大提高流量安全和流量管理的成本,同时对客户端也非常不友好。所以引入一个集中组件来统一控制 API 暴露,并负责流量的均衡和分发就是一个自然而然的选择了(事实上,服务暴露还涉及一个网络隔离的问题,不过本文主要介绍的是七层 API 网关,网络问题暂且忽略)。

相比于传统的反向代理,微服务网关有了一个职能的增强。传统的反向代理更加注重基础的路由转发和负载均衡,而 API 网关除此以外,更多的还要关注流量的治理能力和流量的观察能力。

在构建函谷网关之前,集团内部实际上已经有了一些其他的 API 网关方案。比如网易传媒、严选使用的是 Kong,还有一些业务使用基于 Spring Gateway 的技术方案。但是这些 API 网关都有一些局限性,比如它们的容器化支撑能力,再比如它们的性能,又或者它们的治理能力。网易数帆最初的动机就是准备构建一个具备丰富能力、覆盖多种场景需求并兼具高性能的新 API 网关统一和替代网易集团内部的这些技术方案。

2 如何做好微服务网关?

在对微服务网关本身有了基础的了解之后。第二个问题就是,如何才能做好一个微服务网关呢?只有先明确目标,确立一个好的微服务网关需要解决的问题,才能为后续的技术选型、以及具体实践方向提供指导。在梳理了集团内已有的各种网关解决方案以及各个业务方的需求和场景之后,团队总结了一下六条微服务网关需要具备的关键特性(一家之言,仅作参考)。

  • 高性能:作为集群流量入口,性能是必须保证的。包括吞吐量和延迟,都是衡量一个高性能网关的关键要素。作为一个通用的解决方案,网易数帆的轻舟微服务网关设计之初,就希望尽可能覆盖未来更多的场景和业务方需求。所以性能自然要求越高越好,要满足对性能要求最苛刻的那一个业务方的需求。但是,如果各位希望自研微服务网关,那所谓高性能,不一定是吞吐量和延迟达到某个固定标准,只要满足业务方的实际需求就是高性能网关,没有必要过早优化。很多时候,网关的开销只有几 ms,而业务本身开销几十 ms,瓶颈不在网关。
  • 可观察:可观察性在微服务架构当中非常重要。因为业务不再是单体,为排障监控带来了新的复杂度,所以需要可观察性的支持。
    • 自证清白:实践得来的一个经验是,一旦集群内流量产生了一些业务层面的波动,作为入口的微服务网关几乎总是第一个被怀疑的对象。明确的可观察数据比如说日志、指标可以有说服力的证明网关的清白;
    • 辅助排障:日志指标也会包含业务的一些特征情况,可以帮助业务方快速定位出问题所在。
    • 观察趋势:最后,作为流量统一入口,网关的可观察性可以让用户了解到集群内的流量现状、趋势,并且形成长效的监控告警系统,提前发现问题。
  • 丰富的治理能力:目前稍好一点的小区大门一般都会加上人脸解锁、一杆一车之类的功能。API 网关也类似,作为入口的它也被要求做越来越多的与业务逻辑无关的额外治理功能,比如黑白名单、限流、熔断等等。
  • 可扩展性:和治理能力非常相关的一个关键特性就是可扩展性。业务方的需求是无穷无尽的,甚至会有一些非常定制化的需求,API 网关开发团队也难以覆盖所有需求,所以可扩展性就非常关键了。
    • 对网关开发团队:良好的可扩展性可以帮助 API 网关快速迭代新功能,降低扩展新的治理能力的成本和开销;
    • 对于业务方:降低网关开发的门槛,对于具有一定技术能力的团队,业务可以根据自身需求特点实现最合适的功能扩展,可以提高自身的自主能力;
  • 稳定性:网关稳定性的保证是一个很宏大的问题,除了软件的质量之外,更多的还要依赖流程的控制以及针对性的技术方案,比如灰度发布、金丝雀发布之类的。但是总体来说,就是要经历生产的检验,要有大规模的流量验证。
  • 可视化:一个友好、易用的可视化控制台,可以实现 API 网关的路由配置、服务管理、监控审计的可视化。
    • 简化操作:通过平台产品的封装,简化网关的操作流程和配置过程,隐藏或者减少底层技术的复杂性,降低 API 网关的使用门槛;
    • 实现约束:实现约束,通过产品的封装和合理的提示,降低在使用 API 网关的过程中,用户犯错的风险,让用户以一种更加正确的姿势使用网关;
    • 监控报警可视化;

3 为什么偏偏是 Envoy?

在函谷网关的基础数据面的技术选型当中,网易数帆选择了新兴开源网络代理 Envoy。Envoy 是由 Lyft 开源的一款高性能代理软件,后来被捐赠给了 CNCF 基金会,是 CNCF 基金会毕业的第三个项目。相比于 Nginx、HAProxy 等经典代理软件,Envoy 具备丰富的可观察性和灵活的可扩展性,并且引入了基于 API 的动态配置方案 xDS。此外,Envoy 还提供了大量的开箱即用的 Filter 以满足各种场景下流量治理的需求。

首先,选择 Envoy 可以使得网易数帆团队统一微服务架构中东西南北数据面技术栈。 Envoy 有典型的两种工作模式。一种作为中心代理,代理集群的南北向流量,也就是出入口流量,负责流量分发、流量治理之类的工作的。这种模式下,Envoy 一般就是负载均衡设备或者是 API 网关的基础数据面,比如 Ambassador,Gloo 都是新兴的开源的基于 Envoy 的开源网关。另一种模式,就是作为业务进程的 Sidecar。当有业务请求访问业务的时候,流量会被劫持到 Sidecar Envoy 当中,之后再被转发给业务进程。类似的,当业务需要访问其他业务的时候,请求流量也会先被拦截到 Sidecar Envoy,再被转发到目标服务。这样,就是在 Envoy Sidecar 中实现一些流量的治理和观察的功能。这个 Sidecar 的模式就设计到全新的一种微服务架构服务网格了。数帆轻舟团队和 Envoy 的结缘最初是在服务网格项目当中。在服务网格项目中,发现 Envoy 的丰富功能同样可以适用于网关场景,同时,业界也已经有了 Gloo 这样的开源网关在前。所以也就尝试使用 Istio 和 Envoy 去构建新的轻舟 API 网关。而这样做也可以保证技术栈的统一,使用 Envoy 来对微服务集群中南北-东西两向的流量进行全面的接管。

其次,Envoy 丰富的流量治理能力。 Envoy 本身就提供了比较丰富的流量治理能力,包括全局限流、本地限流、服务熔断、超时控制、策略重试、域管理等等。这些社区提供的七层治理能力让轻舟 API 网关一开始就有一个比较高的起点,可以节省大量的工作量。这些功能基本都是开箱即用,本身控制面的技术选型 Istio 也已经实现了对这些能力的封装。哪怕不做任何的扩展,只是简单的组合 Istio 和 Envoy 或者组合 Envoy 和裸的配置文件,也可以实现一个最简易的微型 API 网关了。

第三,Envoy 提供了开箱即用的可观察性。 社区 Envoy 本身提供了丰富的指标、灵活的日志、全面的分布式跟踪支持。

  • 日志:日志灵活的配置格式、扩展、实现自定义过滤规则等,而且支持多种的输出方案。
  • 指标:指标也非常的全面,即使现在,我也不敢说了解 Envoy 每一项指标的含义。而且 Envoy 的指标也可以在不侵入 Envoy 的前提下,进一步的扩展更多的监控指标;
  • 跟踪:最后是跟踪系统部分,Envoy 主要是做采集层的工作。支持 ZipKin、SkyWalking、OpenTracing 等多种的分布式跟踪系统对接。这些特性保证了使用 Envoy 来构建一套全面的监控告警排障系统是一件相对简单的事情。

第四,Envoy 强大的可扩展性。 Envoy 本身也提供了非常好的可扩展性,利用它的 L4/L7 的过滤器扩展机制,可以在各个层级实现 Envoy 功能的增强。实际上,Envoy 中大量的核心功能都是使用 Filter 来实现的,比如 HTTP 的七层治理能力,其实全都是一个叫做 HTTP Connection Manager 的七层扩展插件。针对其他的协议,一样可以使用类似的方式来扩展支持,比如数帆就额外做了对 FTP 还有 Kafka 的支持。

而且 Envoy 还提供了基于 Lua 和基于 WASM 两种不同的动态增强扩展方法,让用户可以在不需要重新构建 Envoy 的前提下,实现 Envoy 的功能增强和扩展。利用这种机制,作为一个 API 网关基础设施的提供方,可以简单的为业务方提供自定义扩展的能力。不过后面会讲到,目前两种方案还是有一些局限,所以数帆还提供了额外的增强。

第五,xDS/UPDA 提供的标准数据面代理抽象。 Envoy 代理软件还有一个重要的特性就是 xDS。xDS 的全称就是 x Discovery Service,是一种动态的配置分发方案。其中 x 表示某种资源,一个端口监听,一个 Upstream Host,一个 Upstream Cluster 都是一种资源,是真实微服务集群在 Envoy 中的抽象。Envoy 支持三种不同的 xDS 方案或者说载体:gRPC,文件,和 Restful API。其中 gRPC 是最常用的一种。就是 Envoy 和控制面之间建立起一个 gRPC 连接。控制组件通过 gRPC 将各种资源通过 ProtoBuf 序列化之后推送给 Envoy。Envoy 解析各项资源,然后动态生效。基于文件的 xDS 在做本地测试的时候,也比较常用。对于一些个人开发者,如果希望简单的使用 Envoy 构建一个高性能反向代理,基于文件的 xDS 方案也是不错的推荐。像是 LDS,Listener Discovery Service 用于动态的打开端口监听;CDS 用来发现新的可以通过 Envoy 代理的服务并抽象为名叫 Cluster 的资源。而 EDS 可以在 Cluster 本身不更新的前提下,更新它的示例列表。个人认为 xDS 最重要的就是两个特征。一是动态:所有的配置都是动态的发现、更新和生效的。而且这一过程,配置发现和配置更新的过程不需要 Envoy 主动参与。Envoy 通过将这些责任通过订阅的方式委托给了更合适的做这件事的控制面组件,比如说 Isito,或者 Gloo 里面的控制面。二是抽象:xDS 使用 proto 作为配置的载体,使用 proto 对象抽象和封装一组关联配置。也就是说,xDS 里面,动态发现的不是离散的配置项,是一个个资源,一个个对象。当通过 LDS 发现了一个新的 Listener,说明 Envoy 就该开启一个新的端口监听了。而 Listener 里面的具体配置项,都只是在描述这个接下来要创建的端口监听。

最后一个影响团队决策的就是 Envoy 开源社区。 利用 Envoy 的开源社区和生态,数帆轻舟可以更好的从社区借力。 Envoy 是第三个 CNCF 毕业项目 ,相比于 Nginx 社区,Envoy 的社区明显更加开放,可以让人更加放心的贡献和参与。

4 网易数帆实践与开源

最后一部分是网易数帆的具体实践,还有开源相关的工作。数帆微服务的整体架构如图所示。这个图,我几次分享都用到它。简单,清晰明了,而且没有复杂的技术细节。

在最下层,Envoy 作为微服务网关、微服务网格的基础数据面统一了南北东西向的流量治理。再往上,是 Istio 作为的网关和网格的控制面。Istio 之上是统一的 API Plane 作为 API 暴露层。最上层,就是可视化的控制台。同时,APM,Prometheus,ES 等可观察性相关的支撑系统一起来构建一整套可观察体系具体来说,网易数帆做了一下几个方面的工作。

一,更丰富的七层治理能力。 网易数帆实现了更加丰富的七层治理能力,包括流量安全相关的:IP 黑白名单,轻舟认证鉴权,流量稳定性相关的:本地限流、路由级熔断、动静态降级,性能相关的缓存,跨协议访问相关的 Dubbo 协议转换、Web Service 协议转换等等,来覆盖更多的业务方需求和场景。

二,基于 Lua 的动态可扩展性进一步提升。 虽然社区已经提供了基于 Lua 和 WASM 的扩展方案,但是还是略有不足之处。其中 WASM 的方案目前算不上成熟,而且性能不如预期,同时相对来说扩展的开发、编译、分发还是较重;而 Lua 虽然做到了极致的灵活,但是只是简单的 Lua 脚本执行,甚至没有做到扩展逻辑和扩展配置相分离,所以有两个方面的缺陷:不易迁移、难以实现较为复杂的功能。为此,网易数帆设计并实现了一个类似于 OpenResty 的 Lua 扩展框架 Rider,弥补了现有 Lua 扩展的不足。Rider 框架主要包含三个部分:Envoy C++ Filter 部分,Lua SDK 部分,Lua Filter 部分。

三,可观察性增强。 网易数帆另一个非常重要的工作是对 Envoy 的可观察进行增强,包括:一些元数据的注入,来增强审计日志;Skywalking Tracer 的实现,来对接分布式跟踪系统。

四,控制台与监控审计可视化。 网易数帆实现了一个友好的控制台,来实现服务管理、路由配置、监控审计等一系列功能的可视化,提高 API 网关的易用性。主要的功能包括两点,前面也提到过:一是简化网关操作,实现功能的约束;二是聚合监控数据,了解集群的状态。

五,拥抱开源。 整个函谷网关都是构建在开源 Envoy 和开源 Istio 的基础之上的,在使用开源软件的过程中,我们也在尝试对社区做回馈。目前,轻舟团队已经向 Envoy 社区贡献了超过 10000 行的新增代码。

此外,网易数帆也尝试创建自己的开源社区。所以先后开源了 Slime(智能服务网格) 以及函谷网关。在开源方面,我们还是一个新手,所以可能还有很多不足之处。但是我们绝对是认真的。所以希望大家多多尝试,提出 issue。

原文链接:
https://mp.weixin.qq.com/s?__biz=MzU4MDM1MDAwOQ==&mid=2247485497&idx=1&sn=43b0e52cd08c335a33d70c12ed542d1b&utm_source=tuicool&utm_medium=referral

如果觉得本文对你有帮助,可以关注一下我公众号,扫描下方二维码关注“w的编程日记”获取更多Java资料