为联合服务 apollo GraphQL 中的架构更改自动重新加载网关

Posted

技术标签:

【中文标题】为联合服务 apollo GraphQL 中的架构更改自动重新加载网关【英文标题】:Auto Reload of gateway for schema changes in federated service apollo GraphQL 【发布时间】:2020-01-28 01:44:38 【问题描述】:

在阿波罗联邦,我面临这个问题: 每次我们对服务列表中任何联合服务的模式进行更改时,都需要重新启动网关。 我知道每次网关启动时,它都会收集所有模式并聚合数据图。但是有没有一种方法可以在不重新启动网关的情况下自动处理,因为它也会关闭所有其他未受影响的 GraphQL 联合服务

Apollo GraphQL , @apollo/gateway

【问题讨论】:

【参考方案1】:

您可以使用 express 来刷新网关的架构。 ApolloGateway 有一个load() 函数,用于从实现服务中获取模式。如果需要一些自动的东西,这个 HTTP 调用可能是部署过程的一部分。我不会使用轮询或过于自动的东西。部署实施服务后,架构在更新和再次部署之前不会更改。

import  ApolloGateway  from '@apollo/gateway';
import  ApolloServer  from 'apollo-server-express';
import express from 'express';

const gateway = new ApolloGateway( ...config );
const server = new ApolloServer( gateway, subscriptions: false );
const app = express();

app.post('/refreshGateway', (request, response) => 
  gateway.load();
  response.sendStatus(200);
);

server.applyMiddleware( app, path: '/' );

app.listen();

更新load() 函数现在会在重新加载架构之前检查 phase === 'initialized'。解决方法可能是使用gateway.loadDynamic(false) 或可能更改gateway.state.phase = 'initialized';。我推荐loadDyamic(),因为更改状态可能会导致问题出现。由于在本次更新时我没有与 Apollo Federation 合作,因此我没有测试过这两种解决方案。

【讨论】:

这是一个很好的解决方案,但它是否记录在任何地方? apollographql.com/docs/federation/api/apollo-gateway 的网关文档不要提及 load @Nate 他们已经删除了 load 周围的文档,如果它曾经存在的话。我在一些 apollo-gateway 代码中看到了这一点,并认为它适合这个用例。 而且……它不再起作用了。这是一个很好的解决方案,但在最近的版本中,它报告“错误:ApolloGateway.load 以令人惊讶的状态加载”。他们似乎想推动您使用他们的托管联合服务。 这太糟糕了。我想,最初的解决方案应该与一粒盐一起服用,因为它没有记录(可能是因为这个原因)。你可以试试gateway.loadDynamic(false)。您也可以将 Apollo 相位状态破解为“初始化”。想到的唯一其他解决方案是使用另一个模式系统,使用 Apollo Gateway 似乎过于复杂。【参考方案2】:

我不知道除了轮询之外自动重新加载网关的其他方法。 我制作了一个可重复使用的docker image,如果出现重新加载服务的新方法,我将继续更新它。现在,您可以使用POLL_INTERVAL env var 定期检查更改。 下面是一个使用 docker-compose 的例子:

version: '3'

services:
    a:
        build: ./a # one service implementing federation
    b:
        build: ./b
    gateway:
        image: xmorse/apollo-federation-gateway
        ports:
            - 8000:80
        environment: 
            CACHE_MAX_AGE: '5' # seconds
            POLL_INTERVAL: '30' # seconds
            URL_0: "http://a"
            URL_1: "http://b"

【讨论】:

感谢您的想法 :)【参考方案3】:

您可以使用一个实验性的轮询间隔:

const gateway = new ApolloGateway(
  serviceList: [
     name: "products", url: "http://localhost:4002" ,
     name: "inventory", url: "http://localhost:4001" ,
     name: "accounts", url: "http://localhost:4000" 
  ],
    debug: true,
    experimental_pollInterval:3000
)

上面的代码将每 3 秒拉一次

【讨论】:

我试过这个,但问题是这在生产环境中是不可取的,甚至 apollo 也这么说。 :( 请注意,您正在向原始问题添加要求。目前没有更好的 OOB 解决方案。真诚的

以上是关于为联合服务 apollo GraphQL 中的架构更改自动重新加载网关的主要内容,如果未能解决你的问题,请参考以下文章

在 apollo-server 中将网关上的联合类型转换为服务 GraphQL 中的标量类型

Graphql Apollo Federation - 基于实现服务解析计算域

Apollo 联合网关背后的 Hasura GraphQL 端点

解决 graphql 查询中的联合结果时出现意外的 *Missing Field* 错误(Vue Apollo 客户端)

Apollo 中的 GraphQL 模式存在问题

使用 apollo-federation 独立构建 GraphQL 服务