作者简介

章鱼, 携程资深后端开发工程师,契约系统创始人与核心研发。

Sylar, 携程资深研发经理,专注Java技术栈相关研究。

一、前言

随着微服务化在携程的全面落地,业务被拆解得越来越细,接口数量和内外部调用方不断增多;另一方面,随着产品迭代的不断增速,对接口的修改也变得愈加频繁。

接口契约,作为各端的沟通桥梁,在微服务时代显得尤为重要。如何管理好不断变化的接口契约,是携程机票BU在微服务化过程中遇到的一大难题。本文结合一些契约管理的实践经验,介绍下携程契约管理的演进,以及携程机票BU自研发的契约系统(简称MOM - model object management,以下都以此代替)。

二、携程契约管理演变史

2.1 线下管理契约

在携程机票BU以及其它的一些团队里,早期的契约管理,主要由程序员线下进行。当发生需求变更,需要增加新的接口,或改动原有契约时,由相应的开发线下编辑契约文件(如XSD文件),再生成指定格式的契约(如Java类,Protobuf文件),提供给使用方。

在单体应用时代,或业务没有拆分很细的时候,接口契约并不会太多,调用方也相互熟悉,只要有专人负责线下契约维护,这种管理方式并不会有太大问题。但随着微服务化,接口和契约不断增多,此种管理方式的瓶颈逐渐凸显,问题主要集中在以下几点:

1)线下管理,契约容易丢失。

2)契约变更,只有编辑者才能主动感知,无法很好的周知到所有使用方。若契约变更不当,容易在上线时才发现问题。

3)当有多个需求,需要对同一份契约进行修改时,需手工解决各种冲突,这个过程极易出现问题。就好比不用Git,手工去进行代码分支管理一样。

4)契约可读性差,接入沟通成本大,各团的原始契约也没有一个统一的标准。

2.2 第三方工具管理契约

由于线下契约管理,存在太多各式各样的问题。携程内部各团队都在积极探寻,尝试借助一些第三方工具,去更好地管理契约。常见的有Swagger、Knife4j、YAPI等工具。

Swagger是一款非常受欢迎的开源框架,它通过文档与代码的绑定,能很好地对API进行文档化描述,接入起来也比较方便。Swagger一定程度解决了线下管理契约易丢失、可读性差等问题。但由于Swagger单机或集群的契约管理方式,会使得携程内部各项目(应用)之间,显得比较割裂,所以Swagger并未在携程内部大范围推广。同时,Swagger的界面比较粗糙,文档的编写需要遵守一系列的规范,上手有一定难度。

Swagger

Knife4j是一款国产开源项目,也是用于API文档的生成。与Swagger相比,它有着更加出色的界面,并且能够支持如离线文档、安全控制、在线调试等功能。但是与Swagger有相同问题,Knife4j并不是一个中心化的契约管理方案。

Knife4j

YAPI是去哪儿为推进API标准化,研发的一款API治理工具。本身也拥有丰富的功能,携程内部也有一些团队在使用,但它的设计更注重于API的多样化管理,不支持模型共享,不支持单独模型聚合方式管理,必须要有接口名称和输入输出信息。这些限制给契约的管理带来不少麻烦。

YAPI

总的来说,Swagger、Knife4j和YAPI,将契约管理方式从线下转到了线上,一定程度解决了契约易丢失,可读性差的问题,同时还提供一些API管理的高级功能,如调试、Mock等,那为什么还需要MOM呢?

2.3 为什么研发MOM

携程机票BU结合自己的实践经验,并走访收集了其它团队在契约管理上的痛点,总结出一款好用的契约管理系统,所应当具备的功能有:

1)云端管理,项目、权限管理

2)友好的界面,支持在线编辑

3)版本管理,差异比对

4)契约变更消息通知

5)契约导入,代码生成

6)模型共享

由于Swagger、Knife4j以及YAPI,对以上功能的支持或多或少有缺失,而且它们都是以面向API管理为主,并不能很好地解决上述问题。携程机票BU开始尝试研发MOM,并在近一年内陆续在携程内部推广开来。

契约系统又称为MOM(model object management),从名字就能看出,其管理的是模型对象。这个设计理念也是与Swagger,YAPI等工具面向API做管理的最大不同。

模型,无关于接口实现,无关于契约文件类型,也无关于具体生态环境,它仅由字段组合而成。在MOM中,模型作为被管理的最小单位,可以进行任意的组合与嵌套,通过这种结构化的管理方式,使得契约的描述性更加强大,突出表现在能够模型共享上。

模型管理这一理念,其实也是源于携程机票BU的实践经验。在2017年左右,携程服务端的技术栈从.Net转向Java,前端有iOS、Android、React Native、Hybrid等技术栈,一个接口对应了多份契约文件。同时,随着微服务化的深入,接口数量也暴发式增长,我们发现很多接口契约的部分内容是可以复用的,例如航班信息,主要就包含了航班号,出发到达地,机型等信息。

为了解决一份契约会有不同的文件格式,以及契约复用的问题,MOM设计之初就抽象出模型这一概念,并将其作为底层设计的核心思想,这也使得MOM之后具有良好的扩展性,所有其它工具支持的功能,理论上MOM都能支持。

总的来说,Swagger,Knife4j和YAPI主要关注的都是对API的管理,而MOM更加关注的是对契约的管理。

三、MOM架构

MOM作为一个帮助大家管理契约的工具,在使用频率方面,并不会太高,并发压力不会太大。研发时更侧重于其功能的丰富性。所以,整体的物理架构不是很复杂,但支持的功能以及逻辑单元相对丰富,且留有很好的扩展性。

3.1 物理架构

MOM采用双集群进行灾备,使用MySQL管理模型、项目、版本等结构化数据,Mongo用于管理用户上传的原始文件及最终生成的契约文件。系统采用Local Cache + Redis的二级缓存结构进一步降低DB的访问压力,同时用Zookeeper保证各台机器的数据一致性,可能发生变更的静态数据由Schedule定时进行更新。整个系统使用传统的MVC架构进行设计,前端页面使用Angular搭建,服务使用Java进行开发。

3.2 逻辑单元

从以上的逻辑单元可以看出,MOM主要包含的功能有:项目管理,契约编辑,多版本管理,契约生成,变更通知,以及底层的核心:模型管理。后面会对这些功能进行展开介绍,分享这些功能的相关经验。

四、MOM功能介绍

4.1 契约编辑

契约编辑主要分为两块,契约导入和在线编辑。

4.1.1 契约导入

契约导入,顾名思义是将现有的契约,可以是各类契约文件,导入到系统中, 方便后续的查看和修改。这功能的必要性有一定历史原因,因为各团队维护契约文件的方式都不相同,契约文件类型存在差异,要想后续都在MOM上进行管理,就必须提供这么一个功能方便各方快速接入。

之前也提到过,MOM的核心理念是管理模型,不是具体的接口或契约类型,这一层抽象使得契约导入功能能够很方便的实现,需要支持什么类型的契约导入,开发其相应的文件解析器,将契约文件转换成MOM底层维护的模型即可。

契约导入完成后, MOM界面上统提供树形结构与扁平化的展示方式,方便用户直观看到契约模型的相关信息。目前,MOM支持BJSC(携程SOA契约),Protobuf,XSD,Json Schema等契约文件的导入。后续若要支持更多契约类型,也能很快地进行扩展。

4.1.2 在线编辑

在线编辑是MOM的特色之一,对于历史契约,在用户完成契约导入后,MOM会将用户的契约模型持久化下来。对于新接口新契约,MOM也支持在界面上直接进行创建。后续,当接口需要扩展功能,修改契约时,MOM支持在界面上直接修改并保存。界面上友好的契约修改操作流程,避免了人工编辑契约文件可能带来的问题。

值得一提的是,对契约的编辑修改有一项Best Practice:对于已发布的契约,后续的修改只能是顺序增加字段,不能修改现有字段的名称和类型,也不能在任意位置插入新字段。因为,修改已有字段的名称和类型,必定会带来线上兼容性问题;要求顺序增加字段,主要是针对像Protobuf这类对顺序有强要求的契约格式。那字段越加越多,越来越冗余怎么办?可以考虑另起炉灶升级接口契约,或尝试GraphQL。

4.1.3 契约编辑小结

