新闻资讯

新闻资讯 媒体报道

GraphQL及元数据驱动架构在后端BFF中的实践

编辑:001     时间:2021-05-06

整体架构由三个核心部分组成:

  • 业务能力:标准的业务逻辑单元,包括取数单元、展示单元和查询模型,这些都是关键的可复用资产。
  • 元数据:描述业务功能(如:展示单元、取数单元)以及业务功能之间的关联关系,比如展示单元依赖的数据,展示单元映射的展示字段等。
  • 执行引擎:负责消费元数据,并基于元数据对业务逻辑进行调度和执行。

通过以上三个部分有机的组合在一起,形成了一个元数据驱动风格的架构。


新架构提供了一套基于业务抽象出的标准化代码分解约束。以前开发同学对系统的理解很可能就是“查一查服务,把数据粘在一起”,而现在,研发同学对于业务的理解及代码分解思路将会是一致的。比如展示单元代表的是展示逻辑,取数单元代表的是取数逻辑。同时,很多冗杂且容易出错的逻辑已经被框架屏蔽掉了,研发同学能够有更多的精力聚焦于业务逻辑本身,比如:业务数据的理解和封装,展示逻辑的理解和编写,以及查询模型的抽象和建设。

1)展示服务颗粒度设计问题

这种方案要求展示逻辑和取数逻辑封装在一个模块中,形成一个展示服务(Presentation Service),如上图所示。而实际上展示逻辑和取数逻辑是多对多的关系,还是以前文提到的例子说明:

背景:有两个展示服务,分别封装了商品标题和商品标签的查询能力。

情景:此时PM提了一个需求,希望商品在某个场景的标题以“[类型]+商品标题”的形式展示,此时商品标题的拼接依赖类型数据,而此时类型数据商品标签展示服务中已经调用了。

问题:商品标题展示服务自己调用类型数据还是将两个展示服务合并到一起?

以上描述的问题的是展示服务颗粒度把控的问题,我们可以怀疑上述的示例是不是因为展示服务的颗粒度过小?那么反过来看一看,如果将两个服务合并到一起,那么势必又会存在冗余。这是展示服务设计的难点,核心原因在于,展示逻辑和取数逻辑本身是多对多的关系,结果却被设计放在了一起

2)数据图划分问题

通过GraphQL将多个展示服务的数据聚合到一张图(GraphQL Schema)中,形成一个数据视图,需要数据的时候只要数据在图中,就可以基于Query按需查询。那么问题来了,这个图应该怎么组织?是一张图还是多张图?图过大的话,势必带来复杂的数据关系维护问题,图过小则将会降低方案本身的价值。

3)展示服务内部复杂性 + 模型扩散问题

上文提到过一个商品标题的展示存在不同拼接逻辑的情况,在商品展示场景,这种逻辑特别普遍。比如同样是价格,A行业展示优惠后价格,B行业展示优惠前价格;同样是标签位置,C行业展示服务时长,而D行业展示商品特性等。

那么问题来了,展示模型如何设计?以标题字段为例,是在展示模型上放个title字段就可以,还是分别放个titletitleWithCategory?如果是前者那么服务内部必然会存在if…else…这种逻辑,用于区分title的拼接方式,这同样会导致展示服务内部的复杂性。如果是多个字段,那么可以想象,展示服务的模型字段也将会不断扩散。

总结:后端BFF模式能够在一定程度上化解后端逻辑的复杂性,同时提供一个展示字段的复用机制。但是仍然存在未决问题,如展示服务的颗粒度设计问题,数据图的划分问题,以及展示服务内部的复杂性和字段扩散问题。目前这种模式实践的代表有Facebook、爱彼迎、eBay、爱奇艺、携程、去哪儿等等。

在实现层面,同样基于元数据描述展示字段和展示单元之间的关系,基于以上的设计思路,可以在一定程度上减缓模型的扩散,但是还不能避免扩展。比如除了价格、库存、销量等每个商品都有的标准属性之外,不同的商品类型一般还会有这个商品特有的属性。比如密室主题拼场商品才有“几人拼”这样的描述属性,这种字段本身抽象的意义不大,且放在商品查询模型中作为一个单独的字段会导致模型扩张,针对这类问题,我们的解决思路是引入扩展属性,扩展属性专门承载这类非标准的字段。通过标准字段 + 扩展属性的方式建立查询模型,能够较好地解决字段扩散的问题。

4.2.3 元数据驱动架构

到目前为止,我们定义了如何分解业务逻辑单元以及如何设计查询模型,并提到用元数据描述它们之间的关系。基于以上定义实现的业务逻辑及模型,都具备很强的复用价值,可以作为业务资产沉淀下来。那么,为什么用元数据描述业务功能及模型之间的关系呢?

我们引入元数据描述主要有两个目的:1)代码逻辑的自动编排,通过元数据描述业务逻辑之间的关联关系,运行时可以自动基于元数据实现逻辑之间的关联执行,从而可以消除大量的人工逻辑编排代码;2)业务功能的可视化,元数据本身描述了业务逻辑所提供的功能,如下面两个示例:

团单基础售价字符串展示,例:30元。 

团单市场价展示字段,例:100元。

这些元数据上报到系统中,可以用于展示当前系统所提供的功能。通过元数据描述组件及组件之间关联关系,通过框架解析元数据自动进行业务组件的调用执行,形成了如下的元数据架构:

著名计算机科学家David Wheeler说了一句名言,"All problems in computer science can be solved by another level of indirection"。没有加一层解决不了的问题,本质上是需要有人来对这事负责,因此我们在原生GraphQL之上增加了一层执行引擎层来解决这些问题,目标是屏蔽GraphQL的复杂性,让开发人员只需要关注业务逻辑。


郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

回复列表

相关推荐