无法使用 Nginx 和 Uvicorn 连接到 websocket
Not able to connect to websocket using Nginx and Uvicorn
我用 Django、Uvicorn、Nginx 和 Redis 构建了一个 docker 容器,并且正在使用 django-channels 但是当我 运行 它说它无法连接到 websocket 并且可以看到在浏览器控制台中:
WebSocket connection to 'ws://127.0.0.1:8080/ws/notifications/' failed
当我使用 Django 的 运行server 命令进行开发时,它工作正常,但是当我包含 Nginx 和 Uvicorn 时,它会中断。
Entrypoint.sh:
gunicorn roomway.asgi:application --forwarded-allow-ips='*' --bind 0.0.0.0:8000 -k uvicorn.workers.UvicornWorker
Nginx 配置:
upstream django {
server app:8000;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 8080;
location /static {
alias /vol/static;
}
location /ws/ {
proxy_pass http://0.0.0.0:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
location / {
proxy_pass http://django;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_redirect off;
proxy_buffering off;
}
}
settings.py:
CHANNEL_LAYERS={
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
'hosts': [('redis', 6379)], #Redis port
}
}
}
处理套接字的JS文件:
var wsStart = "ws://"
var webSocketEndpoint = wsStart + window.location.host + '/ws/notifications/'
const notificationSocket = new WebSocket(webSocketEndpoint)
asgi.py:
application = ProtocolTypeRouter({
"http": django_asgi_app,
"websocket": AuthMiddlewareStack(
URLRouter([
url(r'^ws/notifications/', NotificationConsumer.as_asgi()),
path("ws/<str:room_name>/", ChatConsumer.as_asgi())
])
)
})
Nginx 使用上面的代码抛出这个错误:
[error] 23#23: *4 connect() failed (111: Connection refused) while connecting to upstream, server: , request: "GET /ws/notifications/ HTTP/1.1", upstream: "http://0.0.0.0:8000/ws/notifications/", host: "127.0.0.1:8080"
当我将 proxy_pass
更改为 http://django
而不是 0.0.0.0
时,Nginx 不再抛出该错误,但我在控制台上收到相同的错误。同样这次 Django 抛出这些警告:
[WARNING] Unsupported upgrade request.
[WARNING] No supported WebSocket library detected. Please use 'pip install uvicorn[standard]', or install 'websockets' or 'wsproto' manually.
正如 Iain Shelvington 在评论中指出的那样,uvicorn 的基础安装中似乎没有包含 websockets
pip uninstall uvicorn
pip install 'uvicorn[standard]'
我用 Django、Uvicorn、Nginx 和 Redis 构建了一个 docker 容器,并且正在使用 django-channels 但是当我 运行 它说它无法连接到 websocket 并且可以看到在浏览器控制台中:
WebSocket connection to 'ws://127.0.0.1:8080/ws/notifications/' failed
当我使用 Django 的 运行server 命令进行开发时,它工作正常,但是当我包含 Nginx 和 Uvicorn 时,它会中断。
Entrypoint.sh:
gunicorn roomway.asgi:application --forwarded-allow-ips='*' --bind 0.0.0.0:8000 -k uvicorn.workers.UvicornWorker
Nginx 配置:
upstream django {
server app:8000;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 8080;
location /static {
alias /vol/static;
}
location /ws/ {
proxy_pass http://0.0.0.0:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
location / {
proxy_pass http://django;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_redirect off;
proxy_buffering off;
}
}
settings.py:
CHANNEL_LAYERS={
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
'hosts': [('redis', 6379)], #Redis port
}
}
}
处理套接字的JS文件:
var wsStart = "ws://"
var webSocketEndpoint = wsStart + window.location.host + '/ws/notifications/'
const notificationSocket = new WebSocket(webSocketEndpoint)
asgi.py:
application = ProtocolTypeRouter({
"http": django_asgi_app,
"websocket": AuthMiddlewareStack(
URLRouter([
url(r'^ws/notifications/', NotificationConsumer.as_asgi()),
path("ws/<str:room_name>/", ChatConsumer.as_asgi())
])
)
})
Nginx 使用上面的代码抛出这个错误:
[error] 23#23: *4 connect() failed (111: Connection refused) while connecting to upstream, server: , request: "GET /ws/notifications/ HTTP/1.1", upstream: "http://0.0.0.0:8000/ws/notifications/", host: "127.0.0.1:8080"
当我将 proxy_pass
更改为 http://django
而不是 0.0.0.0
时,Nginx 不再抛出该错误,但我在控制台上收到相同的错误。同样这次 Django 抛出这些警告:
[WARNING] Unsupported upgrade request.
[WARNING] No supported WebSocket library detected. Please use 'pip install uvicorn[standard]', or install 'websockets' or 'wsproto' manually.
正如 Iain Shelvington 在评论中指出的那样,uvicorn 的基础安装中似乎没有包含 websockets
pip uninstall uvicorn
pip install 'uvicorn[standard]'