契约导入和在线编辑是MOM的一大特色。这功能有别于其它工具,因为Swagger、Knife4j、YAPI都是面向API做管理,或与代码绑定不支持导入编辑,或只支持从Postman等工具导入接口。这与MOM专注契约的管理,有本质上的不同。契约可以看作是API的进一步抽象,MOM导入和编辑的是契约,而不是API。

当契约导入后,或完成编辑保存后,数据是以模型进行管理,在MOM上,模型到契约间的转换是双向的。举个例子,导入的是XSD格式契约,MOM将其转成模型进行存储,最终在界面上,MOM又可以将模型转换成各类契约格式,进行展示。

4.2 项目管理

MOM中的契约模型,是以项目维度进行管理,项目分为应用与自定义项目。

应用是携程内部的定义,可以包含一组接口,通常也是生产发布的最小单位。通过这种直接与应用一一绑定的方式,可以方便用户快速查找自己应用的契约。

自定义项目与应用的差异,主要在于管理模型的差异上。自定义项目更多用于,存储共享模型、数据埋点模型等, 它们可以脱离携程的生态环境而存在。值得一提的是,模型在不同的项目下是相互隔离的,原则上一个项目只能使用该项目下的模型,如果想要跨项目使用模型,必须先建立项目之间的绑定关系。

为了降低契约被项目成员之外的用户误操作,MOM提供了权限管理,权限实际是建立在应用维度之上的。MOM会定时同步应用权限(谁是Owner、管理员),只有拥有这些角色的用户才允许编辑该项目下的契约模型。

4.3 模型管理

模型管理,是MOM底层的核心。模型是最小的管理单元,契约的节点树是在此基础上进行嵌套搭建的。MOM维护了基础数据类型,除此之外系统允许用户定义自定义模型和枚举类。

MOM参考了Java的设计,项目以文件夹形式进行管理,模型所处的文件路径,决定了模型最终的生成位置。为了更好的进行模型描述,MOM对模型抽象出了模型名称、字段、描述、注解等相关属性,通过构建绑定关系使得共享策略得以生效。

契约系统的模型共享,主要分为项目间的共享与外部jar包内的模型共享。项目间的主要使用场景是,用户构建自定义项目维护共享模型,该模型可以被其他项目中的接口访问,来避免触发冲突规则。外部jar包引用,是通过同包下的同名模型进行相关的替换操作,系统解析maven仓库中jar包中的原始文件, 提取类型的节点树信息,替换项目中的模型。

4.4 多版本管理

多版本管理是契约管理的一个重要组成部分。

之前提到,由于需求的快速迭代,团队协作中,契约不可避免的产生多个可编辑的版本。MOM为多个版本提供了相互隔离的环境,并且提供回滚,增量覆盖全量覆盖的相关功能。需要注意的是,版本在发布之后是不允许进行编辑操作的。但是多版本隔离的同时会带来冲突的合并问题,如何解决多版本冲突,提升契约的稳定性更是重中之重。为了解决稳定性问题系统先后提供两种解决方案,其一是版本比较,其二是版本冲突的自动合并。

4.4.1 多版本比较

如何帮助用户更快的发现契约的变更,除了契约变更通知这一种手段外,系统自定义了相关的比较规则,降低用户比较的费力度。核心思路是减少比较内容,突出差异信息。

因为契约的生成格式可以是多种多样的,如果是对每一种生成格式都提供一套比对方案虽然能满足各方的需求,但是必然给系统的维护带来一定的挑战。前文提到系统使用结构化的模型管理,那么是否能提供一种可读性良好,同时能突出展示差异的解决方案?答案是有的。

结合目前线上在使用的契约,参考多方的契约处理格式,最终系统仿照Protobuf的文件定义出模型及接口的比较模板,针对用户关心的主要数据,提取出:字段名、字段别名、注释、模型等相关属性。使得用户比较时可以更直观的发现契约的改动。

当然系统也提供了生成文件的比较,如Java文件,方便特定的用户进行比较。如果有需要,后续也会对其他的格式逐步增加比对支持。

4.4.2 版本冲突自动合并

版本比较一定程度上帮助用户发现问题,但冲突合并才是解决问题的关键。能否支持冲突合并,成为考量系统易用性的重要标准。

契约的冲突合并,与代码的冲突合并类似,每当契约需要进行正式发布时,都应检查在其之前是否已有其它修改发布了。若有,则需解决可能引入的冲突。冲突的类型可能是新增类型,或者对某个模型的字段的修改,这些变更如果遗漏,显然是致命的。

