作者:董红帅,马蜂窝微服务体系建设以及根底服务能力建设专家。
马蜂窝作为旅行社交平台,是数据驱动的新型旅行电商。基于十余年的内容积攒,马蜂窝通过 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 的这套架构中,实际下来还是存在一些痛点。
首先是在公布零碎能力方面,微服务 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 属性以及扩大属性,实现了流量泳道能力。基于流量泳道模型,在下层产品侧构建迭代流量环境调用链路隔离。
在周边生态建设方面,Java SDK 侧做到了利用在迭代环境中能够实现隔离的链路调用,网关侧也进行了相似的操作。只是网关侧作为整个流量的入口,咱们是通过 Cookie 的规定,也就 Cookie 的形式进行配置的。基线环境的流量只能达到基线环境的版本中,迭代环境的流量就会转发到迭代的版本下来。
同时在部署层的 Kubernetes 多集群治理层面,咱们则借助 Karmada 实现了一个多 Kubernetes 集群的治理。在整个架构中(如下图所示),底层的能力次要是由 Kubernetes 多集群和流量网关 Envoy 与 APISIX、发现核心 Atlas、日志服务与监控服务等组成。
而蜂效平台在整个架构中次要是进行配置管理、构建部署、扩缩容和高低线等等,同时蕴含工作流的模块。最上方则是利用市场的一些能力,比方迭代能力和插件能力等。
整体来说,咱们基于利用核心和服务打造出了 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 还有以下几个劣势:
- 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 的数据反对。
借助这种架构,咱们就实现了对两种网关的残缺反对,如下图所示。
网关架构的外围局部则是图中最下方的 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 等;同时网关的动态化配置也是将来非常明显的趋势,对于运维或者根底研发的同学来说,在后续思考网关架构的选型和迭代时,也能够更多关注网关动静配置的方面。