具有网关服务器作为服务的 Apollo 联邦
Apollo federation with gateway server as service
问题摘要已在 Github 问题中描述:
https://github.com/apollographql/apollo-server/issues/2794
简而言之,有没有一种方法可以实现 Apollo Federation,使网关本身拥有自己的架构?
联合 Apollo 服务器,其中网关本身有一个模式
@apollo/gateway@0.6.5
@apollo/federation@0.6.2
预期行为
当我实例化我的 Apollo 网关服务器时,我希望我应该能够合并来自联合服务的模式,以及来自网关本身的模式。
实际行为
网关服务器无法挂载 /graphql
路由,因为它期望所有服务在挂载前都处于 运行ning 状态。
在 运行 时间,以下错误被打印到控制台:
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)
}
根据我的问题报告的原始错误,有两个错误。
- Apollo 网关服务器不能也不应该是具有自己模式的联合服务(参见 Github Issue #2792)。
来自阿波罗:
I'll jump to a conclusion here based on the naming of your service: are you trying to run the gateway at port 8000 and treat it as a federated service at the same time? If so, that's not going to work; the gateway has to resolve all schemas before it can compose the final schema.
- GraphQL 核心依赖项必须至少为
14.2.0
版本(参见 Github Issue #2825)。
来自 GraphQL JS 变更日志:
toConfig is intended to help with schema transformation by minimizing the amount of code you need write and maintain, e.g. recreateType from graphql-tools.
When I worked on graphql-voyager I created my own intermidiate format just to do schema transformations.
Moreover, toConfig will prevent bugs that occur when a new field is added. For example, lexicographicSortSchema doesn't respect newly added assumeValid and allowedLegacyNames fields.
将架构从网关迁移到它自己的联合服务并将我的核心 GraphQL 依赖项更新到适当的版本后,我成功地实现了 gateway/federation 模式。
问题摘要已在 Github 问题中描述:
https://github.com/apollographql/apollo-server/issues/2794
简而言之,有没有一种方法可以实现 Apollo Federation,使网关本身拥有自己的架构?
联合 Apollo 服务器,其中网关本身有一个模式
@apollo/gateway@0.6.5
@apollo/federation@0.6.2
预期行为
当我实例化我的 Apollo 网关服务器时,我希望我应该能够合并来自联合服务的模式,以及来自网关本身的模式。
实际行为
网关服务器无法挂载 /graphql
路由,因为它期望所有服务在挂载前都处于 运行ning 状态。
在 运行 时间,以下错误被打印到控制台:
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)
}
根据我的问题报告的原始错误,有两个错误。
- Apollo 网关服务器不能也不应该是具有自己模式的联合服务(参见 Github Issue #2792)。
来自阿波罗:
I'll jump to a conclusion here based on the naming of your service: are you trying to run the gateway at port 8000 and treat it as a federated service at the same time? If so, that's not going to work; the gateway has to resolve all schemas before it can compose the final schema.
- GraphQL 核心依赖项必须至少为
14.2.0
版本(参见 Github Issue #2825)。
来自 GraphQL JS 变更日志:
toConfig is intended to help with schema transformation by minimizing the amount of code you need write and maintain, e.g. recreateType from graphql-tools.
When I worked on graphql-voyager I created my own intermidiate format just to do schema transformations.
Moreover, toConfig will prevent bugs that occur when a new field is added. For example, lexicographicSortSchema doesn't respect newly added assumeValid and allowedLegacyNames fields.
将架构从网关迁移到它自己的联合服务并将我的核心 GraphQL 依赖项更新到适当的版本后,我成功地实现了 gateway/federation 模式。