如何正确配置Ubuntu 20.04部署Node.js应用以解决服务端缓存问题
问题根因
你当前的问题核心是 AMdataPullDone 被定义为全局单例Promise实例:Node.js加载AMdataPullDone.js模块时就会立刻执行这个Promise,发起一次API拉取数据,后续所有请求复用的都是第一次resolve的缓存结果,不会再发起新的API请求。
之前Heroku免费实例看起来正常是因为免费实例会在无访问时自动休眠销毁进程,下次访问重新启动进程时会重新执行模块加载逻辑拉取新数据,而你的私有Ubuntu虚拟机进程长期运行,就会一直复用首次拉取的旧数据。
修复方案
1. 修改AMdataPullDone.js,将单例Promise改为可重复调用的函数
把原来直接导出Promise实例的逻辑,改成导出一个函数,每次调用函数都重新发起API请求、生成服务端渲染内容:
import React from "react"; import ReactDOMServer from "react-dom/server"; import App from "./src/components/App"; import generateToken from "./utils/generateToken"; import serverGetAMData from "./serverGetAMData"; // 改为导出函数,每次调用都会重新拉取数据 const getAMdata = () => new Promise((resolve, reject) => { generateToken() .then(({ access_token }) => { serverGetAMData( access_token, "URL_to_external_API" ) .then((segResult) => { const allData = { initialMarkup: ReactDOMServer.renderToString( <App initialData={segResult} /> ), initialData: segResult, }; return resolve(allData); }) .catch((err) => { return reject(err.response); }); }) .catch(console.error); }); export default getAMdata;
2. 修改server.js的根路由逻辑,每次请求都调用拉取函数
调整根路由的处理逻辑,每次收到访问请求时都调用新的getAMdata函数拉取最新数据:
// 导入的内容改为函数 import getAMdata from "./AMdataPullDone"; // ...其余代码保持不变 server.get("/", (req, res) => { // 每次请求都调用函数拉取最新数据 getAMdata().then(({ initialMarkup, initialData }) => { res.render("index", { initialMarkup, initialData, }); }).catch(console.error); });
可选优化
如果第三方API调用频率有限制,不想每次用户访问都发起API请求,可以增加一层内存缓存,设置缓存有效期(比如10分钟、1小时),只有缓存过期后才重新拉取数据,兼顾数据新鲜度和接口性能。
另外你当前package.json里的start命令用&后台运行进程的方式不稳定,进程崩溃后不会自动重启,建议安装pm2管理Node.js进程,部署更可靠。
内容的提问来源于stack exchange,提问作者kobra
相关产品推荐
相关产品推荐

