一切皆API的大环境下,如何打造API Everything?

梁向东 2017-12-21 14:30:51

文根据梁向东老师在〖Gdevops 2017全球敏捷运维峰会北京站〗现场演讲内容整理而成。

 

(点击底部“链接”获取梁向东演讲完整PPT)

 

讲师介绍

梁向东,饿了么北京技术中心技术创新部、研发总监,目前负责饿了么API Everything(API接入SOA系统的框架)开发、有菜业务(餐厅采购食材和供应链管理)系统研发及新零售物流配送系统研发;曾在亚马逊从事物流配送系统研发,曾和清华校友创立游戏公司,进行MMORPG游戏的研发和运营;曾在美国优利系统中国有限公司从事金融,交通运输行业的系统研发。深刻了解业务,善于从业务角度,通过技术去解决问题。从业务需求到产品设计,从技术解决方案到实现,从系统上线到推广使用,具有丰富的经验。

 

今天分享讲的和API架构相关,饿了么API Everything框架建设是一个不断演进的过程,借这个机会跟大家分享一二。


 

1

 

什么是API Everything

 

 

 

API这一块不知大家没有什么了解,所以这里先简单介绍一下API,就是相当于前端比如Web访问到后端的服务接口,这中间有一个隔离,适配给外部各端进行访问,隔离是起到安全性的考虑,还有一个协议转换的考虑。当然,基于这一块我们还有很多其它的考虑。在饿了么初期发展阶段,我们的很多Web API层都是手写的,即多数应用服务后端,都自己写Web API,单独部署,提供给前端HTTP API调用。

 

 

 

当时业务高速发展,为了快速应对,有一些业务逻辑会放在Web API层,甚至在Web API层也会访问数据库,进行数据库操作。在API层直接访问数据库会导致安全性的一些问题,这个是不允许的。前端访问后端,这个HTTP API接口是什么风格的,有是Restful的,还有JSON-RPC的,需要统一考虑,不然对前端开发的体验不一致。另外HTTP API文档存在过时,不能反映代码实现的变化,比如代码改了,文档没有改。最后,前端同学和后端同学同时开发,但开发的节奏可能不太一样。比如前端在进行开发,但后端可能会被插入更加紧急的项目,就不能及时完成当前项目的API,可能会延误前端的开发,产生前后端开发不同步,导致前端资源和后端资源有个相互等待,会导致开发体验的不顺畅,效率也不高。

 

2

 

需求调研-API Everything

API

 

基于这些情况,公司考虑是否可以统一形成一个框架,于是我们调研了各个部门,发现他们有这个需求,希望有一个统一的API框架开发,目前也有一些独立写的Web API 层。下面是调研的一些需求:

 

 

 

我们能看到一个很重要的功能就是HTTP到SOA的服务映射,还有认证与鉴权,比如公司的SSO,包括用户、饿了么的一些鉴权,API部署与运行。

 

API Orchestration,这个相当于说API的拼接和剪裁的概念,即可以调用多个API,取各个API返回结果的一部分,重新组合成新的结果,返回给前端。这个应用在一个前端API调用,可以实际调用多个后端API,组装一个返回结果给前端,减少前端调用后端多次,提高前端用户的体验。另外,因为后端已经有了很多基础服务的接口,新业务开发不需要后端再提供接口,只需要在这些接口上进行组合、裁剪就可以了。

 

此外还有API文档、API测试、Mock API、限流、反爬(就是说把接口曝露在公网,存在爬虫爬取这些接口的情况,我们怎么保护接口等等)以及灰度。我们的API Everything做这些事情时,把后端的SOA服务通过API的方式,安全可靠地提供给各种端(Web/APP)来使用。

 

3

 

产品技术方案原则

 

调研出来以后,需要考虑以什么原则去考虑产品和系统设计。

 

 

 

APIEverything是一个基础框架,我们首先考虑到基础框架稳定性是第一的,哪怕你不能满足所有功能需求,但你很稳定,接入API Everything框架的各个应用系统就不会歇菜,不出问题,服务才能在稳定的基础上提升,才有可能增加新的功能和特性,也就是说稳定压倒一切。然后是性能,包括吞吐量(响应速度)、性能高了,就会节省硬件资源;高可用性,避免出现单点故障。还有容错性,对外各种依赖,要考虑外部依赖歇菜怎么办,怎么降级。还有,API Everything接了后端的应用系统,外部流量进来,不能冲击到后端应用系统。如何让这个系统更健壮,怎么保护自己,怎么保护接入的应用系统等等。

 

其次,在这个基础之上考虑DevOps怎么弄,提供接入方自助DevOps,还有各种指标查看、监控告警、排错手段、查看log/trace/exception、自助扩容等。最终希望这一块做到对接入方是透明的,可以自动扩容。API Everything框架引起的问题,由我们解决,接入应用方出现的问题,由接入方解决,要有非常清晰的边界界定。一般问题可以自动解决,现场日志自动保留,尽可能自愈。并且接入方知道发生了什么情况。

 

另外,就是怎么让我们的研发或者应用开发端更“懒”,就是把经常要做的事情自动化,比如接入一个应用方,要进行各种配置,比较繁琐也容易出错,那我们是不是可以进行自动化接入、自动化配置呢?

 

刚才也谈到代码和文档不同步怎么办,所以我们不写文档,在代码里面写文档,比如:在Java代码里写Java doc注释,我们就把这些注释抽出来,作为API文档的一部分。另外,我们也提供一些标注,帮助完成文档。

 

用户体验也是考虑的一大因素,因为技术产品基本上由工程师直接进行开发,追求完成功能,多数没有考虑用户体验,导致用起来操作别扭。所以在这方面要充分吸取教训,把使用者的体验考虑起来,能点一下就可以的,就不用点两下。不能把技术复杂性暴露给用户去理解、去操作。让用户用起来很爽,简单不去操作是一个目标。这个框架涉及到很多配置,散放在不同系统,我们的想法是在一个配置里面全把它搞定,不要让用户理解这个是API Everything框架的哪一部分管理的,要到哪个系统去操作。另外就是满足不同的功能需求,比如接入不同的协议等。这是我们对整个产品方案有些原则上的考虑。

 

4

 

生命周期

 

 

 

从API这边出发,可以看到API的生命周期是从API开发开始的,这个过程中会有文档、Mock,开发完了是管理,也就是授权谁能访问,有些是不是可以灰度。API管理之后是API网关服务,就是运行态服务,对API进行协议转换,比如将HTTP 协议转换成SOA,调用后台的SOA服务,最后进入API运维,就是对API进行监控管理和部署扩容。

 

5

 

产品规划

 

 

根据产品系统设计原则,结合API的生命周期,我们就规划了下面几个产品。

 

 

 

比如说开发支持这一块,就是API Portal,运行支持这块就是Stargate Cluster。还有质量保证,就是API Robot,通过自动化回归测试来保证API的质量。另外要考虑到在开发的过程中,怎么让前后端同步,这里面重要一点怎么样Mock API的数据,让前后端分离开发,就产生了Mock Server,于是根据规划形成了这四个产品。

 

但这四个产品之间是什么样的关系呢?这里从系统上的交互来考虑。

 

 

 

基本上我们从底下看,前端的应用(比如到达圈前端),通过HTTP访问,到达Nginx Cluster,然后转向SOA服务。灰色的路径就是到达圈管理后台应用,灰色再上去就到达圈服务,另外还有红色这条路径,前端URL可以通过加入query string访问Mock Server, Stargate  Cluster收到这个querystring,就不会发给后端SOA服务,会路由到指定的MockServer。前端会通过Mock的方式完成前端的开发。

 

API Portal负责API文档这块,文档对应的是部署到哪个环境,在API Portal里有显示。在饿了么有几个环境,一个是开发的Alpha测试环境,提供给开发使用的。还有一个是Beta环境,是提供给测试来验证是否可以上线的环境,只有通过了Beta测试,才能上线。这个Beta环境也用来和其他团队进行联调。最后是Prod环境,用于线上生产。在API Portal上就能知道当前部署的应用,对外提供的API文档具体是什么,这是API Portal通过访问Stargate Cluster部署信息获得的。

 

API Robot从API Portal中获取API定义,通过定义发测试请求给Stargate Cluster。

 

饿了么内部服务是SOA架构,服务间有相互依赖的情况,需要进行测试、联调。有时候发现我们SOA服务依赖对方SOA服务,对方还没有开发完成,我们想测试自己开发 的SOA服务怎么办?这时我们就可以用Mock Server,Mock 对方的SOA服务,写一下Mock Case,完成我们自己的 开发测试。

 

 

 

刚才说代码即文档,所以可能要规范一下怎样写代码,注释和标注写完了,就可以自动化从这些注释和标注中抽出文档,形成API文档。Web API这一块不需要手工写,目前我们自动生成对应Web API的代码,然后自动再部署。部署就是监听SOA服务部署消息,收到了部署消息,就自动生成的Web API代码并且自动部署。而Mock,我们也是自动生成的,创建Mock Case的时候,就自动生成相应的数据,这些数据可以自己改。还有API的监控告警,每个应用接入,自动进行全链路监控。

 

6

 

Stargate Cluster技术架构

 

 

 

这是其中一个产品Stargate Cluster的技术架构。从上面看,ELESS是我们构建系统,我们会监听它的构建消息,当有构建过来的时候,调用base.stargate_core服务,该服务实现非常简单,就是把StargateCluster需要的信息保存到MaxQ里面,MaxQ是饿了么自己开发的一个MQ产品,目前在大量应用。最后Stargate Cluster运营管理服务是从MaxQ取消息进行处理。

 

