我试图理解GraphQL在微服务架构中最适合使用的地方。

对于只有一个GraphQL模式作为API网关代理请求到目标微服务并强制它们的响应,存在一些争论。微服务仍然使用REST / Thrift协议进行通信。

另一种方法是使用多个GraphQL模式,每个微服务一个。使用一个较小的API Gateway服务器,将请求路由到目标微服务,并将请求的所有信息+ GraphQL查询。

1号的方法

使用一个GraphQL模式作为API网关会有一个缺点,每次你改变你的微服务契约输入/输出时,我们必须在API网关端相应地改变GraphQL模式。

2方法

如果每个微服务都使用多个GraphQL模式,在某种程度上是有意义的,因为GraphQL强制了一个模式定义,消费者需要尊重微服务给出的输入/输出。

问题

你在哪里发现GraphQL适合设计微服务架构? 你将如何设计一个具有GraphQL实现的API网关?


绝对接近第一条。

让您的客户机与多个GraphQL服务通信(如方法#2所示)完全违背了使用GraphQL的初衷,GraphQL的目的是在整个应用程序数据上提供一个模式,以允许在一次往返中获取数据。

从微服务的角度来看,无共享架构似乎是合理的,但对于客户端代码来说,这绝对是一场噩梦,因为每次你改变一个微服务时,你都必须更新所有的客户端。你一定会后悔的。

GraphQL and microservices are a perfect fit, because GraphQL hides the fact that you have a microservice architecture from the clients. From a backend perspective, you want to split everything into microservices, but from a frontend perspective, you would like all your data to come from a single API. Using GraphQL is the best way I know of that lets you do both. It lets you split up your backend into microservices, while still providing a single API to all your application, and allowing joins across data from different services.

如果你不想为你的微服务使用REST,你当然可以让每个微服务都有自己的GraphQL API,但你仍然应该有一个API网关。人们使用API网关的原因是为了使从客户端应用程序调用微服务更易于管理,而不是因为它很适合微服务模式。


对于方法#2,实际上这是我选择的方式,因为它比手动维护烦人的API网关容易得多。通过这种方式,您可以独立地开发服务。让生活更轻松:P

有一些很棒的工具可以将模式组合成一个,例如graphql-weaver和apollo的graphql-tools,我正在使用graphql-weaver,它很容易使用,工作很棒。


本文推荐方法#1。下面这张图片也摘自上述文章:

将所有内容都放在单个端点后的主要好处之一是,可以比每个请求都有自己的服务更有效地路由数据。虽然这是GraphQL经常被吹捧的价值,减少了复杂性和服务蔓延,但由此产生的数据结构还允许对数据所有权进行非常好的定义和清晰的描述。

采用GraphQL的另一个好处是,您可以从根本上对数据加载过程进行更大的控制。因为数据加载器的过程进入自己的端点,所以您可以部分地、完全地或带有警告地满足请求,从而以极其细粒度的方式控制数据传输方式。

下面的文章很好地解释了这两个好处:https://nordicapis.com/7-unique-benefits-of-using-graphql-in-microservices/


截至2019年年中,第一种方法的解决方案现在有了Apollo人创造的名称“Schema Federation”(以前通常称为GraphQL拼接)。 他们还为此提出了模块@apollo/federation和@apollo/gateway。

ADD:请注意,使用模式联合,您不能在网关级别修改模式。因此,对于模式中需要的每一个比特,都需要有一个单独的服务。


我一直在使用GraphQL和微服务

根据我的经验,对我来说有效的是根据功能/用法将两种方法结合起来,我永远不会像方法1那样只有一个网关,但也不会像方法2那样为每个微服务使用GraphQL。

例如,根据Enayat的答案图像,在这种情况下,我要做的是有3个图网关(而不是图像中的5个)

App(产品,篮子,航运,库存,需要/链接到其他服务) 付款 用户

通过这种方式,您需要特别注意从依赖的服务中公开的所需/链接的最小数据的设计,如认证令牌、用户id、paymentid、支付状态

以我的经验为例,我有“用户”网关,在GraphQL中,我有用户查询/突变,登录,登录,退出,更改密码,恢复电子邮件,确认电子邮件,删除帐户,编辑个人资料,上传图片等…这张图本身就相当大!,它是分开的,因为在最后,其他服务/网关只关心结果信息,如用户id,名称或令牌。

这样更容易……

Scale/shutdown the different gateways nodes depending on they usage. (for example people might not always be editing their profile or paying... but searching products might be used more frequently). Once a gateways matures, grows, usage is known or you have more expertise on the domain you can identify which are the part of the schema that could have they own gateway (... happened to me with a huge schema that interacts with git repositories, I separated the gateway that interact with a repository and I saw that the only input needed/linked info was... the folder path and expected branch) The history of you repositories is more clear and you can have a repository/developer/team dedicated to a gateway and its involved microservices.

更新:

我有一个在线的kubernetes集群,它使用与我在这里描述的相同的方法,所有后端都使用GraphQL,都是开源的,这里是主存储库: https://github.com/vicjicaman/microservice-realm

这是对我的答案的更新,因为我认为如果答案/方法是正在运行的备份代码,并且可以参考/审查,那就更好了,我希望这能有所帮助。

更新2:

只是添加了另一个功能分离的例子,我将与管理文件、上传、创建、删除、将文件分组到桶、批量删除、私有文件、cors配置等相关的功能分离到一个图表中……而其他图形/服务只需要一些细节,如预先签名的帖子或结果url/fileid


截至2019年,最好的方法是编写实现apollo网关规范的微服务,然后使用网关按照方法#1将这些服务粘合在一起。 构建网关的最快方法是像这样的docker映像 然后使用docker-compose同时启动所有服务:

version: '3'

services:
    service1:
        build: service1
    service2:
        build: service2
    gateway:
        ports:
            - 80:80
        image: xmorse/apollo-federation-gateway
        environment: 
            - CACHE_MAX_AGE=5
            - "FORWARD_HEADERS=Authorization, X-Custom-Header" # default is Authorization, pass '' to reset
            - URL_0=http://service1
            - URL_1=http://service2

The way it is being described in this question, I believe that using a custom API gateway as an orchestration service can make a lot of sense for complex enterprise focused applications. GraphQL can be a good technology choice for that orchestration service, at least as far as querying goes. The advantage to your first approach (one schema for all microservices) is the ability to stitch together the data from multiple microservices in a single request. That may, or may not, be very important depending on your situation. If the GUI calls for rendering data from multiple microservices all at once, then this approach can simplify the client code such that a single call can return data that is suitable for data binding with the GUI elements of such frameworks as Angular or React. This advantage doesn't apply for mutations.

The disadvantage is tight coupling between the data APIs and the orchestration service. Releases can no longer be atomic. If you refrain from introducing backwards breaking changes in your data APIs, then this can introduce complexity only when rolling back a release. For example, if you are about to release new versions of two data APIs with the corresponding changes in the orchestration service and you need to roll one of those releases back but not the other, then you will be forced to roll back all three anyway.

在GraphQL和REST的比较中,你会发现GraphQL没有RESTful api那么高效,所以我不建议在数据api上用GraphQL代替REST。


对于问题1,Intuit在几年前宣布迁移到One Intuit API生态系统(https://www.slideshare.net/IntuitDeveloper/building-the-next-generation-of-quickbooks-app-integrations-quickbooks-connect-2017)时承认了GraphQL的强大功能。Intuit选择了方法1。您提到的缺点实际上阻止了开发人员引入可能破坏客户端应用程序的破坏性模式更改。

GraphQL在许多方面帮助提高了开发人员的工作效率。

When designing a new microservice for a domain, engineers (backend/ frontend/ stakeholders) agree on a schema for the domain entities. Once the schema is approved, it is merged with the master domain schema (universal) and deployed on the Gateway.Front end engineers can start coding client applications with this schema while backend engineers implement the functionality. Having one universal schema means that there are no two microservices with redundant functionality. GraphQL has helped client applications become simpler and faster. Want to retrieve data from /update data to multiple microservices? All client applications have to do is fire ONE GraphQL request and the API Gateway abstraction layer will take care to fetch and collate data from multiple sources (microservices). Open source frameworks like Apollo (https://www.apollographql.com/) have accelerated the pace of GraphQL adoption. With mobile being the first choice for modern applications, it is important to design for lower data bandwidth requirements from ground zero. GraphQL helps by allowing client apps to request for specific fields only.

问题2:我们在API Gateway上构建了一个自定义抽象层,它知道模式的哪一部分属于哪个服务(提供者)。当查询请求到达时,抽象层将请求转发给适当的服务。一旦基础服务返回响应,抽象层就负责返回所请求的字段。

然而,现在有几个平台(Apollo服务器、GraphQL -yoga等)允许人们在短时间内构建一个GraphQL抽象层。


在使用graphql引导微服务生态系统时,我们也有类似的担忧。我们可以用Apollo GraphQL解决这个问题。

我们为“一个平台”从零开始构建了这些解决方案。以service结尾的文件夹是微服务,其他的是spa(单页应用程序)

它由各种微服务和带有API网关的spa组成,API网关是多个微服务的主要接口。

与此同时,你可以找到一个OP CLI生成器,它可以帮助你从零开始引导微服务。

项目- https://github.com/1-Platform/one-platform

我请求请看看这个项目,并随时采取,如果这看起来对你很好。

问候

Rigin Oommen