15

减少重复开发,GraphQL在低代码平台如何落地?

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzI0MjczMjM2NA%3D%3D&%3Bmid=2247492490&%3Bidx=1&%3Bsn=8acc355974bb8bd10b6324bc4c324e68
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

2015年,Facebook推出了GraphQL(Graph-Query-Language)查询语言。到目前为止,IBM、Twitter、Walmart Labs、纽约时报、Coursera等很多公司已经在内部从 RESTful转向GraphQL API

作为一种查询语言,GraphQL具有以下特点:

(1)无需关心如何更新文档,所有的查询(query)和变更会 自动形成文档(cchema)

(2)无需获取整个数据集,通过 schema与resolver(处理器) 之间的映射关系,由对应的resolver去获取数据,将结果返回给前端,从而可以编写仅仅返回所请求数据的查询。

(3)对前端提供统一的访问点。从不同的API中获取数据并非易事,GraphQL 支持将所有API进行拼接

爱奇艺号技术团队在实施微服务化的过程中,受到Forrester Research提出的 低代码开发(Low-Code:即无需编码或通过少量代码就可以快速生成应用程序的开发理念) 的启发,基于GraphQL构建BFF(Backend for Frontends),帮助开发人员用拖拽式操作,直观地创建出一个 供前端调用的 API,本文将对实施过程中的经验总结进行叙述。

GraphQL介绍

与 RESTful API 一样,GraphQL API设计用于处理 HTTP 请求并为这些请求提供响应。REST API 构建在请求方法和端点之间的连接上,而 GraphQL API 被设计为只通过一个端点,始终使用 POST 请求进行查询,其 URL 通常是xxx.com/graphql。图1-1为GraphQL部署架构图,可以看到它处于 系统“中间层”

BfIBRje.png!mobile

图1-1

GraphQL 全称叫 Graph Query Language,官方宣传语是 “为你的 API 量身定制的查询语言” ,用传统的方式来解释就是:将你所有后端 API 组成的集合看成一个数据库,用户终端发送一个查询语句,你的 GraphQL 服务解析这条语句并通过一系列规则从你的“API 数据库”里面将查询的数据结果返回给终端,而 GraphQL 就相当于这个系统的一个查询语言,像 SQL 之于 MySQL 一样。GraphQL执行过程如图1-2所示:

YRjAvuR.png!mobile

图1-2

图1-2是GraphQL 执行的大致流程, 第一步 去验证查询语句是否符合GraphQL的schema规范,确认查询内容的合法性, 第二步 生成执行的上下文,关键点在第三步和第四步, 第三步 是获取查询语句所需要查询的字段,这里叫 fields,所有需要查询的字段可以在查询语句里拿到,这就是 GraphQL 如何做到避免返回冗余数据的。拿到所有需要查询的字段后, 第四步 针对每一个字段去执行它的 resolver,可以从 resolver 返回的数据里面拿到字段对应的数据,最后是格式化结果并返回。

重点是第四步,展开说明一下,如图1-3、图1-4所示:

jaMnA3Q.png!mobile

图1-3

qA7jYrb.png!mobile

图1-4

在GraphQL里面有一个概念叫类型 (type),每一个类型下面对应的是一个或多个字段(field),每个字段都会绑定一个处理器(resolver),这个 resolver 的作用就是 获取字段对应的数据

对应到图1-4所示,UserInfo这个类型,它有三个字段:nickName、contractNo、fansNumber。每个字段都对应一个resolver,resolver 需要被开发者重新定义,否则会报错。所以UserInfo下的三个字段nickName、contractNo、fansNumber需要通过实现各自resolver来分别从用户微服务、合同微服务、粉丝微服务去获取用户信息、合同信息和粉丝信息,然后再聚合返回,这样就达到了 使用 GraphQL 进行数据拼接的目的

BFF架构

爱奇艺号在实施微服务化的过程中,加入了BFF的前后端架构,如图2-1所示:

nEbmUzu.png!mobile

图2-1

从图中可以看出,BFF作为前后端的中间层服务。主要的业务逻辑都封装在BFF层,前端通过BFF进行访问,减少微服务之间的相互调用。BFF层通过REST API方式提供服务,随着服务的增多,提供的接口越来越多,这会导致REST API越来越冗余。对于前端而言,有的API粒度较粗不满足需求;有的API又粒度太细,不仅增加了响应时间,还会造成流量的浪费。对于后端而言,前端需要的数据往往在不同的地方具有相似性,但却又不尽相同,比如:针对用户信息,有些地方需要用户简要的基础信息和详细的视频信息,而有些地方却需要用户详细的基础信息和简要的视频信息。这往往需要开发不同的接口去满足各种定制需求,增加了开发人员的工作量,提升了开发工作的重复度。

  • GraphQL与Rest API对比:

    性能

    文档

    调试

    学习成本

    GraphQL

    性能好,申明式获取,非常直观和精准,减少不必要数据网络传输

    代码即文档

    前端能快速感知,强类型,避免出错

    Rest API

    缺乏弹性,大多数情况会获取额外数据

    使用 Swagger

    后端配合排查

表2-1

从表2-1中的对比可以看出,GraphQL相对于Rest API方式,性能更好,能有效减少前后端开发沟通成本。但是Facebook的官方只有JS版本实现,查询方式和Rest API也有所不同(如表2-2所示),对于老项目有一定的迁移、学习成本。

mai63uV.png!mobile

表2-2

接下来,本文将主要探讨如何基于graphql-java,做到减少迁移成本的同时,又能提升后端开发人员的效率,避免重复开发。

爱奇艺号API生成平台实践

爱奇艺号API生成平台,是一个低代码平台。 由于爱奇艺号的技术栈主要基于Java,所以使用的是GraphQL的 Java实现。 基于graphql-java,API生成平台主要做了以下功能优化及增强。

(1 支持Rest API:降低前端接入成本。

(2) 动态接入监控 动态生成的API,与其他普通接口一样支持Prometheus监控,保证监控的灵活性和服务的稳定性。

(3)灵活配置:可以动态生成GraphQL的schema,方便后端接入新服务。

(4) 可视化API管理平台: API接口提供可视化操作,方便查看、新增、修改和重用。

接下来将对以上功能进行详细介绍:

1.支持Rest API

graphql-java通过Spring的封装,位于整个架构的网关层或BFF层。项目user-info-graphQL依赖graphql-java-spring,支持Rest API请求。平台的整体架构图如图3-1所示:

3qMJ3qy.png!mobile

图3-1

User-info-graphQL的服务流程图如图3-2所示。客户端通过graphql/前缀的Rest API方式请求,后端通过前缀与GraphQL Query绑定,从DB获取映射关系,最终转换成GraphQL支持的查询语法。

QJNJn2u.png!mobile

图3-2

2.动态接入监控

在user-info-graphQL项目中,原本是通过template url来匹配任意自定义url;导致监控平台只能显示template url的请求信息,如图3-3所示。这个问题可以通过重写 spring-boot-actuator 中获取tags的方法,将真实的url请求信息暴露到Spring boot的/actuator/prometheus端点这个方法来解决,如图3-4所示。

UZVFZrR.png!mobile

图3-3

I7BBZnN.png!mobile

图3-4

通过暴露的监控端点接入Prometheus,实现对新生成的API进行实时动态监控,示例效果如图3-5所示:

6rauI3j.png!mobile

图3-5

3.灵活配置

为了方便后端快速接入新增微服务,达到支持API动态扩展目的。项目中通过Velocity定义schema模板,通过Java注解、反射机制动态生成graphqls模板文件,如图3-6所示:

UbYNBrV.png!mobile

qQzameI.png!mobile

图3-6

图3-6中的GraphQL schema模板,支持通过用户UID查询用户信息。用户信息是由多个微服务聚合而成,采用异步调用多个微服务并行获取数据。基于此模板,用户只需要实现SPI定义好的接口,就能实现对新增微服务的支持。

4.可视化API管理平台 

通过API生成管理平台,开发人员可以实现API接口的可视化配置、生成、动态监控等功能,达到开箱即用的效果,极大 提升开发和运维效率

总结

通过GraphQL动态构建BFF服务层API,聚合不同的微服务,相比于Rest API方式,能够减少后端重复开发,加快响应前端需求。后端开发人员只需要开发维护新增微服务,并通过SPI方式,增加BFF层对新增微服务的支持即可。

价 值:

通过在爱奇艺号后端微服务引入GraphQL 构建BFF服务层 ,可以达成以下效果:

uI3a2mA.png!mobile

开发方面的优势

  • 提升开发效率:后端开发人员职责分工明确,微服务与BFF层独立开发及维护。新增微服务接入方便,因BFF层对外的API支持动态生成,所以无需更改BFF层的代码,只需集中维护微服务。前端可以通过GraphQL的schema查看接口返回数据,减少前后端沟通成本。

  • 形成低代码平台:随着构建的微服务基础措施足够完善,BFF层支持动态生成API接口,极大减轻重复工作量。

uI3a2mA.png!mobile

运行维护时的优势

  • 便于监控:新增BFF层API接口,通过支持Prometheus端点监控,无开发成本。

  • 支持系统高吞吐量:BFF服务、微服务都是基于docker部署,支持QPS动态扩容,能够支持高并发。

  • 便于维护和扩展:基于GraphQL构建的BFF层,API接口动态生成,层次清晰,更易维护、扩展。

难 点:

  • 动态扩展查询支持,目前schema的定义都是基于明确字段的情况下,如果需要支持动态的查询支持,需要支持动态schema扩展和解析。

  • 中文文档少,Facebook官方只发布了JS实现,Java实现都是基于开源社区,文档和功能都不是很完善。

未来规划:

随着BFF端对API请求的多样化,需要动态支持新方法扩展及监控。 目前API与请求的映射关系持久化在MySQL中,需要支持集群和高性能,后续逐步迁移到ZK或Redis中,并缓存到本地。

随着云原生和K8s的兴起,基于K8s部署的Go服务,更易扩容和维护。基于Java实现的GraphQL,如果迁移到K8s上部署,很难实现快速扩缩容的效果。而graphql-go在github上的star 高达7k ,可见热度极高。如果基于Go实现BFF端,API与请求的映射关系可以存储于K8s的Pod配置文件中,并且通过一个API部署一类Pod,进行服务隔离,可以更高程度的保证服务稳定。

VF7Nrmu.jpg!mobile

也许你还想看

低代码在爱奇艺鹊桥数据同步平台的实践

代码质量提升之道——代码覆盖率原理与移动端工程实践

qqQjuib.gif!mobile 扫一扫下方二维码,更多精彩内容陪伴你!

e2qyYzQ.jpg!mobile


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK