【问题标题】:Websocket error using Django Channels with EC2使用带有 EC2 的 Django 通道的 Websocket 错误
【发布时间】:2017-12-27 00:40:51
【问题描述】:

我正在尝试在 Django 中构建一个使用 Django Channels 的应用程序。我在 Elastic Beanstalk 上进行部署。我的理解是应用程序负载均衡器支持 websockets,我可以将 websocket 流量路由到适当的端口。 websockets 在我的 localhost:8000 上工作。我正在为我的通道层使用免费层 Redis Labs。

我按照本教程进行操作。 https://blog.mangoforbreakfast.com/2017/02/13/django-channels-on-aws-elastic-beanstalk-using-an-alb/#comment-43

按照本教程,我似乎可以让 Daphne 和工作人员在正确的端口上运行。我通过 SSH 连接到 EC2 实例以获取以下输出。

$ sudo /usr/local/bin/supervisorctl -c /opt/python/etc/supervisord.conf status
Daphne                           RUNNING   pid 4240, uptime 0:05:51
Worker:Worker_00                 RUNNING   pid 4242, uptime 0:05:51
Worker:Worker_01                 RUNNING   pid 4243, uptime 0:05:51
Worker:Worker_02                 RUNNING   pid 4244, uptime 0:05:51
Worker:Worker_03                 RUNNING   pid 4245, uptime 0:05:51
httpd                            RUNNING   pid 4248, uptime 0:05:51

我的 daphne.out.log 和 workers.out.log 看起来不错。

$ cat daphne.out.log 
2017-07-20 21:41:43,693 INFO     Starting server at tcp:port=5000:interface=0.0.0.0, channel layer mysite.asgi:channel_layer.
2017-07-20 21:41:43,693 INFO     HTTP/2 support not enabled (install the http2 and tls Twisted extras)
2017-07-20 21:41:43,694 INFO     Using busy-loop synchronous mode on channel layer
2017-07-20 21:41:43,694 INFO     Listening on endpoint tcp:port=5000:interface=0.0.0.0

$ cat workers.out.log 
2017-07-20 21:41:44,114 - INFO - runworker - Using single-threaded worker.
2017-07-20 21:41:44,120 - INFO - runworker - Using single-threaded worker.
2017-07-20 21:41:44,121 - INFO - runworker - Running worker against channel layer default (asgi_redis.core.RedisChannelLayer)
2017-07-20 21:41:44,121 - INFO - worker - Listening on channels http.request, websocket.connect, websocket.disconnect, websocket.receive
2017-07-20 21:41:44,126 - INFO - runworker - Using single-threaded worker.
2017-07-20 21:41:44,126 - INFO - runworker - Running worker against channel layer default (asgi_redis.core.RedisChannelLayer)
2017-07-20 21:41:44,126 - INFO - runworker - Running worker against channel layer default (asgi_redis.core.RedisChannelLayer)
2017-07-20 21:41:44,127 - INFO - worker - Listening on channels http.request, websocket.connect, websocket.disconnect, websocket.receive
2017-07-20 21:41:44,127 - INFO - worker - Listening on channels http.request, websocket.connect, websocket.disconnect, websocket.receive
2017-07-20 21:41:44,133 - INFO - runworker - Using single-threaded worker.
2017-07-20 21:41:44,136 - INFO - runworker - Running worker against channel layer default (asgi_redis.core.RedisChannelLayer)
2017-07-20 21:41:44,136 - INFO - worker - Listening on channels http.request, websocket.connect, websocket.disconnect, websocket.receive

从这里我更新了安全组设置并配置了负载均衡器并测试了我的网页。我没有使用 /ws/ 作为重新路由的路径,而是使用 /table/*,因为这些页面需要 websocket。

如果我使用 /ws/,我会收到此错误。

与“ws://example.com/table/1/”的 WebSocket 连接失败:WebSocket 握手期间出错:意外响应代码:404

如果我使用 /table/* 我会收到此错误。

与“ws://example.com/table/1/”的 WebSocket 连接失败:WebSocket 握手期间出错:意外响应代码:504

当我将负载均衡器的安全组设置更改为在端口 5000 上也允许 TCP 时,工作程序日志会更改。使用负载均衡器中的 /ws/ 路径规则,我现在可以在工作日志中得到它:

...
2017-07-20 21:41:44,136 - INFO - worker - Listening on channels http.request, websocket.connect, websocket.disconnect, websocket.receive
Not Found: /ws/
Not Found: /ws/
Not Found: /ws/
Not Found: /ws/
Not Found: /ws/
Not Found: /ws/

如果我使用 /table/* 路径,我的日志中会出现很长的错误。

2017-07-21 01:22:05,270 - ERROR - worker - Error processing message with consumer deal.consumers.ws_connect:
Traceback (most recent call last):
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/contrib/sessions/backends/base.py", line 193, in _get_session
    return self._session_cache
AttributeError: 'SessionStore' object has no attribute '_session_cache'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/db/backends/base/base.py", line 199, in ensure_connection
    self.connect()
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/db/backends/base/base.py", line 171, in connect
    self.connection = self.get_new_connection(conn_params)
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/db/backends/postgresql/base.py", line 175, in get_new_connection
    connection = Database.connect(**conn_params)
  File "/opt/python/run/venv/local/lib64/python3.4/site-packages/psycopg2/__init__.py", line 130, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
psycopg2.OperationalError: could not connect to server: Connection refused
    Is the server running on host "localhost" (127.0.0.1) and accepting
    TCP/IP connections on port 5432?


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/channels/worker.py", line 119, in run
    consumer(message, **kwargs)
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/channels/sessions.py", line 220, in inner
    result = func(message, *args, **kwargs)
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/channels/auth.py", line 71, in inner
    message.user = auth.get_user(fake_request)
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/contrib/auth/__init__.py", line 167, in get_user
    user_id = _get_user_session_key(request)
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/contrib/auth/__init__.py", line 59, in _get_user_session_key
    return get_user_model()._meta.pk.to_python(request.session[SESSION_KEY])
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/contrib/sessions/backends/base.py", line 48, in __getitem__
    return self._session[key]
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/contrib/sessions/backends/base.py", line 198, in _get_session
    self._session_cache = self.load()
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/contrib/sessions/backends/db.py", line 33, in load
    expire_date__gt=timezone.now()
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/db/models/manager.py", line 122, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/db/models/query.py", line 381, in get
    num = len(clone)
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/db/models/query.py", line 240, in __len__
    self._fetch_all()
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/db/models/query.py", line 1074, in _fetch_all
    self._result_cache = list(self.iterator())
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/db/models/query.py", line 52, in __iter__
    results = compiler.execute_sql()
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/db/models/sql/compiler.py", line 846, in execute_sql
    cursor = self.connection.cursor()
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/db/backends/base/base.py", line 231, in cursor
    cursor = self.make_debug_cursor(self._cursor())
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/db/backends/base/base.py", line 204, in _cursor
    self.ensure_connection()
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/db/backends/base/base.py", line 199, in ensure_connection
    self.connect()
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/db/utils.py", line 95, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/utils/six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/db/backends/base/base.py", line 199, in ensure_connection
    self.connect()
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/db/backends/base/base.py", line 171, in connect
    self.connection = self.get_new_connection(conn_params)
  File "/opt/python/run/venv/local/lib/python3.4/site-packages/django/db/backends/postgresql/base.py", line 175, in get_new_connection
    connection = Database.connect(**conn_params)
  File "/opt/python/run/venv/local/lib64/python3.4/site-packages/psycopg2/__init__.py", line 130, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
django.db.utils.OperationalError: could not connect to server: Connection refused
    Is the server running on host "localhost" (127.0.0.1) and accepting
    TCP/IP connections on port 5432?

不出所料,当我尝试使用 websockets 时,我得到了这个错误:

WebSocket 已经处于 CLOSING 或 CLOSED 状态。

知道我做错了什么吗?

【问题讨论】:

    标签: django amazon-ec2 websocket django-channels elastic-load-balancer


    【解决方案1】:

    好的,问题是当 Daphne 运行时它看不到环境变量。我将以下代码添加到了我的 supervisord.conf 文件中并且它起作用了:

    [program:Daphne]
    environment=PATH="/opt/python/run/venv/bin"
    **command=/bin/bash -c "source /opt/python/current/env && /opt/python/run/venv/bin/daphne -b 0.0.0.0 -p 5000 mysite.asgi:channel_layer"**
    directory=/opt/python/current/app
    autostart=true
    autorestart=true
    redirect_stderr=true
    stdout_logfile=/tmp/daphne.out.log
    
    [program:Worker]
    environment=PATH="/opt/python/run/venv/bin"
    **command=/bin/bash -c "source /opt/python/current/env && python manage.py runworker"**
    directory=/opt/python/current/app
    process_name=%(program_name)s_%(process_num)02d
    numprocs=4
    autostart=true
    autorestart=true
    redirect_stderr=true
    stdout_logfile=/tmp/workers.out.log
    

    【讨论】:

    • 它依赖于哪些环境变量?
    猜你喜欢
    • 2017-06-08
    • 2019-06-04
    • 2017-01-25
    • 2019-01-27
    • 2023-03-09
    • 2022-11-03
    • 2017-01-17
    • 2020-03-04
    • 2021-11-16
    相关资源
    最近更新 更多