目录
一、背景
二、Mooncake API文档维护
    1. API文档组织规范
        1.1 规范应用名称
        1.2 规范文档分类
    2. API文档生成
        2.1 MooncakeUpload Idea插件
            2.1.1 实现原理
            2.1.2 核心实现
            2.1.3 结果
        2.2 基于Gitlab MR自动解析
            2.2.1 背景
            2.2.2 实现
三、Mooncake API元数据中心
    1. 调试
    2. Mock
    3. API元数据平台
四、展望
背景
目前市面上针对API的管理平台很多,但由于各种客观因素,这些平台的功能都更多聚焦在API文档的消费侧。而对于API文档的生成都非常依赖开发人员的手动创建,很难保障文档的实时性和有效性。市面上常见的API管理平台,由于缺乏有效的管理机制,完全依赖开发人员的主动维护,在文档体量变大之后就出现了文档归属混乱、文档重复上传、文档信息更新不及时等问题。
由于文档缺乏有效的维护,很大程度上局限了API文档在消费侧的作用。举个例子,如果一份API文档更新不及时,那么前端就很难基于过时的文档进行数据Mock。如果平台大多数的文档都存在更新不及时的问题,那其他的平台也很难把平台的API文档作为有效信息使用。
Mooncake API文档维护

为了解决文档的维护问题,得物技术部自研了Mooncake平台,并从文档组织规范、文档生成效率等方面做了大量的尝试。

API文档组织规范
平台用户对于接口文档的存储管理、交付时间和交付质量均有一定的诉求。平台通过规范的方式统一起来,建立接口文档项目和目录组织规范,降低接口查找难度和用户使用费力度。
规范应用名称
如果应用名称可以任意创建,从技术部现有数据看来,各域定义的巨大差异将会导致用户使用存在一定的理解成本。为统一项目命名规范,同时更清晰的展示接口与项目之间的关系,平台计划与发布平台&CMDB&网关等系统保持一致,统一采用CMDB中的应用名作为项目名称,降低文档查找的难度。
通过打通CMDB数据,统一CMDB应用名,打通与公司内部平台的数据,主要包含:
  • 建立与发布平台的关系,自动获取应用染色环境列表,降低接口调试难度;
  • 建立与Gitlab平台的关系,自动获取应用需求迭代数据,降低文档与需求绑定的费力度;
  • 建立与网关平台的关系,一键同步接口网关自动关联路由组等数据信息;
  • 打通交易网关、APM的数据,获取接口文档信息,丰富文档信息密度。
通过将应用名称规范化,Mooncake平台建立了一个规范化的应用命名体系,让用户可以更方便地查找和使用文档,并提高了团队的协作效率和产品质量。
规范文档分类
如果以类名或注解作为文档分类的依据,导致文档的可维护性逐渐降低,文档和业务的关系也逐渐削弱。为了解决这个问题,平台通过规范文档的分类,降低文档的查找和管理难度。
  • 在技术层面上,提供多级分类能力,规范化维护文档分类,并完成商家、客服、供应链、交易等规范性分类的推动以及约束文档的落地;
  • 在规范层面上,推进各个团队根据自己的业务场景按照统一的规范来分类文档,从而提高文档的可维护性和管理效率。例如,推动客服、商家、交易等各个域落地接口目录规范文档,项目负责人或Owner定期检查分类规范的执行情况,并对分类不规范的文档进行整理和优化。
通过技术和规范手段相结合,规范文档分类,可以降低文档的查找难度,提升文档的可维护性和管理效率。
API文档生成
MooncakeUpload Idea插件
得物技术部研发的MooncakeUpload Idea插件可以帮助解决API文档创建和录入的问题。该插件通过解析Java项目里的注解和注释,实现了一键生成API文档的功能,降低了API文档创建的费力度。相较于手动创建接口文档,使用插件上传API文档所需的时间仅为几秒钟,而且规范了接口的分类属性,使得上传文档过程更加简便和快速。在每个迭代中,使用插件可以节约将近667小时的时间。
  1. 实现原理
基于IntelliJ Platform自身的基础架构,依靠PSI(Program Structure Interface)核心特性,通过分析解析出来的语法树可以获取准确的代码信息,例如获取文件中包含的类、方法、字段和注释等信息。
  1. 核心实现
  • 配置信息
