有一個想法表明不要在生產中使用 gunicorn 或 uwsgi 運行燒瓶應用程式。Tiangolo 在他的一個存盤庫中提到 app.run 應該僅用于開發,而不是部署或生產。鏈接到 Tiangolo 對該主題的評論 他的代碼如下:
from flask import Flask
app = Flask(__name__)
from .core import app_setup
if __name__ == "__main__":
# Only for debugging while developing
app.run(host="0.0.0.0", debug=True, port=80)
我的問題是為什么運行燒瓶應用程式可能會出現問題(上述代碼的最后一行)并且應該被洗掉或注釋掉。我進行了一系列測驗,發現在生產環境中運行或運行燒瓶應用程式生成的行程數是相同的。這是我用 gunicorn 進行的測驗的輸出。
這是我的碼頭工人撰寫。在第 12 行,您可以查看我是如何運行 gunicorn 的。
version: "3.7"
services:
face:
build: ./app
container_name: face
restart: always
expose:
- 660
environment:
- ENDPOINT=/face
- FACE_DETECTION_MODEL=MTCNNTorchFaceDetector
command: gunicorn --workers=2 --threads 1 -b 0.0.0.0:660 entry_point:app --worker-class sync
nginx:
build: ./nginx
container_name: nginx
restart: always
ports:
- 8000:80
depends_on:
- face
帶有 app.run 的燒瓶 gunicorn 2 行程:
root@e6c7d9ef03cc:/app# cat entry_point.py
from endpoints import FaceDetection
from base_app import app, api, ENDPOINT
api.add_resource(FaceDetection, ENDPOINT)
if __name__ == '__main__':
app.run("127.0.0.1", port=3000)
root@e6c7d9ef03cc:/app# lsof -i
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
gunicorn 1 root 5u IPv4 471109 0t0 TCP *:660 (LISTEN)
gunicorn 7 root 5u IPv4 471109 0t0 TCP *:660 (LISTEN)
gunicorn 8 root 5u IPv4 471109 0t0 TCP *:660 (LISTEN)
root@e6c7d9ef03cc:/app#
正如您在代碼中看到的,有 3 個處理器,其中一個是主處理器,另外兩個是作業處理器。
沒有 app.run 的燒瓶 gunicorn 2 行程(已被注釋掉):
root@e6c7d9ef03cc:/app# cat entry_point.py
from endpoints import FaceDetection
from base_app import app, api, ENDPOINT
api.add_resource(FaceDetection, ENDPOINT)
# if __name__ == '__main__':
# app.run("127.0.0.1", port=3000)
root@e6c7d9ef03cc:/app# lsof -i
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
gunicorn 1 root 5u IPv4 466580 0t0 TCP *:660 (LISTEN)
gunicorn 8 root 5u IPv4 466580 0t0 TCP *:660 (LISTEN)
gunicorn 9 root 5u IPv4 466580 0t0 TCP *:660 (LISTEN)
root@e6c7d9ef03cc:/app#
輸出是相同的,并且丟棄主處理器,只有 2 個主要作業人員啟動并運行。
具有 4 個處理器的 gunicorn 應用程式也是如此。
使用 app.run:
root@f1d9f2d3a5d0:/app# cat entry_point.py
from endpoints import FaceDetection
from base_app import app, api, ENDPOINT
api.add_resource(FaceDetection, ENDPOINT)
if __name__ == '__main__':
app.run("127.0.0.1", port=3000)
root@f1d9f2d3a5d0:/app# lsof -i
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
gunicorn 1 root 5u IPv4 484435 0t0 TCP *:660 (LISTEN)
gunicorn 7 root 5u IPv4 484435 0t0 TCP *:660 (LISTEN)
gunicorn 8 root 5u IPv4 484435 0t0 TCP *:660 (LISTEN)
gunicorn 9 root 5u IPv4 484435 0t0 TCP *:660 (LISTEN)
gunicorn 10 root 5u IPv4 484435 0t0 TCP *:660 (LISTEN)
root@f1d9f2d3a5d0:/app#
沒有 app.run:
root@f1d9f2d3a5d0:/app# cat entry_point.py
from endpoints import FaceDetection
from base_app import app, api, ENDPOINT
api.add_resource(FaceDetection, ENDPOINT)
# if __name__ == '__main__':
# app.run("127.0.0.1", port=3000)
root@f1d9f2d3a5d0:/app# lsof -i
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
gunicorn 1 root 5u IPv4 476011 0t0 TCP *:660 (LISTEN)
gunicorn 8 root 5u IPv4 476011 0t0 TCP *:660 (LISTEN)
gunicorn 9 root 5u IPv4 476011 0t0 TCP *:660 (LISTEN)
gunicorn 10 root 5u IPv4 476011 0t0 TCP *:660 (LISTEN)
gunicorn 11 root 5u IPv4 476011 0t0 TCP *:660 (LISTEN)
root@f1d9f2d3a5d0:/app#
要重現問題,請克隆face-detection-flask-gunicron-docker-compose并運行以下命令:
# get the project
git clone https://github.com/pooya-mohammadi/face-detection-flask-nginx-gunicorn-docker.git
# cd to project's root
cd ace-detection-flask-nginx-gunicorn-docker
# build the images and run the project
sudo docker-compose up --build
# open a new terminal
sudo docker ps -a
# get the container-id for face-detection_face
# open a bash command with that container-id
sudo docker exec -it <container-i> bash # This opens a new command line
# install lsof to view listening services
apt-get install lsof
# view app.run condition
cat entry_point.py | grep app.run # The default is not commented.
lsof -i
在 entry_point.py 中注釋 app.run 并再次運行該程序。
要更改作業人員的數量,請修改 docker-compose.yml 中的第 12 行。
uj5u.com熱心網友回復:
在研究了 gunicorn 庫一段時間后,我注意到 gunicorn 用于import.import_module匯入入口點模塊(包含應用程式的模塊,在我的情況下為 entry_point.py),并且if __name__ == '__main__':不會執行下面的代碼,并且放置起來非常安全那里的任何東西。鏈接到 gunicorn 庫中的 import_app 方法。此方法從方法load_wsgiapp 鏈接呼叫到主要運行器類中的load_wsgiappWSGIApplication 鏈接到 WSGIApplication 類。
正如我注意到 Tiangolo 意味著直接使用燒瓶應用程式進行生產是不安全的,因為:
Flask 應用程式服務器未針對生產性能或安全性進行開發或測驗。
Justin Triplett 的回答(不和諧)
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/405689.html
標籤:
