GraphQL 学习
实践
- Using GraphQL with MongoDB
- Testing a GraphQL Server using Jest
- using-dataloader-to-batch-requests
- How GraphQL Replaces Redux
- js Client Bind GraphQL data to your UI with one function call.
相关网站
- GraphQL CN A query language for APIs. 一种用于 API 的查询语言。
- GraphQL 最佳实践
- awesome-graphql
- The Fullstack Tutorial for GraphQL Youtube 视频教程
- GraphiQL A graphical interactive in-browser GraphQL IDE. Live demo
- Lacinia - GraphQL for Clojure,Github Repo 一套 GraphQL 规范的完整实现,致力于维护对规范的外部兼容。
- alumbra Simple & Elegant GraphQL for Clojure!
- graphql-clj A Clojure library designed to provide GraphQL implementation.
- 流行的服务端框架、客户端库、服务
- Getting started with TypeScript and Apollo
- Relay A JavaScript framework for building data-driven React applications
- Om Next w/ DataScript
- Node.js 实现:
- Apollo Server is a flexible, community driven, production-ready HTTP GraphQL middleware for Express, Hapi, Koa, and more.
- express-graphql
- 以下内容部分摘自微信文章:微服务下使用GraphQL构建BFF的实践
微服务架构的优势(virtue):
简单说来,微服务是一种架构风格。通过对特定业务领域的分析与建模,将复杂的应用分解成小而专一、耦合度低并且高度自治的一组服务。微服务中的每个服务都是很小的应用,这些应用服务相互独立并且可部署。微服务通过对复杂应用的拆分,达到简化应用的目的,而这些耦合度较低的服务则通过 API 形式进行通信,所以服务之间对外暴露的都是 API,不管是对资源的获取还是修改。
- Isolation 隔离状态
- Autonomy 自治
BFF 前端的中间层后端
Backend for Frontends(以下简称 BFF) 顾名思义,是为前端而存在的后端 (服务) 中间层。引用了 BFF 之后,前端应用将直接和 BFF 通信,BFF 再和后端进行 API 通信,所以本质上来说,BFF 更像是一种“中间层”服务。
BFF 其实是一种 API Gateway 实现模式
API Gateway 的三种实现:
- 一个 API Gateway 对所有客户端提供同一种 API,例:
/api/users
- 一个 API Gateway 通过 Router 对每种客户端提供分别的 API,例:
/mobile/api/users
和/web/api/users
- 多个 API Gateway 分别对每种客户端提供分别的 API,例:如上,但两个 Gateway 分别为 Mobile Gateway 和 Web Gateway。
BFF 其实是 API Gateway 的其中一种实现模式,即 BFF 更类似于第三种 API Gateway 实现,通常一个 BFF 对应一种客户端,再由 BFF 去调用后端的实际 API。
GraphQL 与 REST 对比
相比于 REST 风格,GraphQL 具有如下特性:
- 定义数据模型:按需获取
- 数据分层
- 强类型
- 协议而非存储
- 无须版本化
对于 GraphQL 和 REST 之间的对比,主要有如下不同:
- 数据获取:REST 缺乏可扩展性, GraphQL 能够按需获取。GraphQL API 调用时,payload 是可以扩展的 ;
- API 调用:REST 针对每种资源的操作都是一个 endpoint, GraphQL 只需要一个 endpoint( /graphql), 只是 post body 不一样 ;
- 复杂数据请求:REST 对于嵌套的复杂数据需要多次调用,GraphQL 一次调用, 减少网络开销;
- 错误码处理:REST 能够精确返回 HTTP 错误码,GraphQL 统一返回 200,对错误信息进行包装;
- 版本号:REST 通过 v1/v2 实现,GraphQL 通过 Schema 扩展实现;
微服务 + GraphQL + BFF 实践
在微服务下基于 GraphQL 构建 BFF,例如在项目对应的业务场景下,微服务后台有近 10 个微服务,客户端包括针对不同角色的 4 个 App 以及一个 Web 端。对于每种类型的 App,都有一个 BFF 与之对应。每种 BFF 只服务于这个 App。BFF 解析到客户端请求之后,会通过 BFF 端的服务发现,去对应的微服务后台通过 CQRS 的方式进行数据查询或修改。
使用 GraphQL-express 框架构建项目的 BFF 端,然后通过 Docker 进行部署。BFF 和微服务后台之间,还是通过 registrator 和 Consul 进行服务注册和发现。
三个 App 客户端分别使用 GraphQL 的形式请求对应的 BFF。BFF 层再通过 Consul 服务发现和后端通信。
关于系统中的鉴权问题
用户登录后,App 直接访问 KeyCloak 服务获取到 id_token,然后通过 id_token 透传访问 auth-api 服务获取到 access_token, access_token 以 JWT (Json Web Token) 的形式放置到后续 http 请求的头信息中。
在我们这个系统中 BFF 层并不做鉴权服务,所有的鉴权过程全部由各自的微服务模块负责。BFF 只提供中转的功能。BFF 是否需要集成鉴权认证,主要看各系统自己的设计,并不是一个标准的实践。
BFF is pary of Application, BFF 就是客户端的一部分
- BFF 中定义的数据结构,就是客户端所真正关心的。
- BFF 就是为客户端而生,是客户端的一部分。
- 需要说明的是,对于“业务的关注”并不是说,BFF 会处理所有的业务逻辑,业务逻辑还是应该由微服务关心,BFF 关注的是客户端需要什么。
GraphQL Mutation 与 CQRS
不同于 query,所有 mutation 都会调用后端的 API,而后端的 API 对于资源的修改也是通过 SpringBoot EventListener 实现的 CQRS 模式。
新架构的测试
在引入了 BFF 的项目,我们的测试仍然使用金字塔原理,只是在客户端和后台之间,需要添加对 BFF 的测试。
- Client 的 integration-test 关心的是 App 访问 BFF 的连通性,App 中所有访问 BFF 的请求都需要进行测试;
- BFF 的 integration-test 测试的是 BFF 到微服务 API 的连通性,BFF 中依赖的所有 API 都应该有集成测试的保障;
- API 的 integration-test 关注的是这个服务对外暴露的所有 API,通常测试所有的 Controller 中的 API。