通过IntelliJ Platform提供的虚拟文件系统(Virtual File System)功能,读取插件的信息配置,主要包括Mooncake的项目信息,人员的域账号等。从而能够获取Mooncake的分类数据,以及接口的变更人员。
// 解析misc配置文件File miscFile = new File(editor.getProject().getProjectFile().getPath());Element miscElement = JDOMUtil.load(miscFile);// 读取tokenpublic static String getToken(Element element, PsiFile psiFile) { try { String token = getHistoryConfig(element, psiFile, MooncakeConstant.HistoryToken); if (token.equals("")) { token = getProjectConfig(element, psiFile, MooncakeConstant.Token); } if (token.equals("")) { Messages.showErrorDialog("请先去idea/misc.xml配置MooncakeUploadApi配置", "获取配置失败!"); } return token; } catch (Exception e) { Messages.showErrorDialog("请先去idea/misc.xml配置MooncakeUploadApi配置", "获取配置失败!"); return ""; }}
原有的配置功能,会通过用户配置的项目名称信息和当前路径进行二次校验,增加了用户理解的难度,平台插件使用的问题中,80%的问题来源于配置的繁琐。因此在2.0版本之后,通过内置数据校验,降低了项目信息的配置难度,配置信息仅需一个参数即可
<component name="mooncakeUpload"> <option name="token">xxxxxxxx</option></component>
  • 出入参信息
依靠PSI核心特性,通过解析选中文件的语法树,提取字段信息,组装API文档的出入参和注释,主要核心逻辑:
// 获取偏移量PsiFile editorFile = e.getDataContext().getData(CommonDataKeys.PSI_FILE);PsiElement referenceAt = psiFile.findElementAt(editor.getCaretModel().getOffset());// 获取选中的类或者方法PsiClass selectedClass = PsiTreeUtil.getContextOfType(referenceAt, PsiClass.class);PsiMethod selectedMethod = PsiTreeUtil.getContextOfType(referenceAt, PsiMethod.class);// 获取选中类下的所有方法PsiMethod[] psiMethods = selectedClass.getMethods();// 获取类上的注解String apiValue = PsiAnnotationSearchUtil.getPsiParameterAnnotationParam(selectedClass, SwaggerConstants.API, "tags");// 获取参数所属类PsiClass psiClass = JavaPsiFacade.getInstance(project).findClass(psiParameter.getType().getCanonicalText(), GlobalSearchScope.allScope(project));// 获取参数所有字段PsiField[] fields = psiClass.getAllFields();// 字段源类型,可以获取所有信息PsiType type = field.getType();// 字段名称String name = field.getName();
  • 可视化面板
Mooncake平台支持API文档的多级分类,为了降低接口文档的分类难度,降低对代码的侵入,基于Java的Swing GUI库,我们提供了可视化操作面板,用户可以选择需要上传的接口和分类信息,以及需求信息。
  • 版本更新
MooncakeUploadApi上传插件是得物技术部自主研发的插件,由于存在公司的业务信息,无法上传到插件市场,只能将插件打包成Jar文件给开发使用。这种情况下,可能会出现以下问题:
  • 用户无法及时感知到插件修复过的版本,导致升级新版本时存在困难。如果出现问题,用户还需要找Mooncake维护人员定位问题,并进行手动修复和更新,维护成本比较高;
  • 由于不能上传插件市场,用户升级插件需要手动找到Mooncake维护的插件文档,并下载相应的Jar包进行更新,费力度高
针对以上可能存在的问题,得物技术通过搭建私有仓库方式,最终实现了插件更新方案,如图所示:
最终实现了插件启动的自动检查版本更新,并进行通知。
  1. 结果
通过自研Mooncake Idea上传插件,实现Mooncake平台以下收益:
  • 快速响应并定制化需求:通过打通Gitlab,插件可以根据代码分支来自动绑定接口的业务需求,以便快速响应相关问题;
  • 提升开发效率:使用插件可以大幅度降低API文档创建的成本和负担,从而让开发人员更加专注于代码的开发和测试等任务中;
  • 规范API文档:插件通过可视化面板交互方式,规范了文档的格式和内容,并能够快速选择上传的文档分类和字段信息,以便更好地管理和使用API文档信息,从而提高了规范化程度。
目前研发部门接通过插件每个迭代上传API文档的次数(如图所示),平均每个迭代产生数千次的变更,大大提升了维护文档效率,达到降本提效的目的
基于Gitlab MR自动解析
  1. 背景
平台提供了API Upload插件之后,整个文档生产端现状如下:
  • 服务端在开发阶段通过手动/插件上传API文档到Mooncake侧;
  • 提测节点时从网关同步当前迭代新增的API接口,与Mooncake侧接口比对,查看是否存在,不存在则要求开发上传接口。
通过网关来进行新增接口卡点,可能存在以下问题:
  • 网关侧配置的接口仅为需要走网关流量的接口,不走网关的接口,如Dubbo接口、内部接口并不能保证接口在Mooncake存在;
  • 即使在Mooncake存在的接口,如果在上传之后又产生了变更,通过网关的卡点并不能保证最新的变更也同步到了平台。
因此,平台通过上传插件降低API生成费力度的同时也需要将现有的研发流程仍然强依赖使用者的习惯API文档的质量不稳定的风险考虑进去。
针对这个问题,平台在Gitlab的流水线中,新增了一个自动解析代码的节点。对于每个向release分支合并的MR,将其中和接口定义相关的部分进行解析并自动在平台生成/更新对应的API文档,从而保证所有接口在发布前一定将最终的接口定义同步到Mooncake平台。
  1. 实现
  • 配置Gitlab流水线任务
    • 自动解析需要拉取项目的全量代码和依赖包代码,因此占用的内存空间较大;
    • 自动解析项目耗时较长,例如公司内部某个项目,7k+的文件需要耗时3.5min,自动解析feature分支消耗太多资源。
因此我们最终针对HTTP接口只做每个迭代的兜底,通过解析Release分支,保障每个迭代结束时,文档都是完整的和最新的。
  • 获取二方包源码
由于二方包在编译为Jar之后,代码的注释会丢掉,而API文档需要解析字段的注释和注解来描述字段的含义,自动解析要保证接口的完整性,需要补全二方包的注释。因此我们扫描了Pom文件的依赖包,并将公司的二方包全部下载到当前项目目录里面,并反编译解析原始数据。
获取公司内所有的二方包源代码数据
JSONArray allModuleDepsTreeData = new JSONArray();for (String fileDepTree : arrayListScannerMgr_Dep_Tree_POM) { JSONObject treeDependeces = dependcesParse(fileDepTree); allModuleDepsTreeData.add(treeDependeces);}// 过滤公司二方包 String group = nodeChild.getGroupId(); if (group.contains("xxx") || group.contains("xxxx") || group.contains("xxx") || group.contains("xxxx")) { return true; } // 下载所有二方包File tempFile = new File(jarScanPath.trim());String fName = tempFile.getName();fName = FilenameUtils.removeExtension(fName);fName = fName.replaceAll("-", "_");
  • 解析项目所有的代码
通过调研,Qdox工具包具备体积小,解析效率快,使用文档简单的特性,因此采用使用Qdox将项目中的所有代码解析为Java语法树,并实现API文档的信息提取。
核心逻辑如下代码所有,解析所有class,并基于Swagger注解和RestController注解提取所有的Http接口。
// 初始化builderJavaProjectBuilder builder = new JavaProjectBuilder();builder.setEncoding(StandardCharsets.UTF_8.name());// 读取所有class信息builder.addSourceTree(new File(sourceDir));Collection<JavaClass> classes = builder.getClasses();// 过滤所有http接口// 获取所有http api classCollection<JavaClass> httpClasses = new ArrayList<>();for (JavaClass javaClass : classes) { if (CommonHelper.isHttpClass(javaClass)) { httpClasses.add(javaClass); }}
而接口文档信息的解析与Idea插件解析思路基本一样,最终将所有的接口方法解析为JSON格式的API文档,如图所示:
  • 将解析的接口数据与Mooncake平台数据对比
    • 接口在Mooncake不存在的,直接上传到Mooncake平台,保证API文档的完整性;
    • 接口存在的,比对接口文档核心数据,包含出入参和路径等,不一致则更新接口文档,保证API文档的一致性。