为什么会有这样的考虑?因为之前我们在Stargate Cluster运营管理服务里经常有迭代开发,经常增加一些功能(比如异地多活),这些功能不断地迭代、增加,需要经常部署,处于一个不太稳定的情况。我们想任何这种构建和部署消息不能丢,于是就有了 stargate_core这个服务,这个服务非常简单,不进行功能上的迭代,保持不变,这样就比较可靠,作用就是把构建和部署消息放在MaxQ里头;而stargate运营管理不断开发、然后重启,这个过程中至少MaxQ里的数据不会丢,重启完了也可以消费,继续进行部署。我们是基于变化和不变化的隔离去考虑系统可靠性的结果。

 

Stargate Cluster基于Docker部署

 

 

 

谈谈为什么能自动部署?其实挺有意思的,我们这边用的是Docker环境。从底下开始看,可以看到比如SOA服务部署了,通过ELESS(饿了么发布系统 ),我们获得部署消息,放到MaxQ里,我们从MaxQ拿出消息,调用AppOS(饿了么自研的Docker平台),启动相应的Docker实例,实例上运行着这个SOA服务 对应的Web API代码 ,Docker实例启动时,调用Navigator(饿了么自研的Nginx管理平台),将该Docker实例的IP注册到Nginx上,这样外部流量就打到这些Docker上了,在新Docker成功启动之后, Stargate Cluster就会调用Appos 将之前版本的Docker实例给销毁掉,通过Navigator 将对应在Nginx上的IP也删除掉,这就是完成自动部署。

 

 

 

这是我们自动部署的一些信息,可以看到左上角基本上是SOA服务部署的Push Seq,下面是PushSeq Used by Client, 这两个Push Seq一致,就说明SOA服务部署时,Stargate Cluster将其对应的Web API端也自动部署了,两边用的版本(Push Seq)是一致的。同时,包括部署的一些版本信息我们也都会保存下来。

 

7

 

API Portal – 自动化文档

 

 

 

讲完Stargate Cluster,我们看看API Portal这一块。 API Portal在系统部署时,获取部署的源文件,自动解析这些代码,然后根据代码里面的注释和标注自动生成API文档,这个文档以Swagger方式存储。刚开始我们以Swagger的原生界面去展示这个界面,前端开发不太习惯这个界面,于是我们就用前端喜欢的,即作为各种表格进行展示来给他们使用。上面的表格展示方式,就是因为这个开发出来的。

 

那Swagger原生的界面还需要吗?API Portal上有一个功能, Try it Out(就是试一试),具体就是后端开发采用这个功能看看后端API吐的数据长得怎么样,不对就修改后端API,直到满意为止。前端也使用这个功能,看看没有实际数据又是怎么样的。Try it Out功能就采用了Swagger原生的界面,后端反而比较喜欢这个页面,因此保留下来。这样前后端的用户体验,也都能满足,大家各取所需。下面是一个Swagger文档界面:

 

 

8

 

Mock Server 流程

 

 

 

MockServer是什么?看看这个场景,SOA Client要对Service Provider进行测试, Service Provider (就是被测试的对象Server Under Test )依赖外部的服务比如Server Cluster 1,但是外部的服务因为其它情况不能用,我们就用MockServer来模拟Server Cluster 1,这样依赖问题解决了,SOA Client 对 Service Provider就能正常进行测试了。使用Mock Server还可以解决,依赖服务需要返回特定的场景,但又不好操作,这样通过MockServer,写不同的Mock Case进行返回,就比较方便。

 

实际情况下SOA环境里面有很多依赖关系,但对方的接口没有确认或者环境不好怎么办?我们通过Mockserver把这些服务全部屏蔽掉,这样只需要测试我们要测试的服务就好,这对SOA环境解决依赖问题,是挺有效的。

 

Mock Server—自动解析

 

 

 

饿了么有Maven私服,各个SOA服务之间通过Maven私服上的API进行调用。上面是我们的Mock Server界面,可以看到左边是输入依赖服务的接口Maven依赖,基本上操作就是延续之前SOA调用的一些流程,把外部依赖填到上面的框里头,在Mock Server指定依赖的接口,于是Mock Server就能从Maven私服去拉这些依赖,自动分析它到底有哪些类,分析好这个类,包括这个类里面有哪些方法都全部显示出来。上图右边的方法就是自动分析。黄色标识的那个方法,就是想进行Mock,点击下右边的加号,就创建了Mock Case。这个Mock Case名字就是测试任意参数。

 

自动生成Mock Case

 

 

 

