Next.js服务端渲染超时导致生产事故的问题排查和解决办法

 更新时间:2025年03月05日 10:29:34   作者:HyaCinth  
Next.js是一个基于React的开源框架,用于构建服务端渲染(SSR)的Web应用程序,它简化了许多复杂的配置,让开发者可以专注于编写应用逻辑而不是基础设施,前几天公司平台首页崩溃了 504 Time-out,这里记录一下问题排查和解决的过程,需要的朋友可以参考下

前言

前几天公司平台首页崩溃了 504 Time-out,这里记录一下问题排查和解决的过程。

排查和解决

排查过程

  • step 1:检查测试环境、开发环境未出现问题;
  • step 2:检查生产环境流水线,没有最新部署,排除前端新部署代码影响;
  • step 3:检查生产环境其他页面/about-us页面展示正常,但是部分接口报错超时。猜测是因为生产环境接口超时导致首页的服务端请求返回超时,导致首页返回超时;
  • step 4:本地开发调用生产环境接口,将所有在getServerSideProps中发起的请求全部注释后,首页可以正常加载。

问题定位

首页开启了SSR渲染,getServerSideProps中的请求使用了简单的fetch请求,只对普通错误做了兜底,但没有考虑到请求超时的问题,请求超时导致了页面返回超时,首页报了504错误。

解决方案

优化方案

  • 放弃使用SSR渲染,全部采用客户端请求渲染;
  • 修改现有fetch,通过AbortControllersetTimeout手动添加超时处理;
  • getServerSideProps的请求方式从fetch迁移到axios,借助axios本身自带的超时配置,添加接口超时处理。

方案比较

  • 放弃SSR不可取,因为客户端并发请求返回顺序的问题可能会导致首页的入场动画混乱,且失去了部分首屏性能优化;
  • 修改fetch方法,需要手写大量代码,且AbortController是在Node.js 14.17.0+开始支持,当然也可以不去放弃掉请求,可以通过setTimeoutPromise.race提前reject,不过需要因为是自行实现,风险大。
  • axios是十分成熟的请求库,且项目中已经引入,通过axios为请求添加超时处理十分方便。

实际解决方案

fetch迁移到axios,借助axios已有的超时处理配置解决当前问题,添加首页对getServerSideProps中请求超时的兜底,服务端请求超时后,立即返回空数组。

首页所有的数据消费组件继续兜底,当从getServerSideProps中获取的数据为空数组时,会在客户端再发一次请求,尝试从客户端获取数据。

import axios from 'axios';

const ssrAxios = axios.create({
  timeout: 3000,
  timeoutErrorMessage: 'Request timed out'
});

export default ssrAxios;
export const getServerSideProps = async () => {
  const addr = process.env.API_ADDR;

  // 使用 Promise.allSettled 获取所有请求的结果
  const [
    list1Res,
    // ... ,
    list2Res,
  ] = await Promise.allSettled([
    ssrAxios.get(`${addr}/api/list1`),
    // ... ,
    ssrAxios.get(`${addr}/api/list2`),
  ]);

  // 处理每个请求的结果
  const list1 = handleFetchResult(list1Res, 'list1');
  // ... ;
  const list2 = handleFetchResult(list2Res, 'list2');

  return {
    props: {
      list1: list1 ?? [],
      // ... ,
      list2: list2 ?? []
    },
  };
};

// Helper function to handle fetch results
const handleFetchResult =  (result: PromiseSettledResult<any>, key: string) => {
  if (result.status === 'rejected') {
    console.error(`Failed to fetch ${key}:`, result.reason);
    return [];
  }

  const { data, success } = result.value.data;
  if (!success) {
    console.error(`Failed to fetch ${key}`);
    return [];
  }

  switch (key) {
    case 'list1':
      return data?.result || [];
	// ... ;
    case 'list2':
      return data?.result || [];
    default:
      return [];
  }
};

问题探究

问题猜测

  • 接口性能瓶颈:生产环境接口响应时间波动大,SSR并发请求存在短板
  • SSR 超时机制缺失:未设置合理的请求超时阈值,导致慢请求影响页面的生成和响应
  • 错误处理不完善:前端错误处理考虑不全面,未区分超时错误与常规错误,只做了无返回或返回错误的处理,没有对请求超时做兜底。

验证猜想

本地模拟接口返回超时,首页会无法成功加载。添加超时处理兜底后,首页其他内容可以正常展示。

询问deepseek后,得知Next.jsgetServerSideProps没有内置超时处理机制,因此长时间运行的getServerSideProps可能导致页面无法及时返回,甚至触发部署平台(如Vercel)的超时错误。

结论

首页开启了SSR渲染,Next.js 必须在完成getServerSideProps中的所有操作后才能生成页面并返回给客户端。 需要在得到所有需要的props后,才会返回整个页面。因为生产环境某个接口请求超时,并且没有正确处理,可能会导致整个getServerSideProps的执行时间延长,超过服务器的响应时间限制,从而使得页面无法及时返回,出现超时错误。

思考改进

思考

虽然是因为后端服务崩了,接口请求超时导致的问题,但是因为部分服务崩掉导致整个前端首页无法成功加载,作为前端开发人员的我还是有很大责任的。开发时我在对可能出现的错误进行兜底时,需要尽可能地考虑全面。

改进

服务端请求优化,错误处理添加对请求超时的处理。

① 首次访问使用SSR获取最新数据;

② 当SSR超时时自动降级到 CSR版本 ;

③ 保持首屏加载性能的同时提升可用性。

以上就是Next.js服务端渲染超时导致生产事故的排查和解决办法的详细内容,更多关于Next.js服务端渲染超时的资料请关注脚本之家其它相关文章!

相关文章

  • IE6 fixed的完美解决方案

    IE6 fixed的完美解决方案

    IE7已经支持position:fixed了,而我们的IE6呢?还继续使用js事件?消耗资源,破坏结构,画面闪耀。
    2011-03-03
  • 移动端界面的适配

    移动端界面的适配

    本文主要介绍了移动端页面适配相关知识,用于解决在所有手机上看到字体的大小都一样问题。下面跟着小编一起来看下吧
    2017-01-01
  • 实现局部遮罩与关闭原理及代码

    实现局部遮罩与关闭原理及代码

    实现局部遮罩,或许对某些朋友有着特殊的意义。局部遮罩的原理很简单另外加上关闭就有着另一番的效果,本文将介绍实现方法,感兴趣的朋友可以了解下,或许对你有所帮助
    2013-02-02
  • js/jquery解析json和数组格式的方法详解

    js/jquery解析json和数组格式的方法详解

    本篇文章主要是对js/jquery解析json和数组格式的方法进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2014-01-01
  • JavaScript中的数组遍历forEach()与map()方法以及兼容写法介绍

    JavaScript中的数组遍历forEach()与map()方法以及兼容写法介绍

    下面小编就为大家带来一篇JavaScript中的数组遍历forEach()与map()方法以及兼容写法介绍。小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-05-05
  • javascript addLoadEvent函数说明

    javascript addLoadEvent函数说明

    网页加载完整后会触发一个onload事件,默认地一个事件只能和一个函数绑定。
    2010-01-01
  • 浏览器兼容的JS写法总结

    浏览器兼容的JS写法总结

    浏览器兼容的JS写法总结,涵盖的内容很全面,感兴趣的小伙伴们可以参考一下
    2016-04-04
  • js判断是否为空和typeof的用法(详解)

    js判断是否为空和typeof的用法(详解)

    下面小编就为大家带来一篇js判断是否为空和typeof的用法(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-10-10
  • mui上拉加载更多下拉刷新数据的封装过程

    mui上拉加载更多下拉刷新数据的封装过程

    mui的上拉加载和下拉刷新类似,都属于pullRefresh插件。今天小编抽空给大家分享mui上拉加载更多下拉刷新数据的封装过程,需要的朋友参考下吧
    2017-11-11
  • uniapp禁止遮罩层下页面滚动的解决方法

    uniapp禁止遮罩层下页面滚动的解决方法

    在uniapp的开发中用过弹窗的都知道有个bug就是滑动弹窗的内容底部页面也会跟着滑动,所以这篇文章主要给大家介绍了关于uniapp禁止遮罩层下页面滚动的解决方法,需要的朋友可以参考下
    2023-09-09

最新评论