Linux 之父出席、干货分享、圆桌讨论,精彩尽在 OpenCloudOS 社区开放日,报名戳 了解详情
写点什么

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

  • 2021 年 2 月 02 日
  • 本文字数:3480 字

    阅读完需:约 11 分钟

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

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 部署架构图,可以看到它处于系统“中间层”


图 1-1

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


图 1-2

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


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



图 1-3



图 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 所示:



图 2-1

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


  • GraphQL 与 Rest API 对比:


表 2-1


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



表 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 所示:



图 3-1


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


图 3-2

2.动态接入监控

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

图 3-3



图 3-4


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



图 3-5

3.灵活配置

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




图 3-6


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


4.可视化 API 管理平台 

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


总结

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


价值:

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


开发方面的优势

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

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


运行维护时的优势

  • 便于监控:新增 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,进行服务隔离,可以更高程度的保证服务稳定。


本文转载自:爱奇艺技术产品团队(ID:iQIYI-TP)

原文链接:减少重复开发,GraphQL在低代码平台如何落地?


2021 年 2 月 02 日 07:002693

评论

发布
暂无评论
发现更多内容

SpotMax:在云上,看我帮助企业省“余粮”

亚马逊云科技 (Amazon Web Services)

云计算

作业2-产品的利益相关人分析

赝品

产品训练营-第二周学习总结

Trigger

极客时间 极客大学产品经理训练营 产品训练营

第二周 作业

Geek_72d5ab

Stakeholder list

顾远山

产品训练营作业-week02

anyou

第二章学习总结

Kasn

产品经理 产品经理训练营

产品经理训练营 - 第二周作业

玖玖

产品经理训练营--第二周作业

孤星

作业 @ 第4课

糯米~

02-抽奖小助手与「谁」相关

学习高手song轻松

产品

重学JS | Ajax发送数据序列化问题以及Object序列化整理

梁龙先森

JavaScript 大前端 编程语言 28天写作

极客产品训练营第二课作业

HaoJi

如何对应用进行Android系统签名和常用adb命令总结

Changing Lin

android

Week2:抽奖助手StakeHolder思考

Y.

极客大学产品经理训练营

第二周总结

岛乾坤

【纯CSS】画 多国国旗

德育处主任

css3 html/css CSS小技巧 28天写作 纯CSS

主机安全产品利益相关方

赵志广

产品经理训练营

抽奖小程序-利益相关方分析

思亭

第二周作业-APP的利益相关方

Geek_ce1551

Spring Boot 中使用监听器

武哥聊编程

Java springboot SpringBoot 2 28天写作

产品经理第二周作业

克比

产品的利益相关方

沈弋

第二章作业

Kasn

产品经理 产品经理训练营

利益相关者分析

未月二九

第二周

Jove

产品利益相关者分析

Dylan Zhu

CSS(五)——设置文本样式

程序员的时光

程序员 大前端 七日更 28天写作

第二周作业 - 抽奖助手利益相关者

Geek_971380

成功逆袭:外包—苏宁—阿里 论我是怎么快速晋升的?

比伯

Java 编程 架构 面试 程序人生

产品利益相关方

高和不在家

面向体验的视频云-火山引擎增长沙龙

面向体验的视频云-火山引擎增长沙龙

减少重复开发,GraphQL在低代码平台如何落地?_架构_爱奇艺技术产品团队_InfoQ精选文章