写点什么

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

2021 年 2 月 02 日

减少重复开发,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:001985

评论

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

程序员告诉你:C/C++后台开发需要学习哪些技能书

赖猫

c++ Linux 后台开发

今天发的被删了,不是我没写

lidaobing

28天写作

创业感悟 | 2021是继续打工还是选择创业?

黑马腾云

创业

还在用ELK? 是时候了解一下轻量化日志服务Loki了

京东科技开发者

DevOps 云原生 日志监控

DBA 的效率加速器——CloudQuery v1.3.0 上线!

CloudQuery社区

数据库 运维 开发 dba

灵魂一击!详解Java中的IO输入输出流

程序员小毕

Java 程序员 架构 io

我们为什么选择VUE来构建前端

力软.net/java开发平台

Vue 前端

第九周-总结

jizhi7

余额和核心信息数据安全分享

冬天的秘密

加密 防篡改 数据隐私

深度剖析原理!2020年Android网络编程总结篇,已开源

欢喜学安卓

android 程序员 面试 移动开发

【STL 源码剖析】浅谈 STL 迭代器与 traits 编程技法

herongwei

c++ 后端 迭代器模式 源码剖析 stl

Android知识体系大纲!Android平台HTTPS抓包解决方案及问题分析,年薪50W

欢喜学安卓

android 程序员 面试 移动开发

我们该如何正确的中断一个线程的执行??

冰河

Java 并发编程 多线程 高并发 中断线程

架构师训练营第十一周作业

文智

极客大学架构师训练营

阿里P8手把手教你!微信小程序的事件处理,安卓系列学习进阶视频

欢喜学安卓

android 程序员 面试 移动开发

不讲码德!坏味道偷袭我这个老码农

爱笑的架构师

Java 代码审查 代码坏味道 代码规范 七日更

TypeScript | 第一章:环境搭建及基础数据类型

梁龙先森

typescript 前端 七日更

权限系统的基本概念和架构

程序那些事

权限系统 程序那些事 SSO 权限架构 权限认证

欧盟推出新数字法案,会是一场“锄强扶弱”的数字监管变革吗?

脑极体

【Java入门】String,StringBuffer和StringBuilder

HQ数字卡

Java 七日更

甲方日常 71

句子

工作 随笔杂谈 日常

互联网已经干得很好的事情,不应该是区块链干的

CECBC区块链专委会

区块链 互联网

如何坚持做一件事情

熊斌

个人成长 七日更

第13周

袭望

架构师 3 期 3 班 -week5- 作业

zbest

作业 week5

Docker

云淡风轻

如何守护数据安全? 这里有一份RDS灾备方案为你支招

京东科技开发者

数据库 云数据库

第九周-作业

jizhi7

架构师 3 期 3 班 -week5- 总结

zbest

总结 week5

生产环境全链路压测建设历程 16:淘宝网高可用历程的总结

数列科技杨德华

全链路压测 七日更

十日谈:我的 2020

escray

2020 七日更 十日谈

技术为帆,纵横四海- Lazada技术东南亚探索和成长之旅

技术为帆,纵横四海- Lazada技术东南亚探索和成长之旅

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