阿里妹导读:API 是模块或者子系统之间交互的接口定义。好的系统架构离不开好的 API 设计,而一个设计不够完善的 API 则注定会致使系统的后续发展和维护很是困难。比较好的API设计样板能够参考 github 和 k8s ,它们都是典型的RESTful接口。云服务对外开放的窗口就是OpenAPI,今天要讨论的话题是“云服务场景下OpenAPI设计的挑战”。html
之因此强调“云服务”的缘由在于,小规模独立API的设计与大规模批量生产API面临的问题是不同的。一样,只专一于自身产品API的可用性与从更高的层次去看云服务总体API体系的健壮性,要建设的体系也是不同的。git
例如,作一个WEB页面使用的API,只须要考虑性能、稳定性、鉴权就好,由于页面与API是一体的,能够一块儿发布和回滚,只要功能正常,即使API设计有缺陷,用户也能够接受。而云服务要开放API考虑问题就多了:程序员
因此云服务因为产品线众多,须要统一的API规范来保证云产品间API体验一致,在底层平台层面互相兼容,便于上层应用平台化,同时要兼顾到围绕公有云服务的第三方生态、开源生态、企业生态。github
在具体规范层面,业界也在不断尝试,比较知名的是OpenAPI Specfication和 Google API Design Guide。前者针对RESTful API设计在细节层面给出了很是具体的规定,已经成为RESTful API设计领域的事实标准,然后者则主要从云厂商的角度提出许多最佳实践性质的规范与建议,这些原则不只仅适用于RESTful API,也适合其余类型API设计。对API设计感兴趣的开发者,能够详细研究一下资料。编程
2018年Openapi Specification发布了3.0版本
图片来源:https://swagger.io/后端
所以,对于云服务商来讲,在关键环节制定明确的API规范有助于云服务对内提升产品间互通的效率,对外提供一致的使用体验,有助于云服务更好地被集成。那么要作好云服务的横向规范会碰到哪些困难呢?本文就从实践中总结了7大挑战。设计模式
当你在考虑单个产品的API表现形式时,首先会选择一种具体的API风格,常见的有RPC(Remote Procedure Call)和ROA(the Rest-Oriented Architecture)两种模式,而后针对复杂的数据结构你会考虑使用什么样的序列化协议,常见的包括Json/Xml/WSDL/Hessian等,用于封装传输数据。但涉及到不一样的产品时,在具体选型时考虑的问题可能就不太同样了。api
gRPC示意图
图片来源:https://www.grpc.io/docs/guides/浏览器
虽然RESTful设计风格曝光率很高,但并非全部云服务商都选择了彻底遵循RESTful,例如AWS和阿里云RPC风格反而占了大多数,Google和Azure则RESTful居多。安全
Restful API的优点是HTTP具有更好的易用性,让异构系统更容易集成,且开发执行效率比较高,面向资源要求也比较高。而RPC API可使用更普遍的框架和方案,技术层面更底层也更为灵活,设计起来相对简单,掌握起来有必定门槛,架构上更加复杂。
RESTful与RPC模式对比
不一样的团队根据实际状况和业务形态可能选择不一样的方案,那云服务做为一个总体应该强制统一好仍是随意选择好?若是强制统一风格,有些适合RESTful风格的服务非要使用RPC的话,看起来就会比较丑陋,若是只是一个过程化的服务调用,往RESTful资源化设计方向去靠会比较困难。但若是不强制使用统一风格,会形成针对API的体系化支持会更加复杂,例如为兼容两种风格SDK的自动化支持须要两套代码。
一般RESTful风格对API设计者的要求是比较高的,主要的难点在于面向资源设计要求开发者事先作好规划,将后端数据模型与API服务模型相匹配。因此RESTful API的开发者应该是熟知系统总体实体关系模型的,很难想象一个不懂后台业务的新手能设计出合理的API来。那么是否是RPC风格API就不须要面向资源设计了呢?从实践中来看,并非!RPC风格的API也须要资源模型来支持,在下一节中会重点分析。
因此,对于云服务商来讲,选择API风格时要考虑几个问题:
选定了具体设计模式后,就要努力作到统一,避免多种模式混杂带来管理成本的上升。若是确实有必要两种方式都支持(例如阿里云就同时支持RPC和ROA),就须要在技术上作好充分的准备。
用户使用API来访问云服务,本质上是想经过对某种云资源执行特定的操做来完成一个业务动做。Restful API须要面向资源设计众所周知,那为何RPC接口在云服务场景下也须要有资源模型呢?
RPC形式的API组织形态是领域和行为(对象和方法),随着时间的推移,API愈来愈多最终造成一个庞大的集合。以阿里云为例,对外开放的OpenAPI数量已经达到10000多个,涵盖了接近200个不一样的产品。由于开发者必须单独学习每一个API,耗时又容易出错,若是没有一个脉络的理解起来比较困难。若是有一套标准的资源模型,API就能够按照资源模型的维度分类组织,用户使用起来也会有迹可循,体验上会更好,不然面对如此多的API一点点学习无疑是个痛苦的过程。
另外,云服务并不是单个服务的简单排列,它是多个体系的横向整合,整体对外呈现出有机链接。随着云计算的发展,企业客户对对云服务的要求不断提升。最典型的就是当企业客户大规模开始上云后,对虚拟化的云产品提出了各类管理需求,例如鉴权、编排、弹性伸缩等。
企业客户对云服务的管理需求
以最经常使用的鉴权功能为例,客户建立了一组云服务器来跑业务,运维人员须要有重启服务器的权限,其余角色人员则不须要此类权限,针对RestartServer这么一个API就须要进行权限控制了。权限在云平台中通常是中心式管理的,单独的云产品不须要分别管理。若是统一处理鉴权,就须要知道当前API正在操做什么资源,与此相关的资源有哪些(例如与服务器有关的资源包括磁盘、网卡、网络等关联资源),而后针对全部相关资源逐一鉴权才能确认API操做是否可行。
上面提到的资源有两个关键点,一是要有统一的资源模型,便于云产品对特定的API进行鉴权,二是要明确资源关系,当出现资源依赖的时候,须要关联鉴权。在Google的API Guide中就明确提到须要资源关系,能够看出资源关系不只仅是用来作API设计建模的,它对于平台功能的实现也有相当重要的做用。不了解资源关系,有可能把多个资源封装到一个API中,使用和变动都很痛苦,即使后期发现了问题再补救拆开,因为不少用户已经在使用了,要付出的开发成本和沟通成本也是极大的,甚至成为不可能。因此清晰的资源模型有利于梳理清楚API体系。
定义清晰的实体关系图有助于设计出更为完整的API
并且,明确的资源模型对于构建云上运维管理基础设施相当重要,例如能够经过对资源打Tag来对资源进行分类管理(参考阿里云资源Tag),分组受权(参考阿里云资源组),资源审计(参考阿里云CloudConfig),相似开源软件Terraform这样的编排工具,因为有资源模型会更容易接入和使用。
因此,统一的资源模型对云服务的帮助是巨大的:
既然有这么多好处,那么众多的云产品在实际设计API的时候可否坚持以资源为中心,充分考虑到上下游的需求就变成一个很大的挑战了。
肯定了设计模式和资源模型后,是时候进入到API设计细节了。诸如API名称、参数名、属性名称、数据格式、错误码之类的信息,看起来根本不是问题。单个产品问题还不大,只要保证内部风格一致便可,若是考虑到云服务多产品对外的总体体验,就有必要考虑如下问题:
上述问题都是实际研发过程当中要注意的,要所有罗列的话远不止这些。API的用词描述是云服务展示给外部用户的第一印象,绝非随意写就。对人员有必定规模,内部有多条产品线的组织来讲,如何协调组织的各个部分对外具备统一的体验是个很大挑战。
回顾下HTTP协议,最广为认知的是对HTTP Mehod的约定,使用9个单词就完成了对基本动做的规范,为开发者提供了清晰的思惟模型:
Http Method 类型
图片来源:https://tools.ietf.org/html/rfc7231
一样,在HTTP Header里面也对浏览器信息、语言、网络链接属性等作了详细的规定,这样开发者在使用HTTP服务的时候都有一个大体的约定,在关键信息上面不会有误差,保障了异构系统的接口一致性。
所以云服务在管理API时应该考虑一些具体的规范,对命名规则、标准词汇、最佳实践模式、错误码等信息都有明确的规定,同时用系统化、平台化的手段来管理API,确保不走偏。设计风格不是云服务API设计中致命的问题,可是它关乎云服务外表形象,不可不察。
API是后端服务的外部表达,是服务就有可能出现问题,不管这个问题是可预期的仍是不可预期的。若是只考虑功能自己功能特性,而忽视对异常状况的设计,当问题出现的时候业务自己可能没法感知形成服务异常,更重要的是站在客户角度去看,不能有效获取错误缘由是很是痛苦的,不少时候只能一筹莫展,下降云服务提供商的总体口碑,甚至损害营收。
假设有个建立资源的API,每调用一次都会建立新的资源,考虑如下状况:
实践中,若是不作好问题a的处理,可能会形成系统异常状况下大批资源被重复建立,有可能形成用户或云服务商资损;问题b-e没有处理好,可能会让用户陷入盲目等待或者盲目重试,使用体验和效率极差;而f-g关系到自动化处理工具如何作到效率最大化,也关系到被集成的效率。
一个异步重试的状态机
当出现异常的时候,API通常是要靠错误码来告知用户有什么问题。HTTP协议自己对错误码作出了详尽的规定,Restful的API要尽量地符合标准。除此以外,云服务有必要在此基础上进一步提供业务错误码和错误信息,来描述错误具体的细节。
当前云服务的错误码不少,看起来很是专业,但问题主要集中在如下几个方面:
1.错误类型过多:错误码越多客户端处理起来越方便吗?看一下HTTP的错误码,只有5大类加几十个子类的错误码就涵盖了全部场景,而一般你们耳熟能详的无非是200、400、40四、500、502等屈指可数的状态码。有的人考虑错误码越多,客户端能够switch/case一下针对每一个错误码作不一样的操做,这个就见仁见智了,通常的程序员可能不会写那么多的分支流程,必要性也不大。
2.错误信息表达不够充分:相比于提供大量的错误码,错误信息的明确表达更为重要。若是错误信息不够详细,做为用户不了解细节没法掌控的云服务,几乎是没法明确发生了什么,要么提工单,要么只能被动等待,客户体验不好。
3.业务错误码与HTTP错误码含义不匹配:例如参数错误应该返回4xx系列Code,返回5xx系列就不够专业。即使是RPC风格的API,也要大体符合HTTP规则,不然可能会给一些依赖HTTP Code的系统形成误导。网上有种思路以为不管后台响应如何,HTTP Code通通返回200,在Body里面的错误信息体现异常信息,这种不利于对接口的监控,由于监控系统很难经过识别消息体来鉴别功能是否正常响应。
4.相同错误不一样云产品表达不一致:这会给客户端开发形成困扰,增长开发工做量,不利于自动化集成,用户体验比较差。
5.错误码应该是可枚举集合:一个API可以产生的错误码类型应该是可预期的,即使是业务升级,也应该给客户提供明确的错误码列表,不能为所欲为。由于用户端须要明确知道可能会发生什么,而不是随时可能出现不可预知的错误类型。若是错误类型不肯定,就意味着针对错误码分支处理基本是无效的。
要作好服务端容错上述问题,须要从云服务总体层面增强API的容错设计,作好错误码规范,增强对错误信息的管理,来提高用户体验。
API都是不断迭代的,一般都须要版本管理。云服务API的版本管理尤为重要,主要是如下缘由:
针对API各类场景的管理,须要一套成熟的API管理平台,照顾到各类场景的需求,也是一项不小的挑战。
API如何开放看起来是奇怪的问题,难道API作出来不就是开放给别人用的吗?作好就开放就开放啊?但在云服务场景下,状况会更复杂一点!
产品技术都是在不断迭代的,功能始终在增长,新的API层出不穷。从客户视角来看,他们对已开发完毕的API是否开放的需求是什么?假设一个云产品有100个功能特性,20个只能保留在内部,官网上总共提供了80个特性,而公开API只开放了50个,这是用户指望的状态吗?理想状态应该是什么?
围绕云服务有一个庞大的生态,除了普通的开发者,还有许多第三方服务商、企业客户、开源工具。当咱们考虑全部这些生态成员的需求时会发现:云服务自身拥有的功能集合与客户能使用的功能集合之间的差别比较能体现产品的开放程度。这里的差别强调的是云服务已经拥有的,不包括云服务自身没有的服务。客户能使用的功能与云服务能提供的功能之间的差距越大,说明云产品的开放程度越低,由于不少功能都做为保留节目被雪藏了,致使客户和第三方服务商没法享受与云厂商接近的服务,最终生态没法拓展。理想情况是,云服务商自身能经过API使用的功能,客户都能经过OpenAPI使用,内外看到的是一致的。
但具体到某个API应不该该开放,实践中会作以下考虑:
针对这些问题,须要在API的管理机制上面下功夫,可以区分不一样的场景,并作好元数据的管理。针对API是否开放要有明确的规范和度量机制,确保该开放的API均可以开放,确保内外客户看到的功能集合基本一致,才有利于云服务更好地被集成,在客户的业务中发挥更大的做用。
在云服务场景中,API并不是孤立存在:
首先,API发布之后,用户要想顺利地使用API,配套设施必不可少,SDK、文档、工具链的集成都须要考虑到,这里的重点是如何保障准确性、及时性和一致性。开发工程师通常都不太喜欢写文档,专业写文档的又可能不太懂技术,再考虑到国际化的问题,就十分有挑战了。SDK方面,一个API要有多种语言的实现,每种语言还要保障其专业性、可用性,很是考验对开发人员编程语言掌握的深度和对API的理解,业界常常采用的自动化生成SDK的方式也会考验对多语言的兼容能力。工具链好比阿里云的 API Explorer、CloudShell等产品也须要及时与API的最新状态保持同步。
其次,云服务因为产品线众多,如何让用户可以快速学习使用API和相关工具,须要在教程、案例、运行时环境等诸多方面增强建设。围绕云服务,已经发展出许多上层生态工具,例如terraform/ansible/spinnaker等开源软件,它们可以帮助云服务更好地使用起来,必须对它们提供支持,如何可以快速覆盖也对平台开发能力是个考验。
另外,API自己的质量保障也是很是重要的。通常都要考虑性能、稳定性、安全等方面的保障体系,经过压测、监控、部署防御软件等方式来确保API在服务的时候不会掉链子。传统的套路在解决系统问题时很是有效,但具体到业务问题的时候就无能为力了。例如,一个建立服务器的API通常来讲都是要求幂等的,怎么检测该API实际上有没有作到幂等呢?推而广之,其余业务流程的正确性又如何保障呢?等API开放了发现问题再修复就为时已晚,显然应该在上线前经过测试来发现这类问题。可是随着业务的发展,如何能保障这类问题能够有统一的解决方案,可以长期跟进及时发现风险避免损失呢?
阿里云API体系简易图
所谓量变引发质变,上述问题针对单个API的时候都好解决,可是当API规模达到成千上万的时候,就必须经过平台化、系统化的手段来解决了。例如,API服务可靠性SLA指标若是要达到4个9,须要制定明确的标准,而且有手段监控到全部API的运行结果,经过分析成功率来判断其是否达到预期水平,这对云服务自己的底层系统建设提出了较高的要求。
因此,以API为中心完善相关体系,保障用户体验的一致性、及时性、稳定性、易用性是很是有挑战的。
参考文献:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages
https://tools.ietf.org/html/rfc7231#section-4
https://www.cnblogs.com/sparkdev/p/10052310.html
https://www.grpc.io/docs/guides/
https://www.terraform.io/docs/index.html
http://www.grabsun.com/article/2015/1135807.html
本文为云栖社区原创内容,未经容许不得转载。