From 5c5b31db877bbda2642e67d59f14ecba63321c1a Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Mon, 17 Mar 2025 09:41:15 +0800 Subject: [PATCH] update --- api/settings.py | 27 ++++++++++++++++++++++++--- entrypoint.sh | 18 ++++++++++++++++-- pyproject.toml | 2 ++ requirements.txt | 2 ++ uv.lock | 26 ++++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 5 deletions(-) diff --git a/api/settings.py b/api/settings.py index a4d3c52..035793a 100644 --- a/api/settings.py +++ b/api/settings.py @@ -101,14 +101,30 @@ PROD_DATABASES = { "NAME": os.getenv("POSTGRES_DB"), "USER": os.getenv("POSTGRES_USER"), "PASSWORD": os.getenv("POSTGRES_PASSWORD"), - "HOST": os.getenv("POSTGRES_HOST"), + "HOST": os.getenv("POSTGRES_HOST", "pgbouncer"), + "PORT": "5432", + # 由于使用了 PgBouncer,这里不需要保持长连接 + "CONN_MAX_AGE": 0, + "OPTIONS": { + "application_name": "webpreview", # 便于在数据库中识别应用 + "sslmode": "disable", # PgBouncer 不支持 SSL + }, }, } PROD_CACHES = { "default": { - "BACKEND": "django.core.cache.backends.db.DatabaseCache", - "LOCATION": "webpreview_api_cache", + "BACKEND": "django.core.cache.backends.redis.RedisCache", + "LOCATION": os.getenv("REDIS_URL", "redis://webpreview-redis:6379/1"), + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + "CONNECTION_POOL_KWARGS": {"max_connections": 50}, + "SOCKET_CONNECT_TIMEOUT": 5, # 连接超时时间 + "SOCKET_TIMEOUT": 5, # 读写超时时间 + "RETRY_ON_TIMEOUT": True, # 超时时重试 + "MAX_CONNECTIONS": 1000, # 连接池最大连接数 + "HEALTH_CHECK_INTERVAL": 30, # 健康检查间隔 + }, } } @@ -116,7 +132,12 @@ if DEBUG: DATABASES = DEV_DATABASES else: DATABASES = PROD_DATABASES + # 使用 Redis 作为会话存储 SESSION_ENGINE = "django.contrib.sessions.backends.cache" + SESSION_CACHE_ALIAS = "default" + # 设置会话过期时间(24小时) + SESSION_COOKIE_AGE = 86400 + # 配置缓存 CACHES = PROD_CACHES # Password validation diff --git a/entrypoint.sh b/entrypoint.sh index 0232825..1b99b86 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,5 +1,19 @@ #!/bin/sh -python manage.py createcachetable +# 等待 Redis 和 PgBouncer 准备就绪 +sleep 5 + +# 执行数据库迁移 python manage.py migrate --noinput -exec gunicorn --bind 0.0.0.0:8000 api.asgi:application -k uvicorn.workers.UvicornWorker -w 5 \ No newline at end of file + +# 启动 Gunicorn +exec gunicorn api.asgi:application \ + --bind 0.0.0.0:8000 \ + --worker-class uvicorn.workers.UvicornWorker \ + --workers 4 \ + --threads 2 \ + --timeout 120 \ + --keep-alive 65 \ + --max-requests 1000 \ + --max-requests-jitter 50 \ + --log-level info \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index e957ea7..af2ed64 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,4 +14,6 @@ dependencies = [ "pydantic[email]>=2.10.6", "python-dotenv>=1.0.1", "uvicorn>=0.34.0", + "django-redis>=5.4.0", + "redis>=5.0.1", ] diff --git a/requirements.txt b/requirements.txt index 288583b..ea24863 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,6 +5,7 @@ django==5.1.6 django-cors-headers==4.7.0 django-extensions==3.2.3 django-ninja==1.3.0 +django-redis==5.4.0 dnspython==2.7.0 email-validator==2.2.0 gunicorn==23.0.0 @@ -16,6 +17,7 @@ psycopg-binary==3.2.5 pydantic==2.10.6 pydantic-core==2.27.2 python-dotenv==1.0.1 +redis==5.2.1 sqlparse==0.5.3 typing-extensions==4.12.2 uvicorn==0.34.0 diff --git a/uv.lock b/uv.lock index 1220069..c4f5d65 100644 --- a/uv.lock +++ b/uv.lock @@ -93,6 +93,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/00/72/fd2589323b40893d3224e174eeec0c4ce5a42c7d2d384d11ba269ad4d050/django_ninja-1.3.0-py3-none-any.whl", hash = "sha256:f58096b6c767d1403dfd6c49743f82d780d7b9688d9302ecab316ac1fa6131bb", size = 2423381 }, ] +[[package]] +name = "django-redis" +version = "5.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, + { name = "redis" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/83/9d/2272742fdd9d0a9f0b28cd995b0539430c9467a2192e4de2cea9ea6ad38c/django-redis-5.4.0.tar.gz", hash = "sha256:6a02abaa34b0fea8bf9b707d2c363ab6adc7409950b2db93602e6cb292818c42", size = 52567 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/f1/63caad7c9222c26a62082f4f777de26389233b7574629996098bf6d25a4d/django_redis-5.4.0-py3-none-any.whl", hash = "sha256:ebc88df7da810732e2af9987f7f426c96204bf89319df4c6da6ca9a2942edd5b", size = 31119 }, +] + [[package]] name = "dnspython" version = "2.7.0" @@ -242,6 +255,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863 }, ] +[[package]] +name = "redis" +version = "5.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/47/da/d283a37303a995cd36f8b92db85135153dc4f7a8e4441aa827721b442cfb/redis-5.2.1.tar.gz", hash = "sha256:16f2e22dff21d5125e8481515e386711a34cbec50f0e44413dd7d9c060a54e0f", size = 4608355 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/5f/fa26b9b2672cbe30e07d9a5bdf39cf16e3b80b42916757c5f92bca88e4ba/redis-5.2.1-py3-none-any.whl", hash = "sha256:ee7e1056b9aea0f04c6c2ed59452947f34c4940ee025f5dd83e6a6418b6989e4", size = 261502 }, +] + [[package]] name = "sqlparse" version = "0.5.3" @@ -291,10 +313,12 @@ dependencies = [ { name = "django-cors-headers" }, { name = "django-extensions" }, { name = "django-ninja" }, + { name = "django-redis" }, { name = "gunicorn" }, { name = "psycopg", extra = ["binary"] }, { name = "pydantic", extra = ["email"] }, { name = "python-dotenv" }, + { name = "redis" }, { name = "uvicorn" }, ] @@ -304,9 +328,11 @@ requires-dist = [ { name = "django-cors-headers", specifier = ">=4.7.0" }, { name = "django-extensions", specifier = ">=3.2.3" }, { name = "django-ninja", specifier = ">=1.3.0" }, + { name = "django-redis", specifier = ">=5.4.0" }, { name = "gunicorn", specifier = ">=23.0.0" }, { name = "psycopg", extras = ["binary"], specifier = ">=3.2.5" }, { name = "pydantic", extras = ["email"], specifier = ">=2.10.6" }, { name = "python-dotenv", specifier = ">=1.0.1" }, + { name = "redis", specifier = ">=5.0.1" }, { name = "uvicorn", specifier = ">=0.34.0" }, ]