Django频道使用redis设置在heroku泄漏内存

问题描述 投票:1回答:1

我按照这里有点过时的指南:https://blog.heroku.com/in_deep_with_django_channels_the_future_of_real_time_apps_in_django

并成功设置django应用程序与渠道:

> cat requirements.txt 
..
Django==1.10.6
asgi-redis==1.4.3
asgiref==1.1.2
channels==1.1.8
django-redis-cache==1.7.1
daphne==1.4.2
..

> cat Procfile 
web: daphne Landia.asgi:channel_layer --port $PORT --bind 0.0.0.0
worker: python manage.py runworker

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "asgi_redis.RedisChannelLayer",
        "CONFIG": {
            "hosts": [os.environ.get('REDIS_URL', 'redis://localhost:6379')],
        },
        "ROUTING": "Landia.routing.channel_routing",
    },
}

问题在于redis内存消耗从2M开始,并且逐渐地,非常缓慢地,超过48小时左右,当配置空间耗尽并且我的服务器基本上开始丢弃5XX时,增长到50MB。

它可以通过冲洗redis来修复。

我假设频道/ redis没有丢弃它发出的回复。

Screenshot with redis mem usage

任何想法如何修复,或至少调试此问题?

我也使用redis进行会话存储,我认为这是泄漏的来源:

> heroku redis:cli
> info
...
# Keyspace
db0:keys=119,expires=119,avg_ttl=49389233
db1:keys=7749,expires=7749,avg_ttl=1192828136
> select 1
> keys *
...
7757) :1:django.contrib.sessions.cachechnb5cafa749ec3b1b8b6fc20903750f
7758) :1:django.contrib.sessions.cachechn975ee5d806f3b27d6492e3fad8218
7759) :1:django.contrib.sessions.cachechn659906572f30ed388e655b75fbf87

这是django频道会话设置:

CHANNEL_SESSION_ENGINE = 'django.contrib.sessions.backends.cache'

CACHES = {
    'default': {
        'BACKEND': 'redis_cache.RedisCache',
        'LOCATION': os.environ.get('REDIS_URL', 'redis://localhost:6379')
    },
}

并在consumer.py中使用

@allowed_hosts_only
@channel_session_user_from_http
def ws_connect(message):
    ...


@channel_session_user
def ws_receive(message):
   ...


@channel_session_user
def ws_disconnect(message):
    ...

有没有办法清除断开连接时存储在redis中的会话信息,或者至少为redis键设置合理的TTL?

python django heroku memory-leaks django-channels
1个回答
1
投票

我最近遇到了同样的问题,我的调查让我写在django-users group上(简短的回答是django-channels不管理会话删除,只是等待它过期)。

我自己做了,因为一旦WebSocket客户端断开连接,会话就没有用了:

from channels.sessions import session_for_reply_channel

@channel_session_user
def ws_disconnect(message):
    ...
    session = session_for_reply_channel(message.reply_channel.name)
    session.delete(session.session_key)

希望这对你有用。

© www.soinside.com 2019 - 2024. All rights reserved.