针对该问题,系统参考Git的文件管理规则进行设计。契约合并的时机,发生在用户即将发布正式的契约版本时,系统自动拉取最新的发布版本与当前的发布版本进行比较,并做冲突展示,由用户选择解决冲突的方式,允许用户忽略冲突发布,当然相应的结果由用户承担。冲突的自动合并,降低了手工操作犯错的几率,极大的提升了团队协作效率。

4.5 契约生成

契约生成是大多数用户比较关心的地方。能否满足各用户的使用场景,对系统而言也是一个重大挑战。

契约系统独立维护了一套描述性极强的模型结构,对于不同的生成契约类型,只需要根据不同契约的生成规则,定制不同的契约模板即可。随着系统的不断迭代,目前已经支持Java、TS、GraphQL、C#、XSD、Protobuf等文件的生成。

此外,光生成契约文件对于用户来说,易用性可能还不够。MOM还支持将生成好的契约,直接发布到代码仓库。目前,MOM已支持直接将契约部署到maven和NPM(Node Package Manager)仓库,只需简单配置仓库地址即可。至此,契约的编辑到部署,可以全在MOM的操作界面上完成,这极大的提高了开发效率。

4.6 变更通知

MOM不仅方便了契约维护方对契约进行管理, 也方便了接入方能够很好的查看接入。当契约发生变更时,将变动消息告知所有的关心此契约的人,是很有必要的一个功能。

MOM的通知包含变更通知、发布通知。通知的渠道可以是各式各样的。通知的范围包含项目的管理员、owner、项目的关注人以及项目的调用方。契约系统会把用户的每一次编辑记录进行收集作为后续的通知内容,并把契约的改动可能影响的潜在用户列入通范围。此外,通知内容上提供ReleaseNote的编辑方式,用户编辑完成之后可以选择需要通知的对象及通知的方式进行通知操作。

目前,MOM的消息通知渠道,主要包括Trippal(携程内部通讯工具) 和Email。系统预留了可扩展性,若需其它渠道的消息通知,可以快速进行开发或配置。

五、总结

总的来说,MOM与其它工具最大的不同,是其更关心契约的管理。特别是在敏捷模式盛行的今天,业务变更快速而频繁,不可避免的经常对契约进行修改。如何管理并支持好这些修改,是MOM这个产品需要解决的核心问题。

目前,MOM在携程内部正处于推广阶段,功能也在不断的增强与完善中。后续会考虑剥离携程相关生态的依赖, 在契约导入、契约生成、消息通知等功能上, 做到可插拔可扩展。最终开源到社区,帮助大家解决契约管理的问题。

最后:

  • 如果你维护的项目多,接口契约经常发生变化

  • 如果你的接口文档不清晰,甚至还是线下维护的方式

  • 如果契约模型需要在各项目,各接口间共享

  • 如果你需要生成各式类型的契约,提供到使用方法

  • 如果你有多个团队共同维护一个项目, 契约修改经常冲突

  • 如果你想把契约的变更,及时通知到各个关注方

那你可以参考MOM以模型为中心的契约管理方案,也可以持续关注MOM的后续消息。

【推荐阅读】

  • 代理模式Mock平台在携程的应用

  • 前端跨端业务整合的探索与实践

  • 单周多发场景下,携程机票基于Light Merge的自动化分支管理策略

  • 响应式设计在携程火车票的应用

 “携程技术”公众号

  分享,交流,成长