MockCase是说当Mock Server接收的数据,即请求的参数和Mock Case里设定的Input匹配,那么这个Mock Case里设定的Output就作为响应返回。刚才创建了一个Mock Case叫做测试任意参数, Mock Case的值是根据分析的Model(数据定义),自动生成。比如Input "type" : Integer,我们没有加入enum[234567]的时候,就意味着只要是请求里包含任何整数,该Mock Case就会被命中,返回Output的内容。如果加入了enum [234567],那么只有请求参数里是234567,该Mock Case才会命中。

 

Output支持函数,上面Preview 就可以看到执行Output的表达式之后是什么结果,当该Mock Case被命中时,这个Preview的结果就作为响应返回。

 

前后端开发分离

 

 

 

后端开发根据PRD,通过在代码接口里添加标注和注释,就完成了API定义,把代码check in,构建系统知道这个变化,这个变化通知到API Portal,就自动生成了API文档,后端在API Portal上通知前端,双方通过API Portal讨论确认API文档。前端根据这个文档,通过API Portal上提供的Mock,完成前端的开发,更复杂的交互需要构造后端API产生不同的数据。前端通过构造不同的Mock Case,完成这些复杂的开发。开发完成之后,就去进行其它事情,在后端完成API开发之后,通知前端一起进行联调。在以前,前后端不分离的话就会相互等待。前端开发等后端实现API,吐出数据之后再进行,对前端开发体验不好,现在这样前端就可以一气呵成把它开发完成,不用等候后端了。现在,后端这边也开发完了,说一个时间大家联调一下就OK了,这就是整个前后端开发分离的流程。

 

应用实践

 

 

 

这个流程在我们配送范围的项目里已经实际应用起来了,这里我们给出了一个迭代的统计,这个迭代可以在开发的过程中就看到使用的情况,比如原来估计工时5天,现在3天就做完了。后端也节省一下时间,以前他们说不然就等前端调用后告诉他们什么样子,或者他自己写一些测试脚本去看是什么样的数据,这方面他就写了API,通过API Portal就能看到后端API吐的数据是否正确,这样的话后端开发也减少了开发时间。还有,后端以前要写Web API代码,还要进行部署,现在也不用写了,也不用部署了。以前联调时间都比较长,是两天时间,因为其实那时联调是包括开发时间,他不确定数据对不对,所以有些处理还没有写,等他看到数据以后再去开发出来,那时间稍微长一些。联调的时间,只需半个小时,看这个事情通不通就好了,整个开发体验还是不错的,总体来看,整个开发时间减少了50%左右。

 

问题真的解决了吗?

 

 

 

有了这些产品,我们看最早提到的那些问题是不是都解决了。假如今天写业务,我们是通过统一的方式介入,把它下沉到SOA,因此业务也不会分散到各个地方。我们在定义API时也给了一个缺省的API生成方式,就是使用Json RPC,自动将方法签名等作为URL。另外也提供了Mock服务,帮助前后端开发分离,还有就是代码即是文档这一块。然而这些问题都解决了,真的解决了吗?其实还远远没有,还有更多事情要解决。

 

1、全链路环节比较多,出现问题时如何快速定位?

2、故障发生时:

  • 能够自动把现场保留下来吗?

  • 能够执行基本分析,把分析的结果保存下来吗?

  • 能够自愈吗?

3、能够快照后台服务及数据,通过Docker环境,通过之前记录的traffic,自动化完成回归测试吗?

4、采用Async Web,提高性能?采用GO?

5、当有一些业务需求:

  • 现有API相互组合就可以完成这个需求,还是需要开发?

  • 需要智能分析所有API业务属性吗?

  • 需要面向业务开发需要提供搜索和推荐?

 

9

 

关于团队思考

 

 

我们一直在想,面向开发、测试、运维角色,如何提供一个更好的服务,也就是说怎么样更懒,更自动化。比如在API的运维上,我们能不能做到对于接入用户方完全无感知。

 

还有就是我们的API Everything团队,面对多个接入方同时进行,我们应怎样处理,自动化?其实我们不希望太多重复的事情重复去做,而是考虑怎么通过工具把我们自己给解放出来,去做更多自动化的事情。首先解放自己,才能拯救用户。

 

最后我们也希望从根上去思考问题,去解决问题,如果大家对API有什么疑问,建议,对于API架构有更好的想法,或者想加入我们,一起来推进API或者框架开发这块,可以联系我们(联系方式:xiangdong.liang@ele.meor alex.liangxd@qq.com),谢谢!

↓↓↓点这里下载本文干货PPT
https://pan.baidu.com/s/1boKhXiJ

最新评论
访客 2024年04月08日

如果字段的最大可能长度超过255字节,那么长度值可能…

访客 2024年03月04日

只能说作者太用心了,优秀

访客 2024年02月23日

感谢详解

访客 2024年02月20日

一般干个7-8年(即30岁左右),能做到年入40w-50w;有…

访客 2023年08月20日

230721

活动预告