django - 使用 Daphne 部署 Django+Channels+Heroku:关闭 Postgre 连接
问题描述
我的 Django webapp 部署得很好,但是在对 Postgres 进行了几次查询后,我的数据库连接最大。
这是我对我的问题的理解:每个查询都打开到 Postgres 的数据库连接,但没有关闭,一旦达到最大连接数,结果就是数据库超时。
Heroku documentation for this error,但我认为无论通过升级启用多少新的连接,这些连接也将很快达到最大值。(或者我错了吗?)
pg:killall 不能解决我的问题。此应用程序中的解决方案不能是手动的。
我在 Django 中使用 Heroku 文档进行并发和数据库连接
这个SO question是相关的,但答案并不能解决我的问题
调试错误
FATAL: too many connections for role "DB_username"
错误回溯故障点
conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
在 cmd 中运行 heroku pg:info --app appname
=== DATABASE_URL
Plan: Hobby-dev
Status: Available
Connections: 20/20 <<<<<<<<<<<<<<<<<<<<<
PG Version: 12.4
Created: 2020-09-11 16:57 UTC
Data Size: 9.3 MB
Tables: 15
Rows: 85/10000 (In compliance)
Fork/Follow: Unsupported
Rollback: Unsupported
Continuous Protection: Off
Add-on: postgresql-infinite-00894
以下是我尝试过的事情:
- 设置 dj_database_url.config(conn_max_age==0,...)
- 使用 Pgbouncer 池连接
- 禁用服务器端游标
设置.py
# PRODUCTION SETTINGS
MIDDLEWARE.append('whitenoise.middleware.WhiteNoiseMiddleware')
DATABASE_URL = os.environ['DATABASE_URL']
DISABLE_SERVER_SIDE_CURSORS = True
SECRET_KEY = os.environ.get('SECRET_KEY')
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
#HEROKU SETTINGS
DATABASES['default'] = dj_database_url.config(conn_max_age=0, ssl_require=True)
django_heroku.settings(locals())
安装 pgbouncer buildpack
档案
web: bin/start-pgbouncer
web: daphne appname.asgi:application --port $PORT --bind 0.0.0.0 -v2
chatworker: python manage.py runworker --settings=appname.settings -v2
这是唯一对我有用的 Procfile,我看到其他论坛上的人抱怨你不能做 2 个网络测功机,这对我有用,pgbouncer 在部署时成功启动,daphne 也可以。使用 web 和 web2 崩溃应用程序。话虽如此,我愿意尝试任何和所有建议。
asgi.py 以防你好奇
import os
import django
from channels.routing import get_default_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Stonks.settings")
django.setup()
application = get_default_application()
围绕此的文档非常混乱,其他 SO/代码论坛没有提出任何我没有尝试过的建议。澄清这是 Django 代码问题、Heroku 配置问题还是 Daphne 问题也会非常有帮助。
消费者.py 示例
class StatsConsumer(AsyncConsumer):
"""Creates your stats websocket for each connected user"""
async def websocket_connect(self, event):
"""Connects to HTML and JS websocket for your stats"""
await self.send({
"type": "websocket.accept"
})
player = self.scope['user']
player_bids_list = await self.get_bids(player)
result_dict = await self.find_stats(player_bids_list)
await self.send({
"type": "websocket.send",
"text": json.dumps(result_dict),
})
async def websocket_receive(self, event):
"""Is called when yourStats.html pings server for updated data"""
player = self.scope['user']
player_bids_list = await self.get_bids(player)
result_dict = await self.find_stats(player_bids_list)
await self.send({
"type": "websocket.send",
"text": json.dumps(result_dict),
})
async def websocket_disconnect(self, event):
"""Is called when websocket disconnects"""
print("disconnected", event)
@database_sync_to_async
def get_profile(self, user):
"""fetches user profile funds asynchronously"""
return Profile.objects.get(user=user).funds
@database_sync_to_async
def get_bids(self, user):
"""fetches the connected user's bids and returns all bids based on id, asynchronously"""
userid = User.objects.get(username=user).id
result = Bid.objects.filter(username_id=userid)
returnlist = []
for i in result:
returnlist.append(i.amount)
return returnlist
解决方案
推荐阅读
- c++ - 为什么我的代码没有返回原始消息?
- python - 如何使用随机数从字典中打印字符串中的第一项并打印剩余的数字?
- ios - 根据用户输入显示某些文本
- machine-learning - 产品识别的字符串匹配算法
- java - 使用用户设置的配置文件将属性设置为 null
- vuejs2 - 如果容器最初被隐藏,如何在 Vue2Leaflet 中调整地图大小
- cuda - 通过在循环内使用 cuda 内核来降低性能
- java - 关于 BottomSheetDialog 可见性的问题
- wireshark - LIBPCAP 无法解析来自 Wireshark 的有效表达式
- javascript - 为什么我的页面加载项目,闪烁然后一切都消失了?