如何监控Next.js Apollo Client请求并排查随机请求丢失问题
针对你遇到的请求随机丢失问题,我来分享几个实用的排查思路,从客户端监控到中间代理层再到服务器端,一步步定位原因:
既然请求没到达Apollo Server,首先得确认请求是否真的从客户端发出去了,以及发出去后遇到了什么问题:
启用Apollo Client内置日志
在初始化Apollo Client时开启调试日志,能直接在客户端控制台看到请求的发起、响应和错误细节:import { ApolloClient, InMemoryCache } from '@apollo/client'; const client = new ApolloClient({ uri: '/graphql', cache: new InMemoryCache(), logger: console, logOptions: { logLevel: 'debug', logger: (msg) => console.log('[Apollo Client Debug]', msg), }, });这样能快速看到请求是否被正常发送,有没有网络层面的错误(比如连接中断、超时)。
自定义Apollo Link捕获全链路请求
用自定义Link拦截所有请求的生命周期,包括成功、失败和异常情况,还能把错误信息上报到你的后台日志系统,方便后续分析:import { ApolloLink, from } from '@apollo/client'; import { HttpLink } from '@apollo/client/link/http'; const loggingLink = new ApolloLink((operation, forward) => { const startTime = Date.now(); const requestInfo = { operationName: operation.operationName, variables: operation.variables, timestamp: new Date().toISOString(), userAgent: navigator.userAgent, }; console.log('[Request Started]', requestInfo); return forward(operation) .map((response) => { console.log('[Request Completed]', { ...requestInfo, duration: Date.now() - startTime, response: response.data, }); return response; }) .catch((error) => { // 重点捕获未到达服务器的错误:网络失败、超时、连接重置等 console.error('[Request Failed]', { ...requestInfo, error: error.message, errorStack: error.stack, }); // 上报到后端日志接口 fetch('/api/client-request-log', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ...requestInfo, error: error.message }), }); throw error; }); }); const httpLink = new HttpLink({ uri: '/graphql', fetchOptions: { timeout: 12000 } }); const client = new ApolloClient({ link: from([loggingLink, httpLink]), cache: new InMemoryCache(), });这个Link能帮你精准定位哪些请求失败了,失败时的客户端环境是什么样的。
SSR场景的请求日志
如果你的页面用了SSR(getServerSideProps),客户端控制台看不到这些请求的日志,得在Next.js服务端添加日志:export async function getServerSideProps(context) { const apolloClient = initializeApollo(); try { await apolloClient.query({ query: YOUR_QUERY }); console.log(`[SSR Request Success] ${context.req.url} - ${new Date().toISOString()}`); } catch (error) { console.error(`[SSR Request Failed] ${context.req.url}`, error); // 同样可以上报到日志系统 } // ...其他逻辑 }记得把Next.js服务的控制台输出重定向到日志文件(注册Windows服务时配置输出路径),这样能看到SSR请求的状态。
请求没到Apollo Server,很大概率是IIS反向代理这里出了问题,比如超时、连接限制或者转发失败:
启用IIS详细日志
在IIS管理器中找到你的反向代理站点,开启日志功能,日志格式选W3C,确保记录cs-method、cs-uri-stem、sc-status、time-taken、cs(User-Agent)这些字段。日志默认存在C:\inetpub\logs\LogFiles,通过日志可以看到:- 哪些请求到达了IIS,哪些返回了5xx错误;
- 请求是否被成功转发到Apollo Server;
- 响应耗时是否过长(可能触发超时)。
检查IIS代理设置
打开IIS的「应用程序请求路由」模块,进入「服务器代理设置」,重点检查:- 超时设置:「连接超时」「响应超时」是不是太短,导致请求被IIS主动中断;
- 并发连接限制:「最大并发连接数」是否设置得过低,高并发时请求被拒绝;
- 缓存设置:是否开启了代理缓存,如果缓存了错误响应,可能导致随机出现错误。
启用失败请求跟踪(Failed Request Tracing)
这个功能能帮你看到请求在IIS中的完整处理流程,针对5xx错误请求生成详细跟踪日志:- 站点右键 → 配置 → 失败请求跟踪规则;
- 添加规则,选择「状态代码」,输入
500-599; - 启用跟踪,日志会存在
C:\inetpub\logs\FailedReqLogFiles,里面能看到请求是否被转发到后端,在哪一步出了问题。
Next.js和Apollo Server都是Windows服务,偶尔可能出现服务崩溃、重启的情况,导致请求丢失:
查看Windows事件日志
打开「事件查看器」,展开「Windows日志」→「应用程序」,筛选事件源为你的服务名称(注册Windows服务时的名称),查找服务意外停止、启动失败的记录,这些记录能告诉你服务是否异常重启。给服务添加自定义日志
如果服务没有足够的日志输出,修改服务的启动脚本,把控制台输出重定向到日志文件。比如用nssm注册服务时,设置「输出」和「错误」日志路径,或者在启动命令后加上> C:\logs\apollo-server.log 2>&1(确保日志目录存在),这样能看到服务运行时的所有输出,包括未捕获的异常。
用户反馈随机出错但你复现不了,可能是特定客户端环境导致的:
- 在自定义Apollo Link的错误上报中,加入客户端的浏览器版本、系统版本、网络类型等信息,方便定位是不是特定环境的问题;
- 在HttpLink中设置合理的超时时间(比如10-15秒),避免请求无限等待,同时捕获超时错误。
内容的提问来源于stack exchange,提问作者user11127336

