[英]Configure nginx, uwsgi with flask and flask-socketio
我編寫了一個使用flask-socketio的 Flask 應用程序。 我在端口 8000 上運行燒瓶應用程序,在端口 3000 (react-webpack) 上分別運行客戶端應用程序。 它在開發模式下完美運行(Flask 中提供的 Web 服務器)。 但是,當嘗試使用 uwsgi 運行時,我遇到了問題。 下面將詳細介紹這些問題和配置。
wsgi.py (保持不變)
from cloud_app import app, sock
if __name__ == "__main__":
sock.run(app,host='0.0.0.0', debug=True, port=8000)
__init__.py (保持不變)
from flask import Flask
from flask_socketio import SocketIO
import secrets
app = Flask(__name__, static_url_path='/static')
app.secret_key = secrets.secret_key
sock = SocketIO(app)
from cloud_app import routes
routes.py (保持不變,明顯刪除實際邏輯)
...
from flask_cors import CORS
cors = CORS(app, resources={r"/*": {"origins": "*"}}, headers=['Content-Type'], expose_headers=['Access-Control-Allow-Origin'], supports_credentials=True)
@app.route('/example')
def example():
return 'example'
@sock.on('connect', namespace='/example')
def handle_example_connect():
sock.emit('example', 'Connected!\nAwaiting commands...\n', namespace='/example')
...
取自flask-socketio 和 uwsgi 的文檔,翻譯成 ini 文件
[uwsgi]
module = wsgi:app
master = true
processes = 5
buffer-size=32768
http-websockets = true
http = :8000
gevent = 1000
這里不需要 nginx 配置,因為 webpack 提供了這個,ini 文件被配置為直接響應 http 請求 ' http=:port '
控制台:這有時會打印它正在連接“已連接! 等待命令...'來自routes.py中的連接事件,但是它也會給出以下錯誤
POST http://localhost:8000/socket.io/?EIO=3&transport=polling&t=MgTjSL-&sid=5bf4758a09034805b1213fec92620e39 400 (BAD REQUEST)
GET http://localhost:8000/socket.io/?EIO=3&transport=polling&t=MgTjSMG&sid=5bf4758a09034805b1213fec92620e39 400 (BAD REQUEST)
websocket.js:112 WebSocket connection to 'ws://localhost:8000/socket.io/?EIO=3&transport=websocket&sid=5bf4758a09034805b1213fec92620e39' failed: Error during WebSocket handshake: Unexpected response code: 400
UWSGI 進程輸出:
...
[pid: 9402|app: 0|req: 16/33] 127.0.0.1 () {44 vars in 1316 bytes} [Thu May 9 13:55:41 2019] POST /socket.io/?EIO=3&transport=polling&t=MgTl93y&sid=b208e874c0e64330bdde35ae1773b4e0 => generated 2 bytes in 0 msecs (HTTP/1.1 200) 3 headers in 137 bytes (3 switches on core 996)
[pid: 9402|app: 0|req: 17/34] 127.0.0.1 () {40 vars in 1255 bytes} [Thu May 9 13:55:41 2019] GET /socket.io/?EIO=3&transport=polling&t=MgTl94Q&sid=b208e874c0e64330bdde35ae1773b4e0 => generated 12 bytes in 0 msecs (HTTP/1.1 200) 3 headers in 151 bytes (3 switches on core 996)
...
[pid: 9402|app: 0|req: 27/48] 127.0.0.1 () {44 vars in 1316 bytes} [Thu May 9 13:56:57 2019] POST /socket.io/?EIO=3&transport=polling&t=MgTlRbG&sid=5c4c38f18f6b47798978440edd181512 => generated 2 bytes in 0 msecs (HTTP/1.1 200) 3 headers in 137 bytes (3 switches on core 998)
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python2.7/dist-packages/flask_socketio/__init__.py", line 43, in __call__
start_response)
File "/usr/local/lib/python2.7/dist-packages/engineio/middleware.py", line 47, in __call__
return self.engineio_app.handle_request(environ, start_response)
File "/usr/local/lib/python2.7/dist-packages/socketio/server.py", line 360, in handle_request
return self.eio.handle_request(environ, start_response)
File "/usr/local/lib/python2.7/dist-packages/engineio/server.py", line 322, in handle_request
start_response(r['status'], r['headers'] + cors_headers)
IOError: headers already sent
...
取自這個問題。 .ini 文件
[uwsgi]
module = wsgi:app
master = true
processes = 5
buffer-size=32768
http-websockets = true
socket = example_app.sock
chmod-socket = 666
vaccum = true
die-on-term = true
nginx服務器
server {
listen 8000;
location /{
include uwsgi_params;
uwsgi_pass unix:/path/to/app/example_app.sock;
}
location /socket.io {
#include proxy_params;
proxy_http_version 1.1;
#proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://unix:/path/to/app/example_app.sock;
}
}
已注釋掉的選項以前未注釋
錯誤
安慰:
polling-xhr.js:263 GET http://localhost:8000/socket.io/?EIO=3&transport=polling&t=MgTotN9 502 (Bad Gateway)
Access to XMLHttpRequest at 'http://localhost:8000/socket.io/?EIO=3&transport=polling&t=MgTotN9' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
nginx 錯誤日志 (/var/log/nginx/error_log)
2019/05/09 14:16:35 [error] 11338#0: *1 upstream prematurely closed connection while reading response header from upstream, client: 127.0.0.1, server: , request: "GET /socket.io/?EIO=3&transport=polling&t=MgTpw36 HTTP/1.1", upstream: "http://unix:/path/to/app/example_app.sock:/socket.io/?EIO=3&transport=polling&t=MgTpw36", host: "localhost:8000", referrer: "http://localhost:3000/home"
請注意,在這兩個示例中,http 請求(由應用程序服務的請求)都可以正常工作,只有套接字調用會出現問題。
flask_socketio包裝應用程序並根據可用的內容和調用方式使用不同的協議。 它可以同時使用 HTTP 輪詢和本機 Websocket,這兩種不同的方法使用兩種不同的協議。
如果獨占使用eventlet或gevent ,則使用輪詢,即http請求。
如果使用UWSGI ,則使用原生 websocket (ws)。
如果gevent或eventlet與uwsgi一起使用,則使用來自uwsgi的本機 websocket 實現。
在我的例子中,我在客戶端上使用了socket.io ,它使用了 http 輪詢,因此當我嘗試使用 uwsgi 時,服務器期望一個本地 websocket 連接並且沒有任何處理 http 輪詢的東西。
所以為了解決我的問題,我測試了以下解決方案
請注意,根據 socketio 文檔,在使用多個 uwsgi 實例(這是其默認模式)時,您必須通過在創建 SocketIO 對象時指定message_queue選項來配置緩存服務器,例如 Redis。 如果您使用默認緩存,則客戶端將連接,但在與服務器通信時您將經常收到400 錯誤。 確認這是您的問題的一種方法是將 uwsgi 配置為僅運行一個進程,例如processes=1 。 如果這消除了問題,那么很可能是您的消息隊列。 有關如何配置它的信息可以在以下位置找到: https ://flask-socketio.readthedocs.io/en/latest/deployment.html#uwsgi-web-server
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.