多进程中的uwsgi + Flask-socketio

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

我正在尝试一步步构建一个websocket服务器。但是当我尝试使用 eventlet 或 gevent 时遇到了关键问题。

有我的服务器代码:

[uwsgi.ini]

[uwsgi]
chdir = /home/user/websocket
module=websocket:app
callable=app

processes=4
socket=/home/user/websocket/uwsgi.sock
uid = user
gid = user

chmod-socket=664

http-socket = :15000

log-reopen=true
die-on-term=true
master=true
vacuum=true

plugin=python3

virtualenv = /home/user/websocket/web

gevent = 100

[websocket.py]

from flask import Flask
from flask_socketio import SocketIO, send, emit

app = Flask(__name__)
socketio = SocketIO(app, logger=True, engineio_logger=True, cors_allowed_origins='*')


@socketio.on('connect')
def connected():
    print('-'*30, '[connect]', '-'*30)

@socketio.on('message')
def handle_message(data):
    print('-'*30, '[message]', '-'*30)
    print('received message: ' + data)
    send(data)  # Echoes back the received message

@socketio.on_error()  # This decorator handles all errors including connect_error
def handle_error(e):
    if isinstance(e, Exception):
        print('An error occurred:', str(e))
        # Here, you can log the error or perform any necessary action.
        # For example, you can check if it's a connect_error and take appropriate action.

@app.route("/")
def hello():
    return "Connected"

if __name__ == '__main__':
    socketio.run(app)

我跑了:

uwsgi --ini uwsgi.ini

但我收到错误:

Traceback (most recent call last):
  File "/home/user/websocket/web/lib/python3.10/site-packages/flask/app.py", line 1478, in __call__
    return self.wsgi_app(environ, start_response)
  File "/home/user/websocket/web/lib/python3.10/site-packages/flask_socketio/__init__.py", line 43, in __call__
    return super(_SocketIOMiddleware, self).__call__(environ,
  File "/home/user/websocket/web/lib/python3.10/site-packages/engineio/middleware.py", line 63, in __call__
    return self.engineio_app.handle_request(environ, start_response)
  File "/home/user/websocket/web/lib/python3.10/site-packages/socketio/server.py", line 428, in handle_request
    return self.eio.handle_request(environ, start_response)
  File "/home/user/websocket/web/lib/python3.10/site-packages/engineio/server.py", line 271, in handle_request
    packets = socket.handle_get_request(
  File "/home/user/websocket/web/lib/python3.10/site-packages/engineio/socket.py", line 90, in handle_get_request
    return getattr(self, '_upgrade_' + transport)(environ,
  File "/home/user/websocket/web/lib/python3.10/site-packages/engineio/socket.py", line 146, in _upgrade_websocket
    ws(environ, start_response)
  File "/home/user/websocket/web/lib/python3.10/site-packages/engineio/async_drivers/eventlet.py", line 40, in __call__
    raise RuntimeError('You need to use the eventlet server. '
RuntimeError: You need to use the eventlet server. See the Deployment section of the documentation for more information.

所以我尝试将“http-websockets = true”放入ini文件中,但得到了相同的错误。

这是我尝试过的客户端

[index.html]

<!DOCTYPE html>
<html>
<head>
    <title>Flask SocketIO Client</title>
    <script src="https://cdn.socket.io/4.0.0/socket.io.min.js"></script>
</head>
<body>
    <input type="text" id="messageInput" placeholder="Type a message...">
    <button onclick="sendMessage()">Send</button>
    <div id="messages"></div>

    <script>
        var socket = io('http://localhost:15000'); // Change to your server's address and port

        socket.on('connect', function() {
            console.log('Connected to the server.');
        });

        socket.on('message', function(data) {
            console.log('Received message:', data);
            document.getElementById('messages').innerText += data + '\n';
        });


        function sendMessage() {
            var message = document.getElementById('messageInput').value;
            console.log('sending...:', message);
            socket.emit('message', message);
            document.getElementById('messageInput').value = '';
        }
    </script>
</body>
</html>

[客户端.py]

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

if __name__ == '__main__':
    app.run(port=5001)  # Run on a different port than your SocketIO server

在客户端页面,显示此错误:

POST http://localhost:15000/socket.io/?EIO=4&transport=polling&t=Ondmm8T&sid=BooMMCC89x9oei5_AAAQ 400 (BAD REQUEST)
websocket.js:88 WebSocket connection to 'ws://localhost:15000/socket.io/?EIO=4&transport=websocket&sid=1_GSTZsrzqFdezzbAAAP' failed: 

请帮我解决这个问题。

python websocket uwsgi flask-socketio
1个回答
0
投票

听起来您安装了多个受支持的库,因此 Socket.IO 需要知道您要使用其中哪个。默认的是 eventlet,但您使用的是 uWSGI,因此您必须通过将

async_mode='gevent_uwsgi'
添加到您的
SocketIO()
构造函数来明确告诉它使用 uWSGI 逻辑。

我还建议您查看文档以了解如何配置uWSGI。您这样做的方式不支持多个工作进程,您应该运行一个工作进程,它可以通过 gevent 处理数百/数千个并发客户端。

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