以网关服务器为服务的 Apollo 联邦

Posted

技术标签:

【中文标题】以网关服务器为服务的 Apollo 联邦【英文标题】:Apollo federation with gateway server as service 【发布时间】:2019-10-23 05:08:13 【问题描述】:

问题的摘要已在 Github 问题中描述:

https://github.com/apollographql/apollo-server/issues/2794


简而言之,有没有办法实现 Apollo Federation,让网关本身拥有自己的架构?

在网关本身具有架构的情况下联合 Apollo 服务器

@apollo/gateway@0.6.5 @apollo/federation@0.6.2

预期行为

当我实例化我的 Apollo 网关服务器时,我希望我应该能够合并来自联合服务的模式,以及来自网关本身的模式。

实际行为

网关服务器无法挂载/graphql 路由,因为它希望所有服务在它挂载之前都在运行。

在运行时,控制台会打印以下错误:

POST /graphql 404 11.251 ms - 147
Encountered error when loading gateway-app at http://localhost:8000/graphql: invalid json response body at http://localhost:8000/graphql reason: Unexpected token < in JSON at position 0
[DEBUG] Fri Jun 07 2019 12:11:07 GMT-0400 (Eastern Daylight Time) apollo-gateway: Configuration loaded for Gateway
[DEBUG] Fri Jun 07 2019 12:11:07 GMT-0400 (Eastern Daylight Time) apollo-gateway: Composing schema from service list:
  remove-svc
TypeError: schema.toConfig is not a function
    at Object.composeServices (/gateway-app/node_modules/@apollo/federation/dist/composition/compose.js:191:67)
    at Object.composeAndValidate (/gateway-app/node_modules/@apollo/federation/dist/composition/composeAndValidate.js:13:41)
    at ApolloGateway.createSchema (/gateway-app/node_modules/@apollo/gateway/dist/index.js:90:47)
    at ApolloGateway.<anonymous> (/gateway-app/node_modules/@apollo/gateway/dist/index.js:81:22)
    at Generator.next (<anonymous>)
    at fulfilled (/gateway-app/node_modules/@apollo/gateway/dist/index.js:4:58)
    at process._tickCallback (internal/process/next_tick.js:68:7)

源代码

const url = new URL(`redis://$REDIS_URL:$REDIS_PORT/$REDIS_DATABASE`).toString()

const cache = new RedisCache( url )

const context = ( req ) => 
  if (!(req.user || req.headers.authorization === ROUTE_AUTH)) 
    throw new AuthenticationError('Not authenticated')
  
  return  user: req.user, req: req 


try 
  const loadGateway = async () => 
    try 
      const  schema, executor  = await gateway.load()
      return  schema, executor 
     catch (err) 
      console.error(err)
      return null
    
  

  const gateway = new ApolloGateway(
    debug: process.env.ENV !== 'prod',
    serviceList: [
       name: 'gateway', url: `$GATEWAY_HOSTNAME/graphql` ,
       name: 'remote-svc', url: `$REMOTE_SERVICE_HOSTNAME/graphql` ,
    ],
  )

  const  schema, executor  = loadGateway()
  const server = new ApolloServer(
    schema,
    executor,
    cache,
    dataSources,
    engine:  apiKey: ENGINE_API_KEY ,
    tracing: true,
    context,
  )
  server.applyMiddleware( app )
 catch (err) 
  console.error(err)

【问题讨论】:

【参考方案1】:

根据我的问题报告的原始错误,有两个错误。

    Apollo 网关服务器不能也不应该是具有自己架构的联合服务(请参阅 Github Issue #2792)。

来自阿波罗:

我将根据您的服务的命名在这里得出一个结论:您是否尝试在端口 8000 上运行网关并同时将其视为联合服务?如果是这样,那是行不通的;网关必须先解析所有架构,然后才能组成最终架构。

    GraphQL 核心依赖项的版本必须至少为 14.2.0(请参阅 Github Issue #2825)。

来自 GraphQL JS 变更日志:

toConfig 旨在通过最大限度地减少您需要编写和维护的代码量来帮助进行模式转换,例如来自 graphql-tools 的 recreateType。

当我在 graphql-voyager 工作时,我创建了自己的中间格式,只是为了进行模式转换。

此外,toConfig 将防止添加新字段时出现的错误。例如,lexicographicSortSchema 不尊重新添加的assumeValid 和 allowedLegacyNames 字段。

在将架构从网关迁移到它自己的联合服务并将我的核心 GraphQL 依赖项更新到适当的版本后,我成功地实现了网关/联合模式。

【讨论】:

以上是关于以网关服务器为服务的 Apollo 联邦的主要内容,如果未能解决你的问题,请参考以下文章

如何在 NestJS 中热重载联邦网关

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

除了 Apollo,还有其他 GraphQL Federation 实现吗?

父服务关闭时,Apollo 联合网关无法加载

如何使用 Apollo Federation 从网关到服务的请求中获取完整的详细信息

将 Apollo 服务器调试为 AWS Lambda 函数