Open bingoohuang opened 5 years ago
在Service Mesh微服务架构中,我们常常会听到东西流量和南北流量两个术语。 南北流量(NORTH-SOUTH traffic)和东西流量(EAST-WEST traffic)是数据中心环境中的网络流量模式。
假设我们尝试通过浏览器访问某些Web应用。Web应用部署在位于某个数据中心的应用服务器中。在多层体系结构中,典型的数据中心不仅包含应用服务器,还包含其他服务器,如负载均衡器、数据库等,以及路由器和交换机等网络组件。假设应用服务器是负载均衡器的前端。
当我们访问web应用时,会发生以下类型的网络流量:
在这个例子中,前者即即客户端和服务器之间的流量被称为南北流量。简而言之,南北流量是server-client流量。
第二种流量即不同服务器之间的流量与数据中心或不同数据中心之间的网络流被称为东西流量。简而言之,东西流量是server-server流量。
当下,东西流量远超南北流量,尤其是在当今的大数据生态系统中,比如Hadoop生态系统(大量server驻留在数据中心中,用map reduce处理),server-server流量远大于server-client流量。
大家可能会好奇,东西南北,为什么这么命名。
该命名来自于绘制典型network diagrams的习惯。在图表中,通常核心网络组件绘制在顶部(NORTH),客户端绘制在底部(SOUTH),而数据中心内的不同服务器水平(EAST-WEST)绘制。
https://www.servicemesher.com/blog/service-mesh-and-api-gateway/
关于Service Mesh和API Gateway之间的关系,这个问题过去两年间经常被问起,社区也有不少文章和资料给出解答。其中不乏 Christian Posta 这样的网红给出过深度介绍。我在这里做一个资料的整理和汇总,结合个人的理解给出一些看法。另外在本文最后,介绍蚂蚁金服在Service Mesh和API Gateway融合的这个最新领域的一些开创性的实践和探索,希望给大家一个更有体感的认知。
备注1:为了节约篇幅,我们将直奔主题,假定读者对Service Mesh和API Gateway已有基本的了解。
备注2: 这边文章更关注于梳理整个脉络,内容不会展开的特别细,尤其是其他文章已经详细阐述的部分。如果您在浏览本文之后,还想更深入的了解细节,请继续阅读文章最后的参考资料和推荐阅读。
首先,Service Mesh和API Gateway在功能定位和承担的职责上有非常清晰的界限:
如上图所示:
从功能和职责上说:
从部署上说:
在这里引入两个使用非常广泛的术语:
解释一下“东西南北”的由来:如上图所示,通常在地图上习惯性的遵循“上北下南,左西右东”的原则。
总结:Service Mesh和API Gateway在功能和职责上分工明确,界限清晰。但如果事情就这么结束,也就不会出现Service Mesh和API Gateway关系的讨论了,自然也不会有本文。
问题的根源在哪里?
强烈推荐阅读:附录中 Christian Posta 的文章 “Do I Need an API Gateway if I Use a Service Mesh?“对此有深度分析和讲解。
如下图所示,图中黄色的线条表示的是API Gateway访问内部服务:
问题来了,从流量走向看:这是外部流量进入系统后,开始访问对外暴露的服务,应该属于“南北向”通讯,典型如上图的画法。但从另外一个角度,如果我们将 API Gateway 逻辑上拆分为两个部分,先忽略对外暴露的部分,单独只看 API Gateway 访问内部服务的部分,这时可以视 API Gateway 为一个普通的客户端服务,它和内部服务的通讯更像是“东西向”通讯:
所以,API Gateway 作为一个客户端访问内部服务时,到底算南北向还是东西向,就成为一个哲学问题:完全取决于我们如何看待 API Gateway ,是作为一个整体,还是逻辑上分拆为对内对外两个部分。
这个哲学问题并非无厘头,在 API Gateway 的各种产品中,关于如何实现 “API Gateway 作为一个客户端访问内部服务” ,就通常分成两个流派:
而最终决策通常也和产品的定位有关:如果希望维持 API Gateway 的独立产品定位,希望可以在不同的服务间通讯方案下都可以使用,则通常选择前者,典型如kong;如果和服务间通讯方案有非常深的渊源,则通常选择后者,典型如springcloud生态下的zuul和springcloud gateway。
但无论选择哪个流派,都改变不了一个事实,当 “API Gateway 作为一个客户端访问内部服务” 时,它的确和一个普通内部服务作为客户端去访问其他服务没有本质差异:服务发现,负载均衡,流量路由,熔断,限流,服务降级,故障注入,日志,监控,链路追踪,访问控制,加密,身份认证…… 当我们把网关访问内部服务的功能一一列出来时,发现几乎所有的这些功能都是和服务间调用重复。
这也就造成了一个普遍现象:如果已有一个成熟的服务间通讯框架,再去考虑实现API Gateway,重用这些重复的能力就成为自然而然的选择。典型如前面提到的 springcloud 生态下的 zuul 以及后面开发的 springcloud gateway,就是以重用类库的方式实现了这些能力的重用。
这里又是一个类似的哲学问题:当 “API Gateway 作为一个客户端访问内部服务” 时,它以重用类库的方式实现了代码级别的能力重用,相当于自行实现了一个和普通服务间通讯方案完全一样的客户端,那这个“客户端”发出来的流量算东西向还是南北向?
答案不重要。
在进入Service Mesh时代之后,Service Mesh和API gateway 的关系开始是这样:
此时两者的关系很清晰,而且由于当时Service Mesh和API Gateway是不同的产品,两者的重合点只是在功能上。
而随着时间的推移,当 Service Mesh 产品和 API Gateway 产品开始出现相互渗透时,两者的关系就开始变得暧昧。
在Service Mesh出现之后,如何为基于Service Mesh的服务选择合适的API Gateway方案,就慢慢开始提上日程,而其中选择重用Service Mesh的能力也自然成为一个探索的方向,并逐步出现新式API Gateway产品,其想法很直接:
其中的一个做法就是基于Service Mesh的Sidecar来实现API Gateway,从而在南北向通讯中引入Service Mesh这种东西向通讯的方案。这里我们不展开细节,我这里援引一个图片(鸣谢赵化冰同学)来解释这个方案的思路:
这个时候Service Mesh和API Gateway的关系就变得有意思了,因为Service Mesh中sidecar的引入,所以前面的“哲学问题”又有了一个新的解法:API Gateway这次真的可以分拆为两个独立部署的物理实体,而不是逻辑上的两个部分:
在这个方案中,原来用于Service Mesh的sidecar,被用在了API Gateway中,替代了API Gateway中原有的客户端访问的各种功能。这个方案让API Gateway的实现简化了很多,也实现了东西向和南北向通讯能力的重用和融合,而 API Gateway可以更专注于 “API Management” 的核心功能。
此时 Service Mesh 和 API Gateway 的关系就从“泾渭分明”变成了“兼容并济”。
而采用这个方案的公司,通常都是先有Service Mesh产品,再基于Service Mesh产品规划(或者重新规划)API Gateway方案,典型如蚂蚁金服的SOFA Gateway产品是基于MOSN,而社区开源产品Ambassador和Gloo都是基于Envoy。
上述方案的优势在于API Gateway和Sidecar独立部署,职责明确,架构清晰。但是,和Service Mesh使用sidecar被质疑多一跳会造成性能开销影响效率一样,API Gateway使用Sidecar也被同样的质疑:多了一跳……
解决“多一跳”问题的方法简单而粗暴,基于sidecar,将API Gateway的功能加进来。这样API Gateway本体和Sidecar再次合二为一:
至于走到这一步之后,Service Mesh和API Gateway是什么关系:这到底算是Service Mesh/sidecar融合了API Gateway,还是API Gateway融合了Service Mesh/Sidecar?这个问题就像斑马到底是白底黑纹还是黑底白纹一样,见仁见智。
BFF(Backend For Frontend)的引入会让Service Mesh和API Gateway走到一个更加亲密的地步。
先来看看常规的BFF的玩法:
在这里,多增加了一个 BFF 层,介于API Gateway和内部服务(包括组合服务和原子微服务)之间。注意BFF的工作模式和组合服务很类似,都是组合多个服务。但差别在于:
“BFF完全收口外部流量”,这一点在API Gateway和Sidecar融合之后,会变得很有想象空间,我们先看按照前面的融合方式,在有BFF的情况下,API Gateway和Sidecar融合后的情景:
放大一点,单独看API Gateway和BFF:
注意到,流量从被API Gateway接收,到进入BFF在这个流程中,这个请求路径中有两个sidecar:
所以,问题来了:为什么要放两个sidecar在流程中,缩减到一个会怎么样?我们尝试将两个Sidecar合二为一,去掉BFF自带的Sidecar,直接把扮演API Gateway的sidecar给BFF用:
此时的场景是这样:
注意这里有一个关键点,在前面时特意注明的:“BFF完全收口外部流量”。这是前提条件,因为原有的API Gateway集群已经不再存在,如果BFF没能收口全部流量,则这些未能收口的流量会找不到API Gateway。当然,如果愿意稍微麻烦一点,在部署时清晰的划定需要暴露给外界的服务,直接在这些服务上部署带API Gateway功能的Sidecar,也是可行的,只是管理上会比BFF模式要复杂一些。
另外,在部署上,按照上面的方案,我们会发现:API Gateway“消失”了 —— 不再有一个明确物理部署的API Gateway的集群,常规的中心化的网关在这个方案中被融合到每一个BFF的实例中,从而实现另外一个重要特性:去中心化。
上述Service Mesh 和 API Gateway融合的方案,并未停留在纸面上。
在蚂蚁金服内部,我们基于Service Mesh 和 API Gateway融合 + 去中心化的思路,进行过开创性的实践和探索。以支付宝移动网关为例,在过去十年间,网关经历了从单体到微服务,从中心化到去中心化,从共享的 gateway.jar 包到利用MOSN实现网关Mesh化/Sidecar化,最终演变成了这样一个方案:
强烈推荐阅读:附录中我的同事 贾岛 的文章 “蚂蚁金服 API Gateway Mesh 思考与实践” 对此有深入介绍和详细描述。
本文总结了 Service Mesh 和 API Gateway 的关系,整体上说两者的定位和职责“泾渭分明”,但在具体实现上,开始出现融合的趋势:早期传统方式是类库级别的代码复用,最新趋势是API Gateway和Sidecar 合二为一。
后者的发展才刚刚起步,包括在蚂蚁金服我们也是才开始探索这个方向,但是相信在未来一两年间,社区可能会有更多的类似产品形态出现。
补充介绍一下文中多次提到的“MOSN”:
MOSN 是 MOSN 是 Modular Open Smart Network 的简称, 是一款使用 Go 语言开发的网络代理软件,由蚂蚁金服开源并经过几十万容器的生产级验证。 MOSN 作为云原生的网络数据平面,旨在为服务提供多协议、模块化、智能化、安全的代理能力。 MOSN 可以与任何支持 xDS API 的 Service Mesh 集成,亦可以作为独立的四、七层负载均衡,API Gateway、云原生 Ingress 等使用。
意犹未尽的同学,欢迎继续阅读以下内容。
按文章发表的时间排序:
缘起
F5 收购 NGINX,闹得沸沸扬扬的,有人说是一个时代的落幕,毕竟由于技术的“降维攻击”,NGINX 的市场占有率迅速增长:
正如F5 收购 NGINX,一个时代的落幕中所说,随着微服务和 k8s 的技术变革,传统的南北向流量逐渐被弱化,东西向流量的处理变得越来越重要。一批云原生的 反向代理/负载均衡/API网关 开源项目如雨后春笋般冒了出来,蚕食着 NGINX 的市场:
动态,已经成为新一代 web server 的标准配置。诞生于 2007 年的 OpenResty,以 NGINX 强大高效的网络库为基础,天生就以 LuaJIT 的动态为主打,营造了自己的生态;以 OpenResty 为基础的 KONG,更是扛起了新一代 API 网关和 Service Mesh 的大旗。NGINX 的重要性依然存在,但在被逐步下沉,远离业务。
问题