Flask Full-stack + Flask-SocketIO + Nginx + Gunicorn[2/2]
前述の内容では、正しく実装されていない場合に発生する可能性のある問題から、WebSocketとSocketIOの理解とFlask-SocketIOの初期化方法について理解した.今回の記事では、FlashでFlask、Nginx、Guncornとソケット通信を行う簡単な例のソースコード、クライアント構成方法、およびFlaskサンプルコードについて説明します.
4. Nginx + Gunicorn + Flask-SocketIO
4. Nginx + Gunicorn + Flask-SocketIO
4.1 Nginx config
Nginx config of Flask-SocketIO Docs
Flask SocketIOの場合、Docsは次のNginx設定を提供します.server {
listen 80;
server_name _;
location / {
include proxy_params;
proxy_pass http://127.0.0.1:5000;
}
location /static {
alias <path-to-your-application>/static;
expires 30d;
}
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://127.0.0.1:5000/socket.io;
}
}
設定では、proxy passを使用して内部駆動フラスコを接続し、location /socket.io
を使用してsocketを接続します.入力ioのパケットヘッダをアップグレードして転送する内容が書かれています.また、上記の設定はhttpでのみ記述されるため、httpを構成するために追加の設定が必要です.
Nginx config + SSL
# Nginx configuration
# HTTP - Listen 80
server {
listen 80;
# listen [::]:80;
server_name example.com;
access_log /var/www/some/logs/http/access.log;
error_log /var/www/some/logs/http/error.log;
# include /etc/nginx/snippets/letsencrypt.conf;
location ~ /\.well-known/acme-challenge/ {
allow all;
root /var/www/letsencrypt;
}
location / {
return 301 https://$server_name$request_uri;
# expires epoch;
}
}
# HTTPS - Listen 443
server {
listen 443 ssl;
# listen [::]:443;
server_name example.com;
access_log /var/www/some/logs/https/access.log;
error_log /var/www/some/logs/https/error.log;
# letsencrypt should add new group.
# And also chgrp /etc/letsencrypt/live, /etc/letsencrypt/archive
# /etc/nginx.conf ==> user [added user name]
ssl_certificate /etc/letsencrypt/live/$server_name/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$server_name/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3 SSLv3;
ssl_ciphers ALL:!ADH:!EXPORT56:!RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
ssl_prefer_server_ciphers on;
location / {
include proxy_params;
# proxy_pass http://unix:/var/www/some/some.sock;
proxy_pass http://127.0.0.1:8080;
}
location /socket.io {
include proxy_params;
proxy_http_version 1.1;
proxy_buffering off;
proxy_redirect off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://127.0.0.1:8080/socket.io;
}
}
ここでlocation/socket.ioセクションでは、proxy setヘッダのUpgrade、Connectionがコアに必要なセクションです.ソケット通信を行うには、http、httpsではなくws(またはwss)を使用して通信する必要があります.そうでない場合、ソケット通信は非常に不安定であり、各接続のクライアントは新しい接続を要求し続けるため、101アップグレードパッケージを使用してWebソケット接続を実行する必要があります.
4.2 Gunicorn
Guncorn位置の確認
サービスfile内のコンテンツを作成するには、まずgunicornインストール場所を見つける必要があります.$ which -a gunicorn
/usr/local/bin/gunicorn
/usr/bin/gunicorn
/bin/gunicorn
サービスファイルの作成
/etc/systemd/systemm/ディレクトリ内/etc/systemd/systemm/[servicename].サービスの作成sudo vim /etc/systemd/system/myproject.service
確認したGuncorn位置を使用して、ExecStartコマンドを使用して実行位置を作成します.# /etc/systemd/system/~~~.service
[Unit]
Description=Gunicorn instance to serve myflask
After=network.target
[Service]
# You can change your own account
User=flaskuser
# You can change your own group
Group=flaskcert
# /home/userme/myproject
WorkingDirectory=/var/www/some
# "PATH=/home/userme/myproject/myproject-env/bin"
Environment="PATH=/usr/bin"
# You must chown working directory
ExecStart=/usr/bin/gunicorn --worker-class eventlet -w 1 -b 127.0.0.1:8080 wsgi:app
[Install]
WantedBy=multi-user.target
エラーと解決方法
gunicorn-worker-class eventlettを使用するには、適切なeventlettバージョンをインストールする必要があります.eventlettのバージョンが適切でない場合、次のエラーが発生する可能性があります.$ gunicorn --worker-class eventlet -w 1 -b 127.0.0.1:8080 wsgi:app
...
ImportError: cannot import name 'ALREADY_HANDLED' from 'eventlet.wsgi'
...
これらのエラーが発生した場合は、解決策を添付します.$ pip3 install eventlet==0.30.2
4.3 Flask-SocketIO
sockets/init.pyの作成
# file : app/sockets/__init__.py
from flask_socketio import SocketIO
socketio = SocketIO()
init.pyの作成
# file : app/__init__.py
from flask import Flask
from app.sockets import socketio # app/sockets/__init__.py에 선언된 socketio 변수
def create_app():
app = Flask(__name__)
# Your logics...
# Set Config
app.config.from_object(config)
with app.app_context():
# Socket.IO
socketio.init_app( app,
async_mode="eventlet",
cors_allowed_origins="*",
logger=True,
engineio_logger=True)
# Your logics...
return app
5.クライアント構成(Bootstrap+Javascript)
クライアント構成は、完全なスタックとしてFlashを使用し、Bootstrap+socketです.ioライブラリなどの方法を紹介したいと思います.
5.1 Socket.iojavascriptサンプルコード
// important!! - socket.io version
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js" integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA==" crossorigin="anonymous"></script>
var namespace = "/socket/main";
var socket_main = io.connect(namespace, { transports : ['websocket',],
upgrade: true, // 삭제해도 무관
secure: true }); // 삭제해도 무관
socket_main.on('announce', function(msg) {
console.log(msg);
}); // socket_main.on end
上のようにcdnからioライブラリをインポートし、コードを記述できます.ただし、Flask-StocketIOでは、socketは特定バージョンのsocketではありません.ioライブラリを使用すると、バージョンが一致しないエラーが発生する可能性があります.なお、ここでupgrade、secure部分はhttp、httpsなどの環境によって異なるので削除しても構わない.(Defaultに設定されているため)
例示コードでは、socket_main
は任意の変数であり、on('~~',function(msg){})関数内の通知も任意の文字列値である.これは、emit()関数を使用して特定の値を渡すときに指標として使用されます.
6.Flashサンプルソースコード
6.1 Flaskでのsocket通信
Flask内でソケット通信を実現するのは、論理を実現する方法によって異なる場合があります.ここでは、ソースコードの例を簡単に説明します.
app/sockets/init.py
from flask_socketio import SocketIO
socketio = SocketIO()
test.py
# Your logics...
from app.sockets import socketio
@app.route("/test", methods=['GET'])
def test():
socketio.emit( "announce",
{"test" : "test success"},
namespace='/socket/main',
broadcast=True)
return "Some text"
ここでテストpyソースでsocketio.emit()
関数で適切なパラメータを設定し/test pathに入ると、適切なフィードバックが得られます.
終了時..。
研究の過程で多くの曲折を経験した.特にFlask-StocketIOを構成するコンテンツでは、socketio.init_app()
関数を使用して構成されたコンテンツが見つかりません.そのため、ほとんどが実験結果に基づいて文章を書いている.特に、Flask-SocketIOを使用してテスト経験を記述したブログの大部分を見ても、適切なフィードバックが得られなかった.
私を死なせる方法。
成功の数日前まで101 Upgradeパケット要求は失敗した.この時点でFlask+Flask-StocketIO+Guncorn+NginxとSSLの応用が完了した.しかし,Web上でWeb Socketを要求すると,400 Badリクエストが応答として常に存在する.このときのサーバドライバ環境.
Guncornコマンド
$ gunicorn -w 3 -b 127.0.0.1:8080 wsgi:app
このときgevent,eventlett,geventtwebsocket.gunicorn.workers.GeventWebSocketWorkerなどのコマンドは使用されていません.これまでGuniornの問題ではなく、nginxの問題だったと思います.
Pythonドライバ
# file : app/__init__.py
from flask import Flask
from app.sockets import socketio # app/sockets/__init__.py에 선언된 socketio 변수
def create_app():
app = Flask(__name__)
# Your logics...
# Set Config
app.config.from_object(config)
with app.app_context():
# Socket.IO
socketio.init_app( app,
async_mode="gevent",
cors_allowed_origins="*")
# Your logics...
return app
Nginx設定
Nginxの設定は、前述のアプリケーションSSLのプロファイルと同じです.
実験を続けていくうちに、できる限りのテストが行われても400 Badのリクエストは同じなのでGuncornで問題点を探します.最初にテストするコマンドは次のとおりです.$ pip3 install gevent
$ gunicorn -w 3 -b 127.0.0.1:8080 wsgi:app
このとき最も重要な変化101 Upgradeパケットは正常に伝送され、応答も正常に回復する.図に示すように、101交換プロトコルは正常に戻ります.この時点で進めない研究が進んでいくのは安心だ.
通信だけが正常ではない.次のエラーが発生し、スロットが不安定でサービスが提供されないためです.しかしこのとき,NginxではなくGunicornの設定を変更すると,答えの直感が得られるので,種々の実験を行った.[2021-08-01 18:52:03 +0000] [62584] [ERROR] Socket error processing request.
Traceback (most recent call last):
File "/usr/local/lib/python3.8/dist-packages/gunicorn/workers/sync.py", line 135, in handle
self.handle_request(listener, req, client, addr)
File "/usr/local/lib/python3.8/dist-packages/gunicorn/workers/sync.py", line 191, in handle_request
six.reraise(*sys.exc_info())
File "/usr/local/lib/python3.8/dist-packages/gunicorn/six.py", line 625, in reraise
raise value
File "/usr/local/lib/python3.8/dist-packages/gunicorn/workers/sync.py", line 183, in handle_request
resp.close()
File "/usr/local/lib/python3.8/dist-packages/gunicorn/http/wsgi.py", line 409, in close
self.send_headers()
File "/usr/local/lib/python3.8/dist-packages/gunicorn/http/wsgi.py", line 329, in send_headers
util.write(self.sock, util.to_bytestring(header_str, "ascii"))
File "/usr/local/lib/python3.8/dist-packages/gunicorn/util.py", line 304, in write
sock.sendall(data)
OSError: [Errno 9] Bad file descriptor
Guncorn指令実験
まずGuncorn命令を実験するために種々の実験を行った.# Failed - 502 Bad Gateway
gunicorn -k gevent -w 1 -b 127.0.0.1:8080 wsgi:app
# Failed - 502 Bad Gateway
$ gunicorn -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker -w 1 wsgi:app
# Failed - ImportError: cannot import name 'ALREADY_HANDLED' from 'eventlet.wsgi'
$ gunicorn --worker-class eventlet -w 1 -b 127.0.0.1:8080 wsgi:app
# Success - pip3 install eventlet==0.30.2
$ gunicorn --worker-class eventlet -w 1 -b 127.0.0.1:8080 wsgi:app
上記の過程でeventlettは満足のいく結果を得た.ただし、eventlettをインストールする場合は、バージョンをダウングレードする必要があります.
ポスト
上記の実験過程による研究では,参考になる資料の欠如に加えて,ウェブサイト,Nginx,Guncornの理解が欠けている.しかし、見慣れない環境構成やライブラリの使用については、1週間の研究時間が思ったより短く、満足のいく結果が得られたことをうれしく思います.研究時間が足りなかったので仮眠して行ったのですが…たとえ困難にぶつかっても、たまに成功した結果が出ても、眠れず、徹夜で研究します.今回の研究では、Python Flashフレームワークを活用してより多くの機能を提供する方法について理解しました.
Reference
この問題について(Flask Full-stack + Flask-SocketIO + Nginx + Gunicorn[2/2]), 我々は、より多くの情報をここで見つけました
https://velog.io/@kkamikoon/Flask-Full-stack-Flask-SocketIO-Nginx-Gunicorn22
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
server {
listen 80;
server_name _;
location / {
include proxy_params;
proxy_pass http://127.0.0.1:5000;
}
location /static {
alias <path-to-your-application>/static;
expires 30d;
}
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://127.0.0.1:5000/socket.io;
}
}
# Nginx configuration
# HTTP - Listen 80
server {
listen 80;
# listen [::]:80;
server_name example.com;
access_log /var/www/some/logs/http/access.log;
error_log /var/www/some/logs/http/error.log;
# include /etc/nginx/snippets/letsencrypt.conf;
location ~ /\.well-known/acme-challenge/ {
allow all;
root /var/www/letsencrypt;
}
location / {
return 301 https://$server_name$request_uri;
# expires epoch;
}
}
# HTTPS - Listen 443
server {
listen 443 ssl;
# listen [::]:443;
server_name example.com;
access_log /var/www/some/logs/https/access.log;
error_log /var/www/some/logs/https/error.log;
# letsencrypt should add new group.
# And also chgrp /etc/letsencrypt/live, /etc/letsencrypt/archive
# /etc/nginx.conf ==> user [added user name]
ssl_certificate /etc/letsencrypt/live/$server_name/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$server_name/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3 SSLv3;
ssl_ciphers ALL:!ADH:!EXPORT56:!RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
ssl_prefer_server_ciphers on;
location / {
include proxy_params;
# proxy_pass http://unix:/var/www/some/some.sock;
proxy_pass http://127.0.0.1:8080;
}
location /socket.io {
include proxy_params;
proxy_http_version 1.1;
proxy_buffering off;
proxy_redirect off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://127.0.0.1:8080/socket.io;
}
}
$ which -a gunicorn
/usr/local/bin/gunicorn
/usr/bin/gunicorn
/bin/gunicorn
sudo vim /etc/systemd/system/myproject.service
# /etc/systemd/system/~~~.service
[Unit]
Description=Gunicorn instance to serve myflask
After=network.target
[Service]
# You can change your own account
User=flaskuser
# You can change your own group
Group=flaskcert
# /home/userme/myproject
WorkingDirectory=/var/www/some
# "PATH=/home/userme/myproject/myproject-env/bin"
Environment="PATH=/usr/bin"
# You must chown working directory
ExecStart=/usr/bin/gunicorn --worker-class eventlet -w 1 -b 127.0.0.1:8080 wsgi:app
[Install]
WantedBy=multi-user.target
$ gunicorn --worker-class eventlet -w 1 -b 127.0.0.1:8080 wsgi:app
...
ImportError: cannot import name 'ALREADY_HANDLED' from 'eventlet.wsgi'
...
$ pip3 install eventlet==0.30.2
# file : app/sockets/__init__.py
from flask_socketio import SocketIO
socketio = SocketIO()
# file : app/__init__.py
from flask import Flask
from app.sockets import socketio # app/sockets/__init__.py에 선언된 socketio 변수
def create_app():
app = Flask(__name__)
# Your logics...
# Set Config
app.config.from_object(config)
with app.app_context():
# Socket.IO
socketio.init_app( app,
async_mode="eventlet",
cors_allowed_origins="*",
logger=True,
engineio_logger=True)
# Your logics...
return app
クライアント構成は、完全なスタックとしてFlashを使用し、Bootstrap+socketです.ioライブラリなどの方法を紹介したいと思います.
5.1 Socket.iojavascriptサンプルコード
// important!! - socket.io version
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js" integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA==" crossorigin="anonymous"></script>
var namespace = "/socket/main";
var socket_main = io.connect(namespace, { transports : ['websocket',],
upgrade: true, // 삭제해도 무관
secure: true }); // 삭제해도 무관
socket_main.on('announce', function(msg) {
console.log(msg);
}); // socket_main.on end
上のようにcdnからioライブラリをインポートし、コードを記述できます.ただし、Flask-StocketIOでは、socketは特定バージョンのsocketではありません.ioライブラリを使用すると、バージョンが一致しないエラーが発生する可能性があります.なお、ここでupgrade、secure部分はhttp、httpsなどの環境によって異なるので削除しても構わない.(Defaultに設定されているため)例示コードでは、
socket_main
は任意の変数であり、on('~~',function(msg){})関数内の通知も任意の文字列値である.これは、emit()関数を使用して特定の値を渡すときに指標として使用されます.6.Flashサンプルソースコード
6.1 Flaskでのsocket通信
Flask内でソケット通信を実現するのは、論理を実現する方法によって異なる場合があります.ここでは、ソースコードの例を簡単に説明します.
app/sockets/init.py
from flask_socketio import SocketIO
socketio = SocketIO()
test.py
# Your logics...
from app.sockets import socketio
@app.route("/test", methods=['GET'])
def test():
socketio.emit( "announce",
{"test" : "test success"},
namespace='/socket/main',
broadcast=True)
return "Some text"
ここでテストpyソースでsocketio.emit()
関数で適切なパラメータを設定し/test pathに入ると、適切なフィードバックが得られます.
終了時..。
研究の過程で多くの曲折を経験した.特にFlask-StocketIOを構成するコンテンツでは、socketio.init_app()
関数を使用して構成されたコンテンツが見つかりません.そのため、ほとんどが実験結果に基づいて文章を書いている.特に、Flask-SocketIOを使用してテスト経験を記述したブログの大部分を見ても、適切なフィードバックが得られなかった.
私を死なせる方法。
成功の数日前まで101 Upgradeパケット要求は失敗した.この時点でFlask+Flask-StocketIO+Guncorn+NginxとSSLの応用が完了した.しかし,Web上でWeb Socketを要求すると,400 Badリクエストが応答として常に存在する.このときのサーバドライバ環境.
Guncornコマンド
$ gunicorn -w 3 -b 127.0.0.1:8080 wsgi:app
このときgevent,eventlett,geventtwebsocket.gunicorn.workers.GeventWebSocketWorkerなどのコマンドは使用されていません.これまでGuniornの問題ではなく、nginxの問題だったと思います.
Pythonドライバ
# file : app/__init__.py
from flask import Flask
from app.sockets import socketio # app/sockets/__init__.py에 선언된 socketio 변수
def create_app():
app = Flask(__name__)
# Your logics...
# Set Config
app.config.from_object(config)
with app.app_context():
# Socket.IO
socketio.init_app( app,
async_mode="gevent",
cors_allowed_origins="*")
# Your logics...
return app
Nginx設定
Nginxの設定は、前述のアプリケーションSSLのプロファイルと同じです.
実験を続けていくうちに、できる限りのテストが行われても400 Badのリクエストは同じなのでGuncornで問題点を探します.最初にテストするコマンドは次のとおりです.$ pip3 install gevent
$ gunicorn -w 3 -b 127.0.0.1:8080 wsgi:app
このとき最も重要な変化101 Upgradeパケットは正常に伝送され、応答も正常に回復する.図に示すように、101交換プロトコルは正常に戻ります.この時点で進めない研究が進んでいくのは安心だ.
通信だけが正常ではない.次のエラーが発生し、スロットが不安定でサービスが提供されないためです.しかしこのとき,NginxではなくGunicornの設定を変更すると,答えの直感が得られるので,種々の実験を行った.[2021-08-01 18:52:03 +0000] [62584] [ERROR] Socket error processing request.
Traceback (most recent call last):
File "/usr/local/lib/python3.8/dist-packages/gunicorn/workers/sync.py", line 135, in handle
self.handle_request(listener, req, client, addr)
File "/usr/local/lib/python3.8/dist-packages/gunicorn/workers/sync.py", line 191, in handle_request
six.reraise(*sys.exc_info())
File "/usr/local/lib/python3.8/dist-packages/gunicorn/six.py", line 625, in reraise
raise value
File "/usr/local/lib/python3.8/dist-packages/gunicorn/workers/sync.py", line 183, in handle_request
resp.close()
File "/usr/local/lib/python3.8/dist-packages/gunicorn/http/wsgi.py", line 409, in close
self.send_headers()
File "/usr/local/lib/python3.8/dist-packages/gunicorn/http/wsgi.py", line 329, in send_headers
util.write(self.sock, util.to_bytestring(header_str, "ascii"))
File "/usr/local/lib/python3.8/dist-packages/gunicorn/util.py", line 304, in write
sock.sendall(data)
OSError: [Errno 9] Bad file descriptor
Guncorn指令実験
まずGuncorn命令を実験するために種々の実験を行った.# Failed - 502 Bad Gateway
gunicorn -k gevent -w 1 -b 127.0.0.1:8080 wsgi:app
# Failed - 502 Bad Gateway
$ gunicorn -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker -w 1 wsgi:app
# Failed - ImportError: cannot import name 'ALREADY_HANDLED' from 'eventlet.wsgi'
$ gunicorn --worker-class eventlet -w 1 -b 127.0.0.1:8080 wsgi:app
# Success - pip3 install eventlet==0.30.2
$ gunicorn --worker-class eventlet -w 1 -b 127.0.0.1:8080 wsgi:app
上記の過程でeventlettは満足のいく結果を得た.ただし、eventlettをインストールする場合は、バージョンをダウングレードする必要があります.
ポスト
上記の実験過程による研究では,参考になる資料の欠如に加えて,ウェブサイト,Nginx,Guncornの理解が欠けている.しかし、見慣れない環境構成やライブラリの使用については、1週間の研究時間が思ったより短く、満足のいく結果が得られたことをうれしく思います.研究時間が足りなかったので仮眠して行ったのですが…たとえ困難にぶつかっても、たまに成功した結果が出ても、眠れず、徹夜で研究します.今回の研究では、Python Flashフレームワークを活用してより多くの機能を提供する方法について理解しました.
Reference
この問題について(Flask Full-stack + Flask-SocketIO + Nginx + Gunicorn[2/2]), 我々は、より多くの情報をここで見つけました
https://velog.io/@kkamikoon/Flask-Full-stack-Flask-SocketIO-Nginx-Gunicorn22
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
from flask_socketio import SocketIO
socketio = SocketIO()
# Your logics...
from app.sockets import socketio
@app.route("/test", methods=['GET'])
def test():
socketio.emit( "announce",
{"test" : "test success"},
namespace='/socket/main',
broadcast=True)
return "Some text"
研究の過程で多くの曲折を経験した.特にFlask-StocketIOを構成するコンテンツでは、
socketio.init_app()
関数を使用して構成されたコンテンツが見つかりません.そのため、ほとんどが実験結果に基づいて文章を書いている.特に、Flask-SocketIOを使用してテスト経験を記述したブログの大部分を見ても、適切なフィードバックが得られなかった.私を死なせる方法。
成功の数日前まで101 Upgradeパケット要求は失敗した.この時点でFlask+Flask-StocketIO+Guncorn+NginxとSSLの応用が完了した.しかし,Web上でWeb Socketを要求すると,400 Badリクエストが応答として常に存在する.このときのサーバドライバ環境.
Guncornコマンド
$ gunicorn -w 3 -b 127.0.0.1:8080 wsgi:app
このときgevent,eventlett,geventtwebsocket.gunicorn.workers.GeventWebSocketWorkerなどのコマンドは使用されていません.これまでGuniornの問題ではなく、nginxの問題だったと思います.Pythonドライバ
# file : app/__init__.py
from flask import Flask
from app.sockets import socketio # app/sockets/__init__.py에 선언된 socketio 변수
def create_app():
app = Flask(__name__)
# Your logics...
# Set Config
app.config.from_object(config)
with app.app_context():
# Socket.IO
socketio.init_app( app,
async_mode="gevent",
cors_allowed_origins="*")
# Your logics...
return app
Nginx設定
Nginxの設定は、前述のアプリケーションSSLのプロファイルと同じです.
実験を続けていくうちに、できる限りのテストが行われても400 Badのリクエストは同じなのでGuncornで問題点を探します.最初にテストするコマンドは次のとおりです.
$ pip3 install gevent
$ gunicorn -w 3 -b 127.0.0.1:8080 wsgi:app
このとき最も重要な変化101 Upgradeパケットは正常に伝送され、応答も正常に回復する.図に示すように、101交換プロトコルは正常に戻ります.この時点で進めない研究が進んでいくのは安心だ.通信だけが正常ではない.次のエラーが発生し、スロットが不安定でサービスが提供されないためです.しかしこのとき,NginxではなくGunicornの設定を変更すると,答えの直感が得られるので,種々の実験を行った.
[2021-08-01 18:52:03 +0000] [62584] [ERROR] Socket error processing request.
Traceback (most recent call last):
File "/usr/local/lib/python3.8/dist-packages/gunicorn/workers/sync.py", line 135, in handle
self.handle_request(listener, req, client, addr)
File "/usr/local/lib/python3.8/dist-packages/gunicorn/workers/sync.py", line 191, in handle_request
six.reraise(*sys.exc_info())
File "/usr/local/lib/python3.8/dist-packages/gunicorn/six.py", line 625, in reraise
raise value
File "/usr/local/lib/python3.8/dist-packages/gunicorn/workers/sync.py", line 183, in handle_request
resp.close()
File "/usr/local/lib/python3.8/dist-packages/gunicorn/http/wsgi.py", line 409, in close
self.send_headers()
File "/usr/local/lib/python3.8/dist-packages/gunicorn/http/wsgi.py", line 329, in send_headers
util.write(self.sock, util.to_bytestring(header_str, "ascii"))
File "/usr/local/lib/python3.8/dist-packages/gunicorn/util.py", line 304, in write
sock.sendall(data)
OSError: [Errno 9] Bad file descriptor
Guncorn指令実験
まずGuncorn命令を実験するために種々の実験を行った.
# Failed - 502 Bad Gateway
gunicorn -k gevent -w 1 -b 127.0.0.1:8080 wsgi:app
# Failed - 502 Bad Gateway
$ gunicorn -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker -w 1 wsgi:app
# Failed - ImportError: cannot import name 'ALREADY_HANDLED' from 'eventlet.wsgi'
$ gunicorn --worker-class eventlet -w 1 -b 127.0.0.1:8080 wsgi:app
# Success - pip3 install eventlet==0.30.2
$ gunicorn --worker-class eventlet -w 1 -b 127.0.0.1:8080 wsgi:app
上記の過程でeventlettは満足のいく結果を得た.ただし、eventlettをインストールする場合は、バージョンをダウングレードする必要があります.ポスト
上記の実験過程による研究では,参考になる資料の欠如に加えて,ウェブサイト,Nginx,Guncornの理解が欠けている.しかし、見慣れない環境構成やライブラリの使用については、1週間の研究時間が思ったより短く、満足のいく結果が得られたことをうれしく思います.研究時間が足りなかったので仮眠して行ったのですが…たとえ困難にぶつかっても、たまに成功した結果が出ても、眠れず、徹夜で研究します.今回の研究では、Python Flashフレームワークを活用してより多くの機能を提供する方法について理解しました.
Reference
この問題について(Flask Full-stack + Flask-SocketIO + Nginx + Gunicorn[2/2]), 我々は、より多くの情報をここで見つけました https://velog.io/@kkamikoon/Flask-Full-stack-Flask-SocketIO-Nginx-Gunicorn22テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol