3

高德Serverless平台建设及实践

 2 years ago
source link: https://my.oschina.net/amaptech/blog/5061673
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
高德Serverless平台建设及实践 - 高德技术的空间 - OSCHINA - 中文开源技术交流社区

导读

高德启动Serverless建设已经有段时间了,目前高德Serverless业务的峰值早已超过十万QPS量级,平台从0到1,QPS从零到超过十万,成为阿里集团内Serverless应用落地规模最大的BU。这个过程如何实现,遇到过哪些问题?本文将和大家分享高德为何要搞Serverless/Faas,如何做,技术方案是什么?目前进展以及后续计划有哪些,希望对感兴趣的同学有所帮助。

1. 高德为什么要搞Serverless

背景原因是高德当年启动了一个客户端上云项目,项目主要目的是为了提升客户端的开发迭代效率。以前客户端业务逻辑都在端上,产品需求的变更需要走客户端发版才能发布,而客户端发版需要走各种测试流程,灰度流程,解客户端崩溃等问题。

客户端上云之后,某些易变的业务逻辑放到云上来。新的产品需求通过在云端来开发,不用走月度的版本发布,加快了需求的开发迭代效率,离产研同频的理想目标又近了一步(为什么要说“又”,是因为高德之前也做了一些优化往产研同频的方向努力,但是我们希望云端一体化开发能是其中最有效的一个技术助力)。

1.1 目标:客户端开发模式——端云一体

虽然开发模式从以前的端开发转变为现在的云 + 端开发,开发同学应该还是原来负责相应业务的同学,而大家知道,服务端开发和客户端开发显然是有差异的,客户端开发往往是面向单机模式的开发,服务端开发通常是集群模式,需要考虑分布式系统的协调、负载均衡,故障转移降级等各种复杂问题。

如果使用传统的服务端模式来开发,这个过渡风险就会比较大。Faas很好的解决了这一问题。我们结合高德客户端现有的xbus框架(一套客户端上的本地服务注册、调用的框架),扩展了xbus-cloud组件,使得云上的开发就像端上开发一样,目标是一套代码,两地运行,一套业务代码既能在客户端上运行,也能在服务端上运行。

高德客户端主要有三个端:iOS、Android、车机(类Linux操作系统)。主要有两种语言,C++和Node.js。传统地图功能:如地图显示,导航路径显示,导航播报等等,由于需要跨三个端,采用C++语言来开发。地图导航基础之上的一些地图应用功能,如行前、行后卡片,推荐目的地等主要是用Node.js来开发的。

在阿里集团,淘系前端团队开发了Node.js Faas Runtime。高德客户端上云项目,Node.js的部分就采用了现有的淘系的Node.js Runtime,来接入集团的Faas平台,完成Node.js这部分的一些业务上云。2020年十一很好的支撑了高德的十一出行节业务。

C++ Faas没有现有的解决方案,因此我们决定在集团的基础设施之上做加法,新建C++ Faas基础平台,来助力高德客户端上云。

1.1.1 端云一体的最佳实践关键:客户端和Faas之间的接口抽象

原本客户端的逻辑移到Faas服务端上来,或者新的需求一部分在Faas服务端上开发,这里的**成败关键点在于:客户端和Faas的接口协议定义,也就是Faas的API定义。**好的API定义除了对系统的可维护性有好处以外,对后续支撑业务的迭代开发也很重要。

理想情况下:客户端做成一个解析Faas返回结果数据的一个浏览器。浏览器协议一旦定义好,就不会经常变换,你看IE,Chrome就很少更新。

当然我们的这个浏览器会复杂一些,我们这个浏览器是地图浏览器。如何检验客户端和Faas之间的接口定义好不好,可以看后续的产品需求迭代,如果有些产品需求迭代只需要在Faas上完成,不需要客户端的任何修改,那么这个接口抽象就是成功的。

1.2 BFF层开发提效

提到高德,大家首先想到的应该是其工具属性:高德是一个导航工具,(这个说法现在已经不太准确了,因为高德这几年在做工具化往平台化转型,高德的交易类业务正在兴起,高德打车、门票、酒店等业务发展非常迅猛)。针对高德导航来说,相比集团其他业务,相比电商来说,有大量的只读场景是高德业务的一大技术特点。

