You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask API本地正常,部署Heroku后偶现返回过时数据求助

问题描述

我开发了一个投票网站,本地测试功能完全正常,但部署到Heroku后,会随机获取到错误/过时的JSON数据。比如选票原有候选人c1、c2、c3,移除c3后,c3有时仍会显示,有时则不会。即使在Firefox开发者工具中禁用缓存、用Ctrl+F5强制刷新也无法解决。

已尝试的解决措施

前端缓存破击与禁用缓存

在请求URL后添加时间戳参数,并设置请求头禁用缓存:

useEffect(() => {
    const fetchVotingStatus = async () => {
      try {
        const response = await fetch(`/get_voting_status?_t=${timestamp}`, {
          method: 'GET',
          headers: {
            'Cache-Control': 'no-cache, no-store',
            'Pragma': 'no-cache',
            'Expires': '0',
          },
        })
        const data = await response.json();
        if (!data.voting_status.President) {
          // 总统投票关闭,重定向到首页
          navigate('/');
        } else {
          // 投票开放,获取候选人列表
            fetchCandidates();
        }
      } catch (error) {
        console.error('获取投票状态出错:', error);
      }
    };

后端添加禁用缓存响应头

通过after_request中间件给指定路由添加禁用缓存的响应头:

def add_no_cache_headers(response):
    response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate, max-age=0'
    response.headers['Pragma'] = 'no-cache'
    response.headers['Expires'] = '0'
    response.headers['Access-Control-Allow-Origin'] = '*'
    return response

@app.after_request
def apply_no_cache(response):
    no_cache_routes = [
        'no_cache', 'get_voter',
        'getJsonVoteStatus', 'handle_submit_vote', 'open_vote', 'close_vote',
        'pres_candidates', 'memb_candidates', 'AO_candidates', 'SE_candidates',
        'MC_candidates', 'finance_candidates', 'IandB_candidates', 'othervote_prompt',
        'othervote_options', 'open_vote', 'close_vote'
    ]

    if request.endpoint in no_cache_routes:
        return add_no_cache_headers(response)
    return response
问题分析与解决建议

核心怀疑点:后端全局变量的持久化问题

本地测试通常是单进程运行,全局变量的修改会立即生效;但Heroku默认使用多进程/多实例部署,每个进程会维护自己的全局变量副本。当你修改了某个进程中的全局变量(比如移除候选人c3),其他进程的全局变量还是旧值,导致请求被分发到不同进程时,返回的数据随机出现新旧两种状态。这是最可能的原因。

具体解决步骤

  1. 替换全局变量为外部持久化存储
    把存储候选人列表、投票状态等数据的全局变量,换成数据库(比如PostgreSQL,Heroku支持免费版)、Redis缓存。所有数据读写都通过统一的外部存储,确保所有进程获取的是同一数据源。

  2. 验证Heroku的进程数量
    检查Heroku的dyno配置,默认可能启动多个web进程。可以临时设置为单进程测试:

    heroku ps:scale web=1
    

    如果单进程下问题消失,就坐实了多进程全局变量不一致的问题。

  3. 排查Heroku的路由缓存
    虽然你已经设置了缓存头,但Heroku的路由层(Router)可能会对GET请求做缓存。可以在响应头中添加Vary: Accept-Encoding,或者确保Cache-Control配置完全覆盖路由层的缓存策略。另外,确认你的get_voting_status等路由确实被包含在no_cache_routes列表中,没有拼写错误(比如getJsonVoteStatus和前端请求的/get_voting_status是否对应正确的endpoint名称)。

  4. 前端请求的幂等性验证
    确保fetchCandidates()函数也使用了同样的缓存破击策略(添加时间戳参数),避免候选人数据的请求被缓存。


内容的提问来源于stack exchange,提问作者user8394642

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 17:33:22