GraphQL长任务仅报failed to fetch错误 长短请求表现不一致排查问询
问题结论
该问题属于服务端配置错误导致,你写的1200s超时参数完全没有生效,Node.js原生HTTP服务器默认的120s(2分钟)请求超时触发了Apollo Server的内部重试逻辑,所以会出现服务端重复执行任务、前端网络面板看不到二次请求、最终超时抛出failed to fetch错误的现象。你在GraphQL Playground中也能复现问题,已经可以直接排除前端原因。
你配置错误的核心原因:requestTimeout写在了app.listen的origin配置项中,express的app.listen方法完全不识别该参数,你的超时设置从始至终没有生效。
修复&排查方案
1. 修正服务端超时配置
替换你现有代码中mongoose.connect后的逻辑,给HTTP服务器显式设置超时参数:
await mongoose .connect("mongodb://localhost:27017/database", { useNewUrlParser: true }) .then(() => { const server = app.listen({ port: 4000 }, () => { console.log(`Server ready at http://****:4000${apollo.graphqlPath}`) }) // 设置HTTP请求总超时为1200s server.setTimeout(1200 * 1000) // 对齐长连接超时时间,避免主动断开 server.keepAliveTimeout = 1200 * 1000 server.headersTimeout = 1200 * 1000 }) .catch((err) => console.log(err))
同时修改Apollo Server初始化配置,关闭内部重试,避免重复执行任务:
const apollo = new ApolloServer({ typeDefs, resolvers, // 关闭Apollo默认的重试逻辑 retryAttempts: 0, // 给每个请求单独设置超时 context: ({ req }) => { req.setTimeout(1200 * 1000) return {} } })
2. 验证服务端逻辑
- 在长耗时任务对应的resolver中添加日志,每次进入resolver时打印当前时间戳、请求唯一标识,确认重复执行是服务端内部触发,而非外部新请求
- 跳过浏览器和Apollo客户端,直接用curl工具发送GraphQL长请求测试,如果仍然出现重复执行+超时,即可100%确认是服务端配置问题
3. 前端兜底配置(可选)
如果需要彻底排除前端重试的可能性,可以在Apollo Client初始化时显式关闭重试逻辑:
import { ApolloClient, InMemoryCache, createHttpLink, RetryLink } from '@apollo/client'; // 禁用前端重试链路 const retryLink = new RetryLink({ attempts: { max: 0 } }); const httpLink = createHttpLink({ uri: '你的GraphQL服务地址', // 前端fetch超时和服务端对齐 fetchOptions: { timeout: 1200 * 1000 } }); const client = new ApolloClient({ link: retryLink.concat(httpLink), cache: new InMemoryCache(), defaultOptions: { query: { fetchPolicy: 'no-cache' } } });
内容的提问来源于stack exchange,提问作者Siddhant Parekh
相关产品推荐
相关产品推荐