这些只读场景里,大量的需求是BFF(Backend For Frontend)类型的只读场景。为什么这么说,因为导航的最核心功能,例如routing, traffic, eta等都是相对稳定的,这部分的主要工作在用持续不断的优化算法,使得高德的导航更准,算出的路径更优。这些核心功能在接口和功能上都是相对比较稳定的,而前端需求是多变的,例如增加个路径上的限宽墩提示等。

Faas特别适合做BFF层开发,在Faas上调用后端相对稳定的各个Baas服务,Faas服务来做数据和调用逻辑封装,快速开发、发布。在业界,Faas用的最多的场景也正是BFF场景(另外一个叫法是SFF场景,service for frontend)。

1.3 Serverless是云时代的高级语言

虽然高德已经全面上云了,但是目前还不是云时代的终局,目前主要是全面Docker化并上云,容器方面做了标准化,在规模化,资源利用率方面可以全面享受云的红利,但是业务开发模式上基本还和以前一样,还是一个大型的分布式系统的写法。

对于研发模式来说还并没有享受云的红利,可以类比为我们现在是在用汇编语言的方式来写跑在云上的服务。而Serverless、云原生可以理解为云时代的高级语言,真正做到了Cloud as a computer,只需要关注于业务开发,不需要考虑大型分布式系统的各种复杂性。

1.4 Go-Faas补充Go语言生态

前面讲到了因为客户端上云项目,我们在阿里云FC(函数计算)团队之上做加法,开发了C++ Faas Runtime。

不仅如此,我们还开发了Go-Faas,为什么会做Go-Faas呢,这里也简单介绍一下背景,高德服务端Go部分的QPS峰值已超百万。高德已补齐了阿里各中间件的Go客户端,和集团中间件部门共建。可观测性、自动化测试体系也基本完善,目前Go生态已基本完善。补齐了Go-Faas之后,我们就既能用Go写Baas服务,又能用Go写Faas服务了,在不同的业务场景采用不同的服务实现方式,Go-Faas主要应用于上文提到的BFF场景。

2. 技术方案介绍——在集团现有基础设施之上做加法

2.1 整体技术架构

上文讲了我们为什么要做这个事情,现在来讲一下我们具体是怎么做这个事情:如何实现,具体的技术方案是什么样的。

我们本着在集团现有的基础设施、现有的中间件基础之上做加法的思想,我们和CSE,阿里云FC函数计算团队合作共建,开发了C++ Faas Runtime 和 Go Faas Runtime。整体和集团拉通的技术架构如下图所示,主要分为研发态、运行态、运维态三个部分。

2.1.1 运行态

先说运行态,业务流量从网关进来,调用到FC API Server,转发到C++/Go Faas Runtime,Runtime来完成用户函数里的功能。Runtime的架构下一章节来具体介绍。

和Runtime Container一起部署的有监控、日志、Dapr各种Side car,Side car来完成各种日志采集上报功能,Dapr Side car来完成调用集团中间件的功能。

另外,目前Dapr还在试点的阶段,调用中间件主要是通过Broker和各个中间件Proxy来完成,中间件调用的有HSF,Tair,Metaq,Diamond等中间件Proxy。

最后Autoscaling模块来管理函数实例的扩缩容,达到函数自动伸缩的目的。这里的调度就有各种策略了,有根据请求并发量的调度,函数实例的CPU使用率的调度。也能提前设置预留实例数,避免缩容到0之后的冷启动问题。

底层调用的是集团ASI的能力,ASI可以简单理解为集团的K8S + Sigma(集团的调度系统),最终的部署是FC调用ASI来完成函数实例部署。弹性伸缩的,部署的最小单位是上图中的POD,一个POD里包含Runtime Container和Sidecar Set Container。

2.1.2 研发态

再来看研发态,运行态是决定函数是如何运行的,研发态关注的函数的开发体验。如何方便的让开发者开发、调试、部署、测试一个函数。

C++ Faas有个跨平台的难点问题,C++ Faas Runtime里有一些依赖库,这些依赖库没有Java依赖库管理那么方便。这些依赖库的安装比较麻烦,Faas脚手架就是为了解决这个问题,调用脚手架,一键生成C++ Faas示例工程,安装好各种依赖包。为了本地能方便的Debug,开发了一个C++ Faas Runtime Boot模块,函数Runtime启动入口在Boot模块里,Boot模块里集成Runtime和用户Faas函数,可以对Runtime来做Debug单步调试。

我们和集团Aone团队合作,函数的发布集成到Aone环境上了,可以很方便的在Aone上来发布Go或者C++ Faas,Aone上也集成了一键生成Example代码库的功能。

C++和Go Faas的编译都依赖相应的编译环境,Aone提供了自定义编译镜像的功能,我们上传了编译镜像到集团的公共镜像库,函数编译时,在函数的代码库里指定相应的编译镜像。编译镜像里安装了Faas的依赖库,SDK等。

2.1.3 运维态

最后来看函数的运维监控,Runtime内部集成了鹰眼、Sunfire采集日志的功能,Runtime里面会写这些日志,通过Sidecar里的Agent采集到鹰眼、或者Sunfire监控平台上去(FC是通过SLS来采集的)之后,就能使用集团现有的监控平台来做Faas的监控了。也能接入集团的GOC报警平台。

2.2 C++/Go Faas Runtime架构

上面讲的是和Aone,FC/CSE,ASI集成的一个整体架构,Runtime是这个整体架构的一部分,下面具体讲讲Runtime的架构是怎样的,Runtime是如何设计和实现的。

最上面部分的用户Faas代码只需要依赖Faas SDK就可以了,用户只需要实现Faas SDK里的Function接口就能写自己的Faas。

然后,如果需要调用外部系统,可以通过SDK里的Http Client来调用,如果要调用外部中间件,通过SDK里的Diamond/Tair/HSF/Metaq Client来调用中间件就可以。SDK里的这些接口屏蔽了底层实现的复杂性,用户不需要关心这些调用最后是如何实现,不需要关心Runtime的具体实现。

SDK层就是上面提到的Function定义和各种中间件调用的接口定义。SDK代码是开发给Faas用户的。SDK做的比较轻薄,主要是接口定义,不包含具体的实现。调用中间件的具体实现在Runtime里有两种实现方式。

再来看上图中间蓝色的部分,是Runtime的一个整体架构。Starter是Runtime的启动模块,启动之后,Runtime自身是一个Server,启动的时候根据Function Config模块的配置来启动Runtime,Runtime启动之后开启请求和管理监听模式。

往下是Service层,实现SDK里定义的中间件调用的接口,包含RSocket和Dapr两种实现方式,RSocket是通过RSocket broker的模式来调用中间件的,Runtime里集成了Dapr(distributed application runtime) ,调用中间件也可以通过Dapr来调用,在前期Dapr试点阶段,如果通过Dapr调用中间件失败了,会降级到RSocket的方式来调用中间件。

再往下就是RSocket的协议层,封装了调用RSocket的各种Metadata协议。Dapr调用是通过GRPC方式来调用的。最下面一层就是集成了RSocket和Dapr了。

RSocket调用还涉及到Broker选择的问题,Upstream模块来管理Broker cluster,Broker的注册反注册,Keepalive检查等等,LoadBalance模块来实现Broker的负载均衡选择,以及事件管理,连接管理,重连等等。

最后Runtime里的Metrics模块负责鹰眼Trace的接入,通过Filter模式来拦截Faas链路的耗时,并输出鹰眼日志。打印Sunfire日志,供Sidecar去采集。下图是一个实际业务的Sunfire监控界面:

2.2.1 Dapr

Dapr架构见下图所示,具体可以参考看官方文档

Runtime里以前调用中间件是通过RSocket方式来调用的,这里RSocket Broker会有一个中心化问题,为了解决Outgoing流量去中心化问题,高德和集团中间件团队合作引入了Dapr架构。只是Runtime层面集成了Dapr,对于用户Faas来说无感知,不需要关心具体调用中间件是通过RSocket调用的还是通过Dapr调用的。后面Runtime调用中间件切换到Dapr之后,用户Faas也是不需要做任何修改的。

3. 业务如何接入Serverless

如前文所述,统一在Aone上接入。我们提供了C++ Faas/Go Faas的接入文档。提供了函数的Example代码库,代码库有各种场景的示例,包括调用集团各种中间件的代码示例。

C++ Faas/Go Faas的接入面向整个集团开放,目前已经有一些高德以外的BU,在自己的业务中落地了C++ /Go Faas了。

Node.js Faas使用淘宝提供的Runtime和模板来接入,Java Faas使用阿里云FC提供的Runtime和模板来接入就可以了。

3.1 接入规范——稳定性三板斧:可监控、可灰度、可回滚

针对落地新技术大家可能担心的稳定性问题,应对法宝是阿里集团的稳定性三板斧:可监控、可灰度、可回滚。建立Faas链路保障群,拉通上下游各相关业务方、基础平台一起,按照集团的1-5-10要求,做到1分钟之内响应线上报警,快速排查,5分钟之内处理;10分钟之内恢复。

为了规范接入过程,避免犯错误引发线上故障,我们制定了Faas接入规范和CheckList,来帮助业务方快速使用Faas。

可监控、可灰度、可回滚是硬性要求,除此之前,业务方如果能做到可降级就更好了。我们的C++客户端上云业务,在开始试点的阶段,就做好了可降级的准备,如果调用Faas端失败,本次调用将会自动降级到本地调用。基本上对于客户端功能无损,只是会增加一些响应延迟。

另外,客户端上该功能的版本,可能会比服务端稍微老一点,但是功能是向前兼容的,基本不影响客户端使用。

4. 我们目前的情况

4.1 基础平台建设情况

  • Go/C++ Faas Runtime开发完成,对接FC-Ginkgo/CSE、Aone完成,已发布稳定的1.0版本。
  • 做了大量的稳定性建设、优雅下线、性能优化、C编译器优化,使用了阿里云基础软件部编译器优化团队提供的编译方式来优化C++ Faas的编译,性能提升明显。
  • C++/Go Faas接入鹰眼、Sunfire监控完成,函数具备了可观测性。
  • 池化功能完成,具备秒级弹性的能力。池化Runtime镜像接入CSE,扩一个新实例的时间由原来的分钟级变为秒级。

4.2 高德的Serverless业务落地情况

C++ Faas和Go Faas以及Node.js Faas在高德内部已经有大量应用落地了。举几个例子:

上图中的前两个图是C++ Faas开发的业务:长途天气、沿途搜。后两个截图是Go-Faas开发的业务:导航Tips,足迹地图。

高德是阿里集团内Serverless应用落地规模最大的BU,已落地的Serverless应用,日常峰值早已超过十万QPS量级。

4.3 主要收益

高德落地了集团内规模最大的Serverless应用之后,都有哪些收益呢?首先,第一个最重要的收益是:开发提效。我们基于Serverless实现的端云一体组件,助力了客户端上云,解除了需求实现时的客户端发版依赖问题,提升了客户端的开发迭代效率。基于Serverless开发的BFF层,提升了BFF类场景的开发迭代效率。

**第二个收益是:运维提效。**利用Serverless的自动弹性扩缩容技术,高德应对各种出行高峰就更从容了。例如每年的10-1出行节,5-1、清明、双旦、春节的出行高峰,不再需要运维或者业务开发同学在节前提前扩容,节后再缩容了。

高德业务高峰的特点还不同于电商的秒杀场景。出行高峰的流量不是在一秒内突然涨起来的,我们目前利用池化技术实现的秒级弹性的能力,完全能满足高德的这个业务场景需求。

**第三个收益是:降低成本。**高德的业务特点,白天流量大、夜间流量低,高峰值和低谷值差异较大,时间段区分明显。利用Serverless在夜间流量低峰时自动缩容技术,极大的降低了服务器资源的成本。

5. 后续计划

  • FC弹内函数计算使用优化,和FC团队一起持续优化弹内函数计算的性能、稳定性、使用体验。用集团内的丰富的大流量业务场景,不断打磨好C++/Go Faas Runtime,并最终输出到公有云,普惠数字化转型浪潮中的更多企业。
  • Dapr落地,解决Outcoming流量去中心化问题,逐步上线一些C++/Go Faas,使用Dapr的方式调用集团中间件。
  • Faas混沌工程,故障演练,逃生能力建设。Faas在新财年也会参与我们BU的故障演练,逐一解决演练过程中发现的问题。
  • 接入边缘计算。端云一体的场景下,Faas + 边缘计算,能提供更低的延时,更好的用户体验。

以上要做的事情任重道远,另外我们未来还会做更多云原生的试点和落地,技术同学都知道,从技术选型、技术原型到实际业务落地,这之间还有很长的路要走。

欢迎对Serverless、云原生、或者Go应用开发感兴趣的小伙伴,想一起做点事情的同学来加入我们(不管之前是什么技术栈,英雄不问出处,投简历到 [email protected],邮件主题为:姓名-技术方向-来自高德技术),这里有大规模的落地场景和简单开放的技术氛围。欢迎自荐或推荐。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK