专栏名称: java一日一条
主要是讲解编程语言java,并且每天都推送一条关于java编程语言的信息
目录
相关文章推荐
芋道源码  ·  再见了SpringBoot,后端AI已成气候! ·  昨天  
芋道源码  ·  Java面试,问八股文的面试官水平很次? ·  2 天前  
Java编程精选  ·  公司Rust团队全员被裁,只因把服务写得「太 ... ·  2 天前  
芋道源码  ·  if 判断泛滥?试一试规则执行器,太香了! ·  3 天前  
51好读  ›  专栏  ›  java一日一条

GraphQL 在微服务架构中的实践

java一日一条  · 公众号  · Java  · 2018-09-15 11:05

正文

请到「今天看啥」查看全文


连接与分页

在一个常见的数据库中,一对多关系是非常常见的,一个 User 可以同时拥有多个 Post 以及多个 Comment ,这些资源的数量在理论上不是有穷的,没有办法在同一个请求全部返回,所以要对这部分资源进行分页。

Relay 通过抽象出的『连接模型』为一对多的关系提供了分片和分页的支持,在 Relay 看来,当我们获取某一个 User 对应的多个 Post 时,其实是得到了一个 PostConnection ,也就是一个连接:

在一个 PostConnection 中会存在多个 PostEdge 对象,其中的 cursor 就是我们用来做分页的字段,所有的 cursor 其实都是 Base64 编码的字符串,这能够提醒调用方 cursor 是一个不透明的指针,拿到当前 cursor 后就可以将它作为 after 参数传到下一个查询中:

当我们想要知道当前页是否是最后一页时,其实只需要使用每一个连接中的 PageInfo 对象,其中包含了很多与分页相关的信息,一个连接对象中一般都有以下的结构和字段,例如: Edge PageInfo 以及游标和节点等。

Relay 使用了非常多的功能在连接周围构建抽象,让我们能够更加方便地管理客户端中的游标,整个连接相关的规范其实特别复杂,可以阅读 Relay Cursor Connections Specification 了解更多与连接和游标有关的设计。

可变请求

每一个 Web 服务都可以看做一个大型的复杂状态机,这个状态机对外提供两种不同的接口,一种接口是查询接口,它能够查询状态机的当前状态,而另一种接口是可以改变服务器状态的可变操作,例如 POST DELETE 等请求。

按照约定,所有的可变请求都应该以动词开头并且它们的输入都以 Input 结尾,与之相对应的,所有的输出都以 Payload 结尾:

除此之外,可变请求还可以通过传入 clientMutationId 保证请求的幂等性。

小结

Facebook 的 Relay 标准其实是一个在 GraphQL 上对于常见领域问题的约定,通过这种约定我们能够减少工程师的沟通成本和项目的维护成本并在多人协作时保证服务对外提供接口的统一。

N + 1 问题

在传统的后端服务中,N + 1 查询的问题就非常明显,由于数据库中一对多的关系非常常见,再加上目前大多服务都使用 ORM 取代了数据层,所以在很多时候相关问题都不会暴露出来,只有真正出现性能问题或者慢查询时才会发现。

GraphQL 作为一种更灵活的 API 服务提供方式,相比于传统的 Web 服务更容易出现上述问题,类似的问题在出现时也可能更加严重,所以我们更需要避免 N + 1 问题的发生。

数据库层面的 N + 1 查询我们可以通过减少 SQL 查询的次数来解决,一般我们会将多个 = 查询转换成 IN 查询;但是 GraphQL 中的 N + 1 问题就有些复杂了,尤其是当资源需要通过 RPC 请求从其他微服务中获取时,更不能通过简单的改变 SQL 查询来解决。

在处理 N + 1 问题之前,我们要真正了解如何解决这一类问题的核心逻辑,也就是将多次查询变成一次查询,将多次操作变成一次操作,这样能够减少由于多次请求增加的额外开销 —— 网络延迟、请求解析等;GraphQL 使用了 DataLoader 从业务层面解决了 N + 1 问题,其核心逻辑就是整个多个请求,通过批量请求的方式解决问题。

微服务架构

微服务架构在当下已经成为了遇到业务异常复杂、团队人数增加以及高并发等需求或者问题时会使用的常见解决方案,当微服务架构遇到 GraphQL 时就会出现很多理论上的碰撞,会出现非常多的使用方法和解决方案。

在这一节中,我们将介绍在微服务架构中使用 GraphQL 会遇到哪些常见的问题,对于这些问题有哪些解决方案需要权衡,同时也会分析 GraphQL 的设计理念在融入微服务架构中应该注意什么。

当我们在微服务架构中融入 GraphQL 的标准时,会遇到三个核心问题,这些问题其实主要是从单体服务迁移到微服务架构这种分布式系统时引入的一系列技术难点,这些技术难点以及选择之间的折衷是在微服务中实践 GraphQL 的关键。

Schema 设计

GraphQL 独特的 Schema 设计其实为整个服务的架构带来了非常多的变数,如何设计以及暴露对外的接口决定了我们内部应该如何实现用户的认证与鉴权以及路由层的设计。

从总体来看,微服务架构暴露的 GraphQL 接口应该只有两种;一种接口是分散式的,每一个微服务对外暴露不同的端点,分别对外界提供服务。


在这种情况下,流量的路由是根据用户请求的不同服务进行分发的,也就是我们会有以下的一些 GraphQL API 服务:

我们可以看到当前博客服务总共由内容、评论以及订阅三个不同的服务来提供,在这时其实并没有充分利用 GraphQL 服务的好处,当客户端或前端同时需要多个服务的资源时,需要分别请求不同服务上的资源,并不能通过一次 HTTP 请求满足全部的需求。







请到「今天看啥」查看全文