干货 | 以模型为中心,携程契约系统的演进相关推荐

  1. UED专栏 | 带你认识携程插画系统1.0

    本文作者为携程平台UED团队,同时感谢机票.度假.酒店UED团队协同搭建插画系统. 对于每一个设计师来说,插画总是让人喜爱又烦恼.喜爱是因为插画具有特殊的表现力.丰富的图形语言.鲜明的个性特征,运用在 ...

  2. 干货 | 万字长文详解携程酒店订单缓存 存储系统升级实践

    作者简介 荣华,携程高级研发经理,专注于后端技术项目研发管理. 军威,携程软件技术专家,负责分布式缓存系统开发 & 存储架构迁移项目. 金永,携程资深软件工程师,专注于实时计算,数据分析工程. ...

  3. 干货 | 数据为王,携程国际火车票的Sharding-Sphere之路

    作者简介 瑞华,携程高级后端开发工程师,关注系统架构.分库分表.微服务.高可用等. 一.前言 随着国际火车票业务的高速发展,订单量快速增长,单数据库瓶颈层面的问题逐渐显露,常规的数据库优化已无法达到期 ...

  4. 干货 | 支持10X增长,携程机票订单库Sharding实践

    作者简介 初八,携程资深研发经理,专注于订单后台系统架构优化工作:JefferyXin,携程高级后端开发专家,专注系统性能.业务架构等领域. 一.背景 随着机票订单业务的不断增长,当前订单处理系统的架 ...

  5. 干货 | 提升前端工程化,携程 Design2Code 从零到一的实践

    作者简介 by,携程高级研发经理,专注低代码平台搭建和前端智能化技术. Jialu,携程研发总监,专注大前端技术和工程化的研究与发展. 一. 背景 在软件开发过程中,团队协作效率的提高是我们共同关注的 ...

  6. 干货 | 节省55%测试时间,携程酒店比对平台介绍

    作者简介 黄文杰,携程酒店研发部高级测试经理,主要从事测试框架和平台的研发,现在负责自动化与工具平台,热衷于研究技术提升测试工作效率. 一.前言 当初我们为什么想到要开发比对平台,主要遇到以下几个问题 ...

  7. 干货 | 终于来了!携程开源RN开发框架 - CRN

    作者简介 赵辛贵,携程无线平台研发部开发总监.2013年加入携程,主要负责App基础框架研发相关工作,曾参与Native.Hybrid和React Native框架设计.工程模块化.Android插件 ...

  8. 干货 | 响应式设计在携程火车票的应用

    作者简介 永利,携程开发经理,专注于Web领域的探索. 一.什么是响应式设计? 可能很多人脑海中已经出现了这样一个动画,当浏览器中页面尺寸不断变化时,内容也在随之变化.简单说,响应式网站设计是一种允许 ...

  9. 订单失效怎么做的_携程旅游系统崩溃?济南一市民遭遇“钱已付,酒店订单不存在”...

    10月2日晚间,有多名网友发布微博,称通过携程APP预订酒店,付款后显示订单不存在,系统疑似崩溃."我在携程APP上预订的酒店,银行卡的钱已经扣了,可携程订单显示'该订单已失效'." ...

最新文章

  1. npm 常用命令详解
  2. lua 多条件_【LUA】只需花费你半天时间
  3. Java多线程-线程状态
  4. 流星,刹那间划过天际
  5. 领域应用 | OMAHA联盟发布“疾病临床表现”、“中毒”知识图谱及OMAHA知识库
  6. .net微信公众号开发——基础接口
  7. Python利用openpyxl来操作Excel(一)
  8. 2020年最好用的手机是哪一款_2020,哪款5G手机最值得入手?
  9. zookeeper 进入客户端_Zookeeper基础知识简单介绍
  10. 接口与interface关键字
  11. Qt编写的RTSP播放器+视频监控(android版本)
  12. 51单片机c语言教程第二章,51单片机C语言教程-郭天祥-PDF转word版第二章.pdf
  13. wlan 网速测试软件,WiFi大师网速测试
  14. Hadoop大数据环境搭建保姆级教程(完整版)
  15. 查询linux ssh端口,查看ssh端口
  16. 使用JavaScript进行iframe的DOM操作
  17. day11_rabbitmq和redis
  18. 第四章USB数据流模型
  19. 教育培训机构屡遭投诉?湖南中创教育给出三点建议
  20. android判断是否json格式,简单方法判断字符串是否是json字符串

热门文章

  1. 使用MDC增强日志记录
  2. shiro保护你的应用程序
  3. 安全生产预警管理系统
  4. 如何使IOT2050成为PN设备
  5. 新高考3+1+2模式(4选2)全走班自动排课系统7.0(正式版)
  6. 工具mysql5.528特点_未来主力 试驾全新宝马5系528Li
  7. 车文化:1.BMW车型概览
  8. 如何记账,导出账目到表格
  9. python中大批量m3u8文件合并总结
  10. ElasticSearch自定义pinyin和ik分词库