Mooncake API元数据中心

Mooncake平台通过不断完善从生产到消费链路的信息,延长API文档的生命周期,完成API文档元数据中心的闭环。在平台的探索过程中,逐渐沉淀了丰富API文档信息,解决了API的利用率低API信息密度低的问题。目前,API信息主要包含以下:
  • API描述信息:如 Swagger、OpenAPI 等格式的 API 描述文件,包括 API 名称、版本、路径、参数、响应等;
  • 接口规范:定义API请求和响应协议,规范接口分类;
  • 稳定性:API的版本管理、生命周期、周期变更率等数据;
  • 文档和示例:API的使用文档、示例代码、调用等;
  • 开发平台:提供API开发者所需的工具和SDK,例如IDEA插件、Go cli等;
  • 研发流程规范:提供接口版本周期稳定性数据,例如:调试是否成功、自动化测试用例等。
通过打造得物API元数据中心,更有效的提高API开发和管理效率,使得API能够更加透明化、可靠化、易于使用。基于丰富的API文档信息,平台围绕调试Mock、数据开放等API消费侧的功能也做了大量的探索尝试
调试
由于平台沉淀了精确的接口字段定义,因此基于这些定义对接口进行调试自测就非常方便。在提供基础调试功能的同时,平台也通过以下手段对调试的体验进行了优化:
  • 基于文档信息,自动填充入参字段信息;同时基于文档信息进行简单的类型校验;
  • 通过同步CMDB应用名称,自动获取染色环境名称,支持调试自动填充染色环境参数;
  • 打通内部核心平台,优化接口签名和鉴权问题,降低接口调试难度。
对于部分仍然习惯于使用postman进行调试的用户,平台也支持将postman调试记录进行一键同步。
之所以这么执着的推动大家到Mooncake来进行调试,主要是期望将调试记录作为研发完成自测的一种“凭证”,并将其同得物现有的研发协同面板系统进行结合,把“自测凭证”作为生成前后端联调单的前置条件,通过保障联调过程中的接口质量从而提升联调效率。
整个联调过程大致如下:
Mock
  • 由于项目接口的完整性和及时性,前端可以基于平台的Mock功能,在开发阶段,前端可以Mock需求下的所有接口,充分完成功能的自测,前置联调流程,降低因为后端延迟提供接口的带来延期的风险。
  • 基于入参字段的准确性和完整性,在Mock数据过程中,平台可以校验入参的信息的准确性,包括是否完整,数据入参类型是否准确等,提前发现问题,提升前端交付质量。
  • 通过API文档的调试功能,平台沉淀了基于接口文档的真实数据,因此,平台可以自动为前端提供更加精准的具备业务属性的数据Mock,以及不同的异常状态码数据场景,更加真实对页面场景进行还原。
API元数据平台
将公司所有的API文档收敛到Mooncake平台,通过保障接口的完整性和及时性,可以保障所有消费平台都能拿到接口的详细信息,同时通过与其他平台协作,将接口的不同维度信息收敛到平台信息,例如接口的等级、读写属性等,丰富文档的信息密度。
通过提供OpenApi,为公司内部平台提供API信息,例如:
  • 提供API文档包括接口名称,字段语义,出入参完整性给APM监控平台,提升Trace链路的可读性;
  • 提供完整的出入参信息,与流量平台的接口数据比对,及时发现接口版本问题;
  • 提供接口的变更率、是否调试成功等数据给提测平台,作为质量管控数据面板的一部分;
  • 提供接口相关联的域名信息给网关平台,作为网关平台监控接口流量信息的依据;
  • 将接口信息提供给接口自动化平台,可以提升测试编写接口测试用例效率。
展望
目前得物面对日益增长的业务,尤其是涉及分布式架构、微服务等技术和架构时,通过API元数据中心集中化管理API接口文档,在协同管理各团队、保证接口的一致性和完整性、快速演进变更、降低沟通成本等方面有着至关重要的作用。后续,平台依然会围绕已经沉淀的API信息,在接口自动化测试、API文档管理、接口健康度监控等上下游领域进行持续的探索。
继续阅读
阅读原文