云服务OpenAPI设计7大挑战(上)
前言
关于API的设计与开发,在业界已经进行了很多讨论,无论是API的具体设计原则,还是针对API的规范性指引,都层出不穷。而有关RESTful的API设计风格的讨论在近年来也是愈加热闹,比较好的API设计样板可以参考 github 和 k8s ,它们都是典型的RESTful接口。云服务对外开放的窗口是OpenAPI,所以今天要讨论的话题就是“云服务场景下OpenAPI设计的挑战”。
为什么要有API规范
之所以强调“云服务”的原因在于,小规模独立API的设计与大规模批量生产API面临的问题是不一样的。同样,只专注于自身产品API的可用性与从更高的层次去看云服务整体API体系的健壮性,要建设的体系也是不一样的。
例如,做一个WEB页面使用的API,只需要考虑性能、稳定性、鉴权就好,因为页面与API是一体的,可以一起发布和回滚,只要功能正常,即便API设计有缺陷,用户也可以接受。而云服务要开放API考虑问题就多了:
首先,云服务开放的是基础设施和服务接口,一般是系统级的对接,API一旦开放想要变更就非常困难
其次,云服务并非单独运行,不同的产品实际场景中是互相组合的,需考虑产品间的一致性和互通便利性
云服务API数量庞大,为了更方便使用,配套的API查找、编排、自动化生成SDK等需求也比普通服务强烈
云服务的稳定性非常重要,核心产品的稳定性就是客户的生命线,要求非常高
所以云服务由于产品线众多,需要统一的API规范来保证云产品间API体验不一致,在底层平台层面互相兼容,便于上层应用平台化,同时要兼顾到围绕公有云服务的第三方生态、开源生态、企业生态。
在具体规范层面,业界也在不断尝试,比较知名的是OpenAPI Specfication和 Google API Design Guide。前者针对RESTful API设计在细节层面给出了非常具体的规定,已经成为RESTful API设计领域的事实标准,而后者则主要从云厂商的角度提出许多最佳实践性质的规范与建议,这些原则不仅仅适用于RESTful API,也适合其他类型API设计。对API设计感兴趣的开发者,可以详细研究一下上面的资料。
2018年Openapi Specification发布了3.0版本
因此,对于云服务商来说,在关键环节制定明确的API规范有助于云服务对内提高产品间互通的效率,对外提供一致的使用体验,有助于云服务更好地被集成。那么要做好云服务的横向规范会碰到哪些困难呢?本文就从实践中总结了7大挑战,以下前半部分内容:
挑战1. 选择API设计模式
当你在考虑单个产品的API表现形式时,首先会选择一种具体的API风格,常见的有RPC(Remote Procedure Call)和ROA(the Rest-Oriented Architecture)两种模式,然后针对复杂的数据结构你会考虑使用什么样的序列化协议,常见的包括Json/Xml/WSDL/Hessian等,用于封装传输数据。但涉及到不同的产品时,在具体选型时考虑的问题可能就不太一样了。
gRPC示意图
RESTFUL示意图
虽然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风格时要考虑几个问题:
选择支持哪种风格,才能更好地体现业务特性,让客户操作起来更加方便
设计API时能否面向资源设计,相应的工程人员是否具备做这种设计的能力
针对这种风格工具链的支持是否到位,投入产出比如何
业界流行的趋势如何,是否需要考虑与其他系统体系的互操作
选定了具体设计模式后,努力做到统一,避免多种模式混杂带来管理成本的上升。如果确实有必要两种方式都支持(例如阿里云就同时支持RPC和ROA),就需要在技术上做好充分的准备。
挑战2. 面向资源设计API
用户使用API来访问云服务,本质上是想通过对某种云资源执行特定的操作来完成一个业务动作。RESTful API需要面向资源设计众所周知,那为什么RPC接口在云服务场景下也需要有资源模型呢?
RPC形式的API组织形态是领域和行为(对象和方法),随着时间的推移,API越来越多最终形成一个庞大的集合。以阿里云为例,对外开放的OpenAPI数量已经达到6000多个,涵盖了接近200个不同的产品。因为开发者必须单独学习每个API,耗时又容易出错,如果没有一个脉络的理解起来比较困难。如果有一套标准的资源模型,API就可以按照资源模型的维度分类组织,用户使用起来也会有迹可循,体验上会更好,否则面对如此多的API一点点学习无疑是个痛苦的过程。
另外,云服务并非单个服务的简单排列,它是多个体系的横向整合,总体对外呈现出有机连接。随着云计算的发展,企业客户对对云服务的要求不断提高。最典型的就是当企业客户大规模开始上云后,对虚拟化的云产品提出了各种管理需求,例如鉴权、编排、弹性伸缩等。
企业客户对云服务的管理需求
以最常用的鉴权功能为例,客户创建了一组云服务器来跑业务,运维人员需要有重启服务器的权限,其他角色人员则不需要此类权限,针对RestartServer这么一个API就需要进行权限控制了。权限在云平台中一般是中心式管理的,单独的云产品不需要分别管理。如果统一处理鉴权,就需要知道当前API正在操作什么资源,与此相关的资源有哪些(例如与服务器有关的资源包括磁盘、网卡、网络等关联资源),然后针对所有相关资源逐一鉴权才能确认API操作是否可行。
上面提到的资源有两个关键点,一是要有统一的资源模型,便于云产品对特定的API进行鉴权,二是要明确资源关系,当出现资源依赖的时候,需要关联鉴权。在Google的API Guide中就明确提到需要资源关系,可以看出资源关系不仅仅是用来做API设计建模的,它对于平台功能的实现也有至关重要的作用。不了解资源关系,有可能把多个资源封装到一个API中,使用和变更都很痛苦,即便后期发现了问题再补救拆开,由于很多用户已经在使用了,要付出的开发成本和沟通成本也是极大的,甚至成为不可能。所以清晰的资源模型有利于梳理清楚API体系。
定义清晰的实体关系图有助于设计出更为完整的API
而且,明确的资源模型对于构建云上运维管理基础设施至关重要,例如可以通过对资源打Tag来对资源进行分类管理(参考阿里云资源Tag),分组授权(参考阿里云资源组),资源审计(参考阿里云CloudConfig),类似开源软件Terraform这样的编排工具,由于有资源模型会更容易接入和使用。
所以,统一的资源模型对云服务的帮助是巨大的:
它可以使API具有更清晰的结构,帮助用户理解
它可以帮助对比API与后台实体关系模型,更容易提供更完整的API服务
它可以使产品协作更加顺畅,对资源的操作也更加规范化
它可以使云服务底层平台实现起来更统一、更方便
它可以使围绕API的生态集成起来更加简单、高效
既然有这么多好处,那么众多的云产品在实际设计API的时候能否坚持以资源为中心,充分考虑到上下游的需求就变成一个很大的挑战了。
挑战3. API设计风格
确定了设计模式和资源模型后,是时候进入到API设计细节了。诸如API名称、参数名、属性名称、数据格式、错误码之类的信息,看起来根本不是问题。单个产品问题还不大,只要保证内部风格一致即可,如果考虑到云服务多产品对外的整体体验,就有必要考虑以下问题:
在API命名的时候,遵循什么样的范式来确保大体风格相似?动词、名词、介词如何组合才能保持API风格看起来比较统一,降低理解成本?
对于类似的操作,有没有使用规范?有哪些公共的标准词汇使得同类型的操作可以比较容易理解,避免使用晦涩奇怪的词汇?(例如读操作,Read/Query/Describe/List/Get中都在什么场合使用什么动词)
被广泛使用的参数如何尽可能保持一致,避免不同产品的表达混乱的情况?(例如分页参数用PageNumber还是PageNum)
对于常用的场景,例如幂等、分页、异步API的设计有没有统一的规范,避免使用体验不一致?
错误码应该怎么设计?公共错误码怎么统一,业务错误码怎么表达?
上述问题都是实际研发过程中要注意的,要全部罗列的话远不止这些。API的用词描述是云服务展现给外部用户的第一印象,绝非随意写就。对人员有一定规模,内部有多条产品线的组织来说,如何协调组织的各个部分对外具有统一的体验是个很大挑战。
回顾下HTTP协议,最广为认知的是对HTTP Mehod的约定,使用9个单词就完成了对基本动作的规范,为开发者提供了清晰的思维模型:
Http Method 类型
同样,在HTTP Header里面也对浏览器信息、语言、网络连接属性等做了详细的规定,这样开发者在使用HTTP服务的时候都有一个大致的约定,在关键信息上面不会有偏差,保障了异构系统的接口一致性。
因此云服务在管理API时应该考虑一些具体的规范,对命名规则、标准词汇、最佳实践模式、错误码等信息都有明确的规定,同时用系统化、平台化的手段来管理API,确保不走偏。设计风格不是云服务API设计中致命的问题,但是它关乎云服务外表形象,不可不察。
由于篇幅原因,下半部分内容将会以一篇单独的文章推出,敬请期待!!