Конфигурация Python 3.7 Flask-SocketIO + uWSGI + nginx - PullRequest
0 голосов
/ 03 января 2019

Я размещаю два приложения python (app1 и app2) на машине с Ubuntu (16.04) под одной и той же установкой с разными версиями python (2.7 и 3.7), оба основаны на фреймворке Flask с использованием Flask-SocketIO, работающем на uWSGI ( 2.0.17.1) за прокси Nginx. Мне удалось успешно реализовать поддержку websocket в версии 2.7, но я не смог сделать то же самое в 3.7. Конфигурация Nginx и uwsgi одинаковы, за исключением разных плагинов для uwsgi (версия Python) В обоих случаях я использую сервер uwsgi websocket (через SocketIO) с очередью redis. Помимо проблемы websocket app2 работает просто отлично.

Python Setup

Python 2.7 Libs:

Настой == 0.12.2

Колба-SocketIO == 2.9.4

GEvent == 1.2.2

greenlet == 0.4.13

Python 3,7 Libs:

Настой == 1.0.2

Колба-Script == 2.0.6

GEvent == 1.3.7

greenlet == 0.4.15

uWSGI - 2.0.17.1

Рабочая конфигурация приложения 1:

__ __ INIT. Ру

  app = Flask(__name__)
    # SocketIO
    try:  # This step is required only for version deployed on UWSGI
        import uwsgi
        socketio = SocketIO(app, message_queue=app.config['REDIS_QUEUE_URL'])
    except ImportError:
        print 'Application runs outside of uWSGI context'
        socketio = SocketIO(app)

manage.py

from flask-script import Manager
from app1 import app

@manager.command
def runserver(host = None, port = None, socket = True):
    if not host:
        host = 'localhost'
    if not port:
        port = 5000
    if socket:
        socketio.run(app)
    else:
        app.run(host, port, debug=False)

app1.ini

  [uwsgi]
    plugins-dir = /usr/local/lib/uwsgi
    plugins = python27
    #application's base folder
    base = /home/ubuntu/app1

    #python module to import
    app = manage
    module = %(app)

    home = %(base)/venv
    virtualenv = %(base)/venv
    pythonpath = %(base)

    #socket file's location
    socket = %(base)/app1.sock

    #permissions for the socket file
    chmod-socket = 666

    callable = app

    logto = /var/log/uwsgi/%n.log

    processes = 20

    http-websockets = true

    gevent = 500

    vacuum = true

    die-on-term = true

    enable-threads = true

    master = true

app1-сайт

server {
    listen 1014 ssl default_server;
    server_name server_name_1;
    access_log /var/log/nginx/app1_access_log;
    error_log /var/log/nginx/app1_error_log;
    auth_basic off;
    # SSL only
    ssl on;
    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;

    ssl_session_timeout 5m;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

location /socket.io/ {
    include uwsgi_params;             
    uwsgi_pass unix:/home/ubuntu/app1/app1.sock;
    proxy_http_version 1.1;
    proxy_read_timeout 180s;
    proxy_buffering on;
    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-Proto $scheme;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
}

location / {deny all;}
location = /app1{ rewrite ^ /app1/; }
location /app1{
    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-Proto $scheme;
    proxy_pass          http://localhost:8080;
    proxy_read_timeout  90;
    proxy_redirect      http://server:8080 https://server_name_1:1014/app1;
        try_files $uri @app1; }

location @app1{
    include uwsgi_params;
    uwsgi_param SCRIPT_NAME /app1;
    uwsgi_modifier1 30;
    uwsgi_read_timeout 180s;
    uwsgi_send_timeout 180s;
    proxy_read_timeout 180s;
    uwsgi_pass unix:/home/ubuntu/app1/app1.sock;
}}

Конфигурация приложения 2

__ __ INIT. Ру

 def create_app():
        ...
        app = Flask(__name__)
        socket_io.init_app(app, message_queue = app.config['REDIS_URL'])
        ...
        return app

wsgi.py

 import uwsgi
    from gevent.monkey import patch_all

    patch_all()
    print('Patching all!')

    from app2 import create_app

    application = create_app()

app2.ini

[uwsgi]
plugins-dir = /usr/local/lib/uwsgi
plugins = python37

#application's base folder
base = /home/ubuntu/app2

home = %(base)/venv
virtualenv = %(base)/venv
pythonpath = %(base)

mount = /app2=%(base)/wsgi.py

callable = application

socket = %(base)/app2.sock

chmod-socket = 666

chdir = %(base)
attach-daemon = %(virtualenv)/bin/celery -A celery_worker.celery worker
attach-daemon = %(virtualenv)/bin/celery -A celery_worker.celery beat

logto = /var/log/uwsgi/%n.log

processes = 20

vacuum = true

die-on-term = true

enable-threads = true

master = true

manage-script-name = true

http-websockets = true

gevent = 5000

#Workaround for flask send_file() failing on python 3 and uwsgi
wsgi-disable-file-wrapper = true

app2-сайт

  server {
        listen 1015 ssl default_server;
        server_name server_name_2;
        access_log /var/log/nginx/app2_access_log;
        error_log /var/log/nginx/app2_error_log;


        auth_basic off;

        # SSL only
        ssl on;
        ssl_certificate /etc/nginx/ssl/nginx.crt;
        ssl_certificate_key /etc/nginx/ssl/nginx.key;

        ssl_session_timeout 5m;

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

    location /socket.io/ {
        include uwsgi_params;
        uwsgi_buffering off;
        uwsgi_pass unix:/home/ubuntu/app2/app2.sock;
        proxy_http_version 1.1;
        proxy_read_timeout 180s;
        proxy_buffering on;
        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-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    } 

    location / {deny all;}
    location = /app2 { rewrite ^ /app2/; }
    location /app2/ {
        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-Proto $scheme;
        proxy_pass          http://localhost:8080;
        proxy_read_timeout  90;
        proxy_redirect http://localhost:8080 https://server_name_2:1015/app2;
        try_files $uri @app2; }

    location @app2 {
        include uwsgi_params;
        uwsgi_read_timeout 180s;
        uwsgi_send_timeout 180s;
        proxy_read_timeout 180s;
        uwsgi_pass unix:/home/ubuntu/app2/app2.sock;
    }}

Судя по моим исследованиям, проблема в uWSGI, по какой-то причине он не получает никаких вызовов wss. С точки зрения клиента сокетное соединение Завершено вместо 101 Ожидание .

Проблема сохраняется независимо от того, каким клиентом я пользуюсь.

В приложении 1 я вижу каждую попытку и ошибку подключения к сокету в лог-файлах nginx и uwsgi (vassal), в случае app2 я вижу только 499 ошибок для каждой попытки подключения к сокету, без соответствующей записи в журнале вассала.

Изначально я обвинял сервер uwsgi websocket, на котором можно было разместить только 1 приложение, но я могу свободно дублировать app1 столько раз, сколько захочу, под разными вассалами и сайтами nginx, соединения с websocket хороши.

Что я пробовал

  • переключение между версиями lib (gevent должен быть> = 1.3.6)
  • используя сокет http вместо unix one
  • эксперименты с путями
  • жонглирование размерами буфера на nginx и uwsgi

Известны ли какие-либо проблемы с интеграцией Python 3.7 & uwsgi и SocketIO? У меня нет идей.

...