Skip to main content

马蜂窝如何利用 APISIX 网关实现微服务架构升级

· 阅读需约 21 分钟
董红帅

本文从马蜂窝的微服务架构平台蜂效迭代过程和应用 APISIX 后的产品实践角度,为大家呈现了基于 APISIX 的网关应用实例。

作者:董红帅,马蜂窝微服务体系建设以及基础服务能力建设专家。

马蜂窝作为旅行社交平台,是数据驱动的新型旅行电商。基于十余年的内容积累,马蜂窝通过 AI 技术与大数据算法,将个性化旅行信息与来自全球各地的旅游产品供应商实现连接,为用户提供与众不同的旅行体验。

随着业务的发展,马蜂窝架构也在跟随技术步伐进行更迭,开始基于 Kubernetes 进行更多的延展。在这个技术背景下,需要针对云服务开启新一轮的架构更新,比如:微服务场景建设新的蜂效平台及周边设施来支持迭代和流量泳道的能力,在多 Kubernetes 集群场景引入 Karmada 实现多集群管理,在微服务网关领域将 Istio + Envoy 的架构替换为 Apache APISIX 与 Envoy 共存的微服务网关模式。

微服务 1.0 模式现状

目前马蜂窝内部的微服务架构经历了两次迭代,本文中将针对原有架构的第一次调整定义为 1.0 版本。在进行微服务 1.0 架构的搭建之前,我们从发布系统能力、Kubernetes 容器、服务发现和微服务网关等角度进行了一些考量与目标对齐。比如 Kubernetes 的广泛应用,需要开始考虑基于容器做多语言支持,在 CI/CD 环节实现全面容器化,并支持多 Kubernetes 集群等。

在进行第一次迭代之前,内部架构的微服务网关使用的是 NGINX Ingress,但它其实是存在问题的。比如配置变更基于 NGINX reload,会造成业务有损;同时在应用范围内仅支持单 Kubernetes 集群,场景受限;内置资源过于简单,大量匹配规则依赖 Annotations,配置繁杂不友好,尤其是对外部服务发现能力支持很弱。

因此在进行微服务 1.0 迭代落地的过程中,为了满足一些业务需求,我们进行了如下动作(选取部分操作列举):

  • 在 Kubernetes 容器内,基于 macvlan 改造容器网络,IDC 机房网络与云厂商网络互通(容器互通的通信基础);借助网关或容器直连实现服务互访,不再使用 Kubernetes Service。
  • 基于 Kubernetes 容器场景部署;基于 Consul 物理机虚拟机部署。
  • 增加统一服务发现能力,基于 Kubernetes、Consul 建设统一的发现中心 — Atlas;同时基于 Atlas 扩展微服务网关、Java 生态、监控体系等。
  • 在微服务网关的选择上,基于 Istio + Envoy 架构进行构建。对 Istio 中 Pilot 进行二次开发,对接 Atlas 发现中心,由于 Atlas 数据来源于多套 Kubernetes 和 Consul,进而将实例发现与 Kubernetes 集群解耦,间接做到网关对接多 Kubernetes 集群的能力,实现整个网关动态感知识别的变化。

蜂效 1.0 微服务网关架构
Click to Preview

痛点梳理

在微服务 1.0 的这套架构中,实践下来还是存在一些痛点。

首先是在发布系统能力方面,微服务 1.0 中的发布系统,仅仅是一个发布系统,无法有效融合项目需求的管理(发布也是度量的一环);同时这套发布系统基于 PHP 构建,无法很好地支持自动化滚动部署、多版本滚动部署容量变更等较为复杂的部署场景;当多人对同一个项目开发,或一个需求关联多个项目时,缺少机制让流量在同一个迭代中自动串联(流量泳道)。同时对多 Kubernetes 集群管理并不方便,当 Kubernetes 下线时需要业务侧参与,给业务线带来了时间成本等。

其次就是微服务网关架构层面。前文也提到了 1.0 架构下网关是基于 Istio+Envoy 对 Pilot 做了二次开发,主要是对接 Atlas 发现中心。随着业务的应用数量越来越多,访问规则也越来越多,这就导致我们线上的网关生效延迟也越来越高。在流量巅峰状态下,大概有 15 秒左右的延迟。这个延迟主要来自于 CRD 资源,几乎全都在相同的 namespace 下,同时上下线时会触发全量更新导致延迟较高。

而在早期的使用过程中,Envoy 在数据全量推送过程中还会出现链接中断的状况,造成 503 问题的产生。除此之外,Envoy 还存在使用内存持续增长导致 OOM 的情况,当网关出现问题时,对 Envoy 和 Pilot 进行排错的成本较高。当使用一些高阶配置时,需要借助 Envoy Filter 实现,其上手门槛较高,对于想简单实现熔断、限流、Auth 鉴权等功能而言,成本较高。

除此之外,两个社区(Istio 和 Envoy)的发展速度很快,这也导致我们的架构比较难跟进上游社区的发展。

基于 APISIX 的微服务 2.0 模式

新平台与新架构

面对 1.0 架构下存在的痛点与问题,内部对于这套微服务架构进行了再次迭代,来到了 2.0 时代。2.0 架构场景下,我们新增了一套发布平台——蜂效平台。

蜂效平台重点突出了以下能力:

  • 融合了需求管理,支持了迭代部署能力,使得发布系统可以增益度量。
  • 将容器部署和机器部署(物理机部署)在产品能力上进行了统一。
  • 增强了精细化的流量管理能力、回滚能力(回滚策略:批次、实例数、间隔等)
  • 与 Java 生态融合共建,支持了流量泳道能力,环境流量隔离。
  • 网关基于 APISIX 进行重构,解决 Envoy OOM 及规则生效延迟较高的同时,通过 APISIX 产品化能力降低了问题排错成本,降低了扩展和配置网关的上手门槛。

在蜂效平台产品侧中,我们将需求管理与迭代部署关联结合,并且为了支持了多种迭代流水线模式。在流量管理方面,我们借助 Atlas Instance 模型中的 env 属性以及扩展属性,实现了流量泳道能力。基于流量泳道模型,在上层产品侧构建迭代流量环境调用链路隔离。

规划蜂效 2.0
Click to Preview

在周边生态建设方面,Java SDK 侧做到了应用在迭代环境中可以实现隔离的链路调用,网关侧也进行了类似的操作。只是网关侧作为整个流量的入口,我们是通过 Cookie 的规则,也就 Cookie 的方式进行配置的。基线环境的流量只能到达基线环境的版本中,迭代环境的流量就会转发到迭代的版本上去。

v1 与 v2 版本的流量分配
Click to Preview

同时在部署层的 Kubernetes 多集群管理层面,我们则借助 Karmada 实现了一个多 Kubernetes 集群的管理。在整个架构中(如下图所示),底层的能力主要是由 Kubernetes 多集群和流量网关 Envoy 与 APISIX、发现中心 Atlas、日志服务与监控服务等组成。

而蜂效平台在整个架构中主要是进行配置管理、构建部署、扩缩容和上下线等等,同时包含任务流的模块。最上方则是应用市场的一些能力,比如迭代能力和插件能力等。

蜂效平台 2.0 架构图
Click to Preview

整体来说,我们基于应用中心和服务打造出了 2.0 新架构。这套新架构在 Kubernetes 集群发生变更时,可通过 PropagationPolicy、OveridePolicy 等策略,实现 Deployment 等在 Kubernetes 集群级别的资源分发,减少集群变更时业务参与的成本,减轻了业务研发侧的一些压力。

网关选型

在 2.0 模式的架构中,流量网关我们提到了两个网关产品,即 Envoy 与 APISIX。Envoy 作为之前 1.0 版本的选择,我们并没有完全放弃,在 2.0 中我们也因为一些需求和产品期望,开始考虑新的网关产品进行替代,比如:

  • 访问规则变化时,网关的生效速度需要控制在毫秒级(生效慢,会导致网关生效速度不一,在使用了 CDN 场景下可能导致业务资源长时间 404)。
  • 可在现有场景中,完全替换 Istio+Envoy 架构;同时支持 HTTP、gRPC,并兼容现有路由策略。
  • 需要降低问题的排查成本,最好有产品化支持(如 Dashboard)。
  • 产品足够稳定,社区活跃,功能强(对限流等场景支持)。
  • 不需要二次开发即可支持公司现有架构的替换。
  • 在替换 Istio+Envoy 架构过程中,需要保持双架构可用(Istio、Envoy 与新网关并存),如果新架构有问题可快速回退至原来方案。

在调研了一些关键网关产品的模型之后,我们最终将方案锁定在了 Apache APISIX。APISIX 的架构也分为控制面和数据面,同时还附带 Dashboard 产品。在功能使用上,APISIX 提供了丰富的插件,比如限流、熔断、日志安全和监控等等。我们可以通过 APISIX 的 Admin API 提供的接口,去完整操作 APISIX 的所有能力,比如 Upstream、Consumer 还有各种插件等。对我们而言,APISIX 还有一个特别有优势的点,就是 APISIX 在升级时,能够做到对低版本的 API 进行统一的兼容。

APISIX 架构
Click to Preview

除此之外,我们认为 APISIX 还有以下几个优势:

  • APISIX 基于 Openresty 的性能很好,相比 Envoy 来说,性能损耗很少。在经过我们测试之后,在 QPS 的表现上,APISIX 损耗 3%,而 Envoy 损耗 16%;在时延表现上,APISIX 平均转发耗时 2ms,而 Envoy 耗时 7ms。数据的体现,已经展示了 APISIX 在性能上的卓越优势。
  • APISIX 还附有 Dashboard 支持,对于路由匹配异常等场景可快速判断是否为规则配置错误。
  • 作为开源产品,APISIX 的社区更为活跃。在产品的功能上,在限流、鉴权、监控等方面相比 Envoy 成本更低,支持性更好。
  • APISIX 相比 Envoy 内存占用很低,但在配置的动态变更上相比 Envoy 要弱(Envoy 几乎大部分配置可动态下发),但也足够满足需求。

因此,在调研与测试之后,我们在微服务 2.0 的架构下增添了 Apache APISIX 作为流量网关加入。由于网关是整个微服务流量的核心,如果从一套旧架构切换到一套新的架构,其实成本是比较高的。所以我们希望微服务的网关规则变化能够对新旧两套网关(Envoy 与 APISIX)同时生效,也就是一套配置可以适用于两种架构,因此我们在 2.0 架构中,针对这些变动做了一些调整。

落地方案与实践问题

首先考虑到成本问题,对原本的 Istio 架构保持不变,并未进行改造。同时在网关架构中,引入了新开发的关键组件—— istio-apisix-translator

istio-apisix-translator 主要是去对接 Atlas 发现中心以及 Istio 的 CRD 数据。作为数据同步服务,实时将 VirtualService、DestinationRule 等规则变化转换为 APISIX 路由规则,将 Atlas Instance 数据实时转换为 APISIX Upstream 规则等。简单来说,就是通过这样一个服务组件,实现了对 Atlas 以及 Istio CRD 的数据支持。

借助这种架构,我们就实现了对两种网关的完整支持,如下图所示。

蜂效 2.0 微服务网关架构
Click to Preview

网关架构的核心部分则是图中最下方的 APISIX,上层的 istio-apisix-translator 则充当类似 Istio 架构中的 Pilot 角色,将 Instance 与 CR 数据整合后,借由 APISIX Admin API 推送至 APISIX 中,实例则是对接到内部业务的 Atlas 发现中心。因此,无论是访问规则发生变化还是 Atlas 的数据源发生变化,都可以将这份数据变化转换成 APISIX 的数据推到 APISIX 中。目前全链路都是基于 Watch 机制保证数据变化的实时处理,因此在实际应用场景下,基本可以达到数据变化的毫秒级生效。

当然,在使用 APISIX 的过程中,我们也遇到了几处问题。但均已解决并将结果同步给了社区进行反馈。

第一个问题就是在 APISIX 使用证书对接 etcd 时,如果 APISIX 节点较多,可能会导致 APISIX Admin API 接口响应非常慢。这个问题的原因是因为目前 etcd 存在一个关于 HTTP/2 的 BUG。如果通过 HTTPS 操作 etcd(HTTP 不受影响),HTTP/2 的连接数上限为 Golang 默认的 250 个。而 APISIX 的控制面和 Istio 架构的控制面有区别,APISIX 节点是直连 etcd,当 APISIX 数据面节点数较多时,一旦所有 APISIX 节点与 etcd 连接数超过这个上限,则 APISIX 的接口响应会非常的慢。

为了解决这个问题,我们也在 etcd 和 APISIX 的社区均进行了反馈,后续也通过升级版本(etcd 3.4 升级到 3.4.20 及以上,etcd 3.5 升级到 3.5.5 及以上)解决了这个问题。同时我们也已将这个结果同步到了 APISIX 社区官网 Q&A 文档中,方便后续用户遇到同样问题时,可以有所参考。

第二个问题就是在使用 APISIX 的过程中会遇到性能抖动的问题。

首先是会出现 499 响应抖动,这个问题主要出现在连续两次以上过快的 post 请求(也不止 post)的场景下。这种情况是 NGINX 认定为不安全的连接,则主动断开了客户端的连接。为了处理这个问题,只需将 proxy_ignore_client_abort 的配置调整为 on 即可。

除此之外,当 APISIX Admin API 接口请求密集时,也会出现 APISIX 数据面少部分响应超时的状况。这个主要是因为 istio-apisix-translator 在重启时,会将 Atlas、Istio CR 数据聚合,全量同步至 APISIX 中,大量请求引发 APISIX 数据变更,APISIX 数据面密集的同步变更导致小部分响应超时。为此,我们引入协程池和令牌桶限流,减少 APISIX 数据密集变更的场景来应对此问题。

总结与发展

马蜂窝当前是基于 Kubernetes 容器部署以及基于 Consul 的机器部署场景,自建 Atlas 服务发现中心,同时,在 Java 生态、微服务网关,微服务体系的流量泳道,以及监控体系做对接和适配。

在微服务网关前期,是基于 Istio 1.5.10 对 Pilot 二次开发,也在网关侧支持非容器部署场景。目前阶段则是保持了 Istio+Envoy 架构与 APISIX 架构同时支持,通过引入外部服务组件,让 APISIX 也复用 Istio CRD 资源。

从网关发展视角来看,未来我们也会跟随网关的一些趋势。比如现在很多产品都开始支持 Gateway API,像 APISIX Ingress、Traefik、Contour 等;同时网关的动态化配置也是未来非常明显的趋势,对于运维或者基础研发的同学来说,在后续考虑网关架构的选型和迭代时,也可以更多关注网关动态配置的方面。