當你的django項目中使用channels增加了websocket功能的時候,在使用runserver命令啟動時,既可以訪問http請求,又可以訪問websocket請求。但是當你使用uWSGI+nginx的來啟動項目的時候,你會發現http請求可用,但是websocket請求永遠是404的錯誤。這是為什么呢?
因為在我們的標准生產環境部署中,使用的事WSGI協議來啟動的我們的項目,也就是使用的wsgi.py這個文件來對接的uWSGI服務器。但是我們channels使用的ASGI協議,在我們使用uWSGI來啟動項目的時候,關於ASGI的一些配置他就找不到了。這就導致了你所有的websocket請求都是404。在查閱了大量的資料和閱讀了官方文檔以后終於解決了這個問題。
這個問題的解決有兩種方案:
-
啟用uWSGI來處理所有的http請求,另外開啟一個daphne服務來處理websocket請求。這樣的好處是按照請求類型分流,兩種請求方式互不干擾。
-
另外一種則是啟用daphne服務來處理http和websocket這兩種請求。在daphne服務內部他會根據請求類型的不同分開處理。讓你既可以訪問websocket又可以訪問http。
安裝Daphne
pip install daphne
在setting.py同級的目錄下新建一個asgi.py文件
""" ASGI entrypoint. Configures Django and then runs the application defined in the ASGI_APPLICATION setting. """ import os import django from channels.routing import get_default_application os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings") django.setup() application = get_default_application()
daphne -b 0.0.0.0 -p 8000 myproject.asgi:application
這種方式只是在后台啟動了你的項目,我們為了保證項目的穩定性,保證項目在意外死亡以后可以迅速的重啟,我們來使用supervisor來管理我們的daphne服務。
-
作用:它可以很方便的監聽、啟動、停止、重啟一個或多個進程。
-
用Supervisor管理的進程,當一個進程意外被殺死,supervisort監聽到進程死后,會自動將它重新拉起
-
很方便的做到進程自動恢復的功能,不再需要自己寫shell腳本來控制。
-
說白了,它真正有用的功能是倆個將非daemon(守護進程)程序變成deamon方式運行對程序進行監控,當程序退出時,可以自動拉起程序。
-
但是它無法控制本身就是daemon的服務。
yum install epel-release
yum install supervisor
不要使用pip下載supervisor,因為系統有python2.7和python3.6兩個版本,有時候會因為版本問題倒是supervisor啟動錯誤。而且pip的supervisor的安裝和使用方式也更為繁瑣一些。
在/etc/supervisord.d/文件夾下面配置被管理的服務的配置,然后啟動supervisor即可管理該服務。
下面使用supervisor來管理我們dephne服務

[program:asgi] directory=/code/shiyanloupro/ command=daphne -b 0.0.0.0 -p 8000 --proxy-headers shiyanloupro.asgi:application autostart=true autorestart=true stdout_logfile=/tmp/websocket.log #日志 redirect_stderr=true
supervisor的管理命令
[root@linux-node1 tmp]# supervisord -c /etc/supervisord.conf # 啟動supervisor [root@linux-node1 tmp]# systemctl enable supervisord # 開機自啟動 [root@linux-node1 tmp]# systemctl start supervisord # 啟動supervisord服務 [root@linux-node1 tmp]# supervisorctl reread # 重新讀取多有的配置文件 [root@linux-node1 tmp]# supervisorctl update # 配置文件修改后使用該命令加載新的配置,常和reread連用 [root@linux-node1 tmp]# supervisorctl reload # 重新啟動配置中的所有程序 [root@linux-node1 tmp]# supervisorctl status # 查看supervisor管理的所有進程狀態 [root@linux-node1 supervisord.d]# supervisorctl restart test # 啟動test程序 [root@linux-node1 supervisord.d]# supervisorctl stop all # 停止所有程序 [root@linux-node1 supervisord.d]# supervisorctl stop es # 停止名稱es程序(如果停止所有換成all) [root@linux-node1 tmp]# supervisorctl start es # 啟動項目名稱es程序

upstream channels-backend { server localhost:8000; } ... server { ... location / { try_files $uri @proxy_to_app; } ... location @proxy_to_app { proxy_pass http://channels-backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; } ... }
最后來開啟你的nginx服務和dephne服務即可。
systemctl restart nginx #重啟nginx supervisorctl reread #重新讀取supervisor的配置 supervisorctl update #更新supervisor的配置 supervisorctl start asgi #啟動asgi服務,也就是我們的daphne服務