Heroku部署的Django站点无请求时离线问题求助
Django部署在Heroku上频繁崩溃,Idle后需多次刷新才能恢复
我部署在Heroku上的Django网站频繁出现问题:当一段时间没有新请求触发时,站点会显示**“There's nothing here, yet.”**的提示,得多次刷新页面才能重新加载正常内容。我用了django_on_heroku和dj_database_url来配置Heroku的自动设置,怀疑是配置问题但找不到具体原因,相关配置文件和崩溃前的日志如下:
base.py
""" Django settings for setup project. Generated by 'django-admin startproject' using Django 4.0.6. For more information on this file, see https://docs.djangoproject.com/en/4.0/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/4.0/ref/settings/ """ import dj_database_url from dotenv import load_dotenv, find_dotenv from pathlib import Path, os # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent.parent # Application definition INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", # 自定义应用 "users.apps.UsersConfig", "accounts.apps.AccountsConfig", "produtos.apps.ProdutosConfig", "lojista.apps.LojistaConfig", # 第三方应用 "localflavor", "tempus_dominus", "django_extensions", ] MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "whitenoise.middleware.WhiteNoiseMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", ] ROOT_URLCONF = "setup.urls" TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [BASE_DIR / "templates"], "APP_DIRS": True, "OPTIONS": { "context_processors": [ "django.template.context_processors.debug", "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", ], }, }, ] WSGI_APPLICATION = "setup.wsgi.application" # Database # https://docs.djangoproject.com/en/4.0/ref/settings/#databases # DATABASES = { # "default": { # "ENGINE": "django.db.backends.sqlite3", # "NAME": BASE_DIR / "db.sqlite3", # } # } load_dotenv(find_dotenv()) DATABASES = { "default": dj_database_url.config(default="sqlite://db.slite3") } # Password validation # https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", }, { "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", }, { "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", }, { "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", }, ] # Internationalization # https://docs.djangoproject.com/en/4.0/topics/i18n/ LANGUAGE_CODE = "pt-Br" TIME_ZONE = "America/Sao_Paulo" USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.0/howto/static-files/ STATIC_URL = "/static/" STATIC_ROOT = BASE_DIR / "staticfiles" STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),) MEDIA_ROOT = os.path.join(BASE_DIR, "media") MEDIA_URL = "/media/" STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" # Default primary key field type # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" # 自定义用户模型 AUTH_USER_MODEL = "users.CustomUser" LOGIN_REDIRECT_URL = "/" LOGOUT_REDIRECT_URL = "/" TEMPUS_DOMINUS_LOCALIZE = True USE_L10N = True # 消息标签配置 from django.contrib.messages import constants as messages MESSAGE_TAGS = { messages.DEBUG: "alert-info", messages.INFO: "alert-info", messages.SUCCESS: "alert-success", messages.WARNING: "alert-warning", messages.ERROR: "alert-danger", }
prod.py
import django_on_heroku from decouple import config from .base import * SECRET_KEY = config("SECRET_KEY") DEBUG = False ALLOWED_HOSTS = [ "e-commerce-validity.herokuapp.com", ] DEBUG_PROPAGATE_EXPECTIONS = True LOGGING = { "version": 1, "disable_existing_loggers": False, "formatters": { "verbose": { "format": "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s", "datefmt": "%d/%b/%Y %H:%M:%S", }, "simple": {"format": "%(levelname)s %(message)s"}, }, "handlers": { "console": { "level": "DEBUG", "class": "logging.StreamHandler", }, }, "loggers": { "MYAPP": { "handlers": ["console"], 'level': os.getenv('DJANGO_LOG_LEVEL', 'DEBUG'), }, }, } # Heroku 配置 django_on_heroku.settings(locals(), staticfiles=False) del DATABASES["default"]["OPTIONS"]["sslmode"]
站点离线前的最后日志
2022-09-20T09:22:00.227176+00:00 app[web.1]: 10.1.5.86 - - [20/set/2022:06:22:00 -0300] "GET /media/products/2022/09/20/shopping_1.webp HTTP/1.1" 404 179 "https://e-commerce-validity.herokuapp.com/categoria/bebidas" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36" 2022-09-20T09:22:00.227188+00:00 heroku[router]: at=info method=GET path="/media/products/2022/09/20/shopping_1.webp" host=e-commerce-validity.herokuapp.com request_id=1b0debf4-5a8c-407d-a589-e17a602d23b4 fwd="179.66.122.162" dyno=web.1 connect=0ms service=1ms status=404 bytes=452 protocol=https 2022-09-20T09:22:01.046037+00:00 heroku[router]: at=info method=GET path="/produto/coca-cola-zero" host=e-commerce-validity.herokuapp.com request_id=1c953d08-eb6f-4dd2-8a97-de9f805d3df8 fwd="179.66.122.162" dyno=web.1 connect=0ms service=14ms status=200 bytes=5704 protocol=https 2022-09-20T09:22:01.046086+00:00 app[web.1]: 10.1.5.86 - - [20/set/2022:06:22:01 -0300] "GET /produto/coca-cola-zero HTTP/1.1" 200 5241 "https://e-commerce-validity.herokuapp.com/categoria/bebidas" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36" 2022-09-20T09:22:01.318131+00:00 heroku[router]: at=info method=GET path="/media/products/2022/09/20/shopping_1.webp" host=e-commerce-validity.herokuapp.com request_id=9316ccb6-f7fd-43ab-b545-47b1442f3f3d fwd="179.66.122.162" dyno=web.1 connect=0ms service=2ms status=404 bytes=452 protocol=https 2022-09-20T09:22:01.318224+00:00 app[web.1]: 10.1.5.86 - - [20/set/2022:06:22:01 -0300] "GET /media/products/2022/09/20/shopping_1.webp HTTP/1.1" 404 179 "https://e-commerce-validity.herokuapp.com/produto/coca-cola-zero" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36" 2022-09-20T09:22:02.380148+00:00 heroku[router]: at=info method=GET path="/carrinho/" host=e-commerce-validity.herokuapp.com request_id=e0d79cfd-4b64-4305-9025-a863cade10d3 fwd="179.66.122.162" dyno=web.1 connect=0ms service=11ms status=200 bytes=10006 protocol=https 2022-09-20T09:22:02.380234+00:00 app[web.1]: 10.1.5.86 - - [20/set/2022:06:22:02 -0300] "GET /carrinho/ HTTP/1.1" 200 9543 "https://e-commerce-validity.herokuapp.com/produto/coca-cola-zero" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36" 2022-09-20T09:22:02.655168+00:00 heroku[router]: at=info method=GET path="/media/products/2022/09/20/shopping.webp" host=e-commerce-validity.herokuapp.com request_id=55c3277d-ea8b-4506-a37e-a79f029845dc fwd="179.66.122.162" dyno=web.1 connect=0ms service=2ms status=404 bytes=452 protocol=https 2022-09-20T09:22:02.655208+00:00 app[web.1]: 10.1.5.86 - - [20/set/2022:06:22:02 -0300] "GET /media/products/2022/09/20/shopping.webp HTTP/1.1" 404 179 "https://e-commerce-validity.herokuapp.com/carrinho/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36"
问题分析与解决方案
你看到的**“There's nothing here, yet.”**是Heroku dyno休眠后首次请求的默认提示,但多次刷新才恢复,核心问题集中在数据库连接、dyno唤醒配置这两块,结合你的代码和日志,逐个修复:
1. 修复数据库SSL连接配置
你直接删除了sslmode参数,导致Heroku PostgreSQL连接不稳定,dyno唤醒时无法快速重建连接,请求失败。
修改prod.py的数据库配置:
# 替换原来的del语句 DATABASES["default"]["OPTIONS"]["sslmode"] = "require"
2. 配置数据库连接池,减少唤醒延迟
默认Django没有连接池,dyno唤醒时重新建立数据库连接的速度慢,导致首次请求超时。
修改base.py的数据库配置:
DATABASES = { "default": dj_database_url.config( default="sqlite://db.sqlite3", conn_max_age=600, # 保持连接10分钟,避免频繁重建 ssl_require=True ) }
3. 统一静态文件配置,避免冲突
你关闭了django_on_heroku的静态文件处理,但自己配置了Whitenoise,两者冲突可能导致站点启动异常。
修改prod.py的Heroku配置:
# 让django_on_heroku处理静态文件,再手动恢复Whitenoise配置 django_on_heroku.settings(locals(), staticfiles=True) STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
4. 优化dyno唤醒速度,避免超时
Heroku对dyno唤醒的首次请求有超时限制,如果站点启动慢就会返回默认页面。
- 清理
INSTALLED_APPS,移除没用的第三方库(比如如果django_extensions只在本地用,就移到dev配置里) - 用定时工具(比如UptimeRobot)每隔15分钟请求一次站点,防止dyno休眠
- 升级到专业级dyno,启用Preboot功能,实现无缝重启
5. 解决媒体文件404问题(辅助优化)
日志里大量媒体文件找不到,因为Heroku本地存储是临时的,dyno重启后文件会丢失。把媒体文件迁移到云存储(比如Cloudinary、AWS S3),不要存在Heroku本地目录。
内容的提问来源于stack exchange,提问作者xSkolz
相关产品推荐
相关产品推荐

