Gunicorn: لا يعمل Gunicorn + Flask + Tensorflow في حاوية Docker

تم إنشاؤها على ٣ أكتوبر ٢٠١٩  ·  23تعليقات  ·  مصدر: benoitc/gunicorn

أهلا

لدي مشروع TensorFlow 2.0 به واجهة برمجة تطبيقات Flask صغيرة أمامه حتى أتمكن من تقديم طلبات إلى النموذج من خلال مكالمات HTTP مع المعالجة المسبقة للبيانات التي تم إجراؤها بالفعل في واجهة برمجة التطبيقات. اخترت Gunicorn لتشغيل تطبيق Flask / TensorFlow الخاص بي في حاوية عامل إرساء. للأسف ، العملية العمالية التي أنشأها Gunicorn معلقة في الحاوية حتى قتلها Gunicorn. الخادم لا يأتي أبدًا ولا يمكنني تقديم طلبات إليه. علاوة على ذلك ، فإن إعداد Gunicorn نفسه يعمل بشكل لا تشوبه شائبة خارج عامل الإرساء ، في الجهاز المضيف.

سجلات Docker (يتم تعليقها هناك وتطبع خطأ انتهاء المهلة بعد وقت طويل)

[2019-10-03 18:03:05 +0000] [1] [INFO] Starting gunicorn 19.9.0
[2019-10-03 18:03:05 +0000] [1] [INFO] Listening at: http://127.0.0.1:8000 (1)
[2019-10-03 18:03:05 +0000] [1] [INFO] Using worker: sync
[2019-10-03 18:03:05 +0000] [8] [INFO] Booting worker with pid: 8
2019-10-03 18:03:08.126584: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
2019-10-03 18:03:08.130017: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 3392000000 Hz
2019-10-03 18:03:08.130306: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x55fbb23fb2d0 executing computations on platform Host. Devices:
2019-10-03 18:03:08.130365: I tensorflow/compiler/xla/service/service.cc:175]   StreamExecutor device (0): Host, Default Version

ملف عامل ميناء:

FROM python

RUN pip install gunicorn

WORKDIR /usr/src/app

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

CMD [ "gunicorn", "--chdir", "src", "api:app" ]

api.py:

from flask import Flask, request
import inference

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def predict():
    if request.method == 'GET':
        return 'POST a json payload of {"imageBase64": "base64base64base64"} to this address to predict.'
    try:
        result = inference.run(request.json['imageBase64'])
        return result
    except Exception as e:
        return {'error': str(e)}, 500

if __name__ == "__main__":
    app.run()
else:
    print('\n * Server ready!')

الاستدلال

# Import packages
from __future__ import absolute_import, division, print_function, unicode_literals

import os
import tensorflow as tf
from tensorflow import keras
import PIL
import numpy as np
from io import BytesIO
import base64
import json

print("TensorFlow version is ", tf.__version__)

# Set variables
##########################################################################################
##########################################################################################

model_name = 'catsdogs'

base_dir = os.path.join(os.path.dirname(__file__), '..')
model_dir = os.path.join(base_dir, 'models')

##########################################################################################
##########################################################################################

# Load model
model = keras.models.load_model(os.path.join(model_dir, model_name + '.h5'))

# Load metadata
with open(os.path.join(model_dir, model_name + '_metadata.json')) as metadataFile:
    metadata = json.load(metadataFile)

# Split metadata
labels = metadata['training_labels']
image_size = metadata['image_size']

# Exported function for inference
def run(imgBase64):
    # Decode the base64 string
    image = PIL.Image.open(BytesIO(base64.b64decode(imgBase64)))

    # Pepare image
    image = image.resize((image_size, image_size), resample=PIL.Image.BILINEAR)
    image = image.convert("RGB")

    # Run prediction
    tensor = tf.cast(np.array(image), tf.float32) / 255.
    tensor = tf.expand_dims(tensor, 0, name=None)
    result = model.predict(tensor, steps=1)

    # Combine result with labels
    labeledResult = {}
    for i, label in enumerate(labels):
        labeledResult[label] = float(result[0][labels[label]])

    return labeledResult

لقد بحثت عن حل لهذا للأعمار ولم أتمكن من التوصل إلى أي شيء ، أي مساعدة ستكون موضع تقدير كبير.

شكرا!

Feedback Requested FeaturWorker FeaturIPC PlatforDocker

التعليق الأكثر فائدة

كان لديه نفس المشكلة. بقدر ما أستطيع تخمينه من سجلاتي الخاصة ، يبدو أن tensorflow يستخدم gevent ، ولا يمكنك استخدام gevent في نفس الوقت في gunicorn . لا تُحدث العلامات --workers و --threads أي فرق بالنسبة لي ، لكن التغيير من --worker-class=gevent إلى --worker-class=gthread أصلح المشكلة بالنسبة لي. شكرا ياjavabrett

ال 23 كومينتر

هل يحد إعداد Docker الخاص بك من الحد الأقصى للذاكرة المتاحة للحاوية؟

تعاني من نفس الشيء. لا أعتقد أن جونيكورن هو المسؤول. أحصل على نفس الخطأ عند تشغيل python3 api.py من bash shell في الحاوية.

tlaanemaa هل يمكنك تأكيد ما يقول mackdelany ؟

مهلا. آسف لتختفي من هذا القبيل.

يحد الإعداد الخاص بي من ذاكرة الوصول العشوائي لـ Docker قليلاً ولكن حدث نفس الشيء حتى عندما أزلت القيد.

سأحاول تشغيل ملف api بدون gunicorn و r eport.

شكرا!

tlaanemaa أي أخبار عنها؟

تضمين التغريدة
عذرًا ، لقد انجرفت بعيدًا مع أشياء أخرى ولم يكن لدي الوقت الكافي للمضي قدمًا في هذا الأمر.
سأحاول أن أزعج هذا اليوم وأعود إليك

لذلك حاولت تشغيل التطبيق بدون gunicorn في الحاوية ونجح ذلك.
يوجد أدناه جزء CMD من ملف Dockerfile الخاص بي

يعمل:

CMD [ "python", "src/api.py" ]

السجلات:

2019-12-02 11:40:45.649503: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
2019-12-02 11:40:45.653496: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2208000000 Hz
2019-12-02 11:40:45.653999: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x55f969cf6a40 executing computations on platform Host. Devices:
2019-12-02 11:40:45.654045: I tensorflow/compiler/xla/service/service.cc:175]   StreamExecutor device (0): Host, Default Version
TensorFlow version is  2.0.0
 * Serving Flask app "api" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

لا يعمل:

CMD [ "gunicorn", "--chdir", "src", "api:app" ]

السجلات:

[2019-12-02 11:39:22 +0000] [1] [INFO] Starting gunicorn 20.0.4
[2019-12-02 11:39:22 +0000] [1] [INFO] Listening at: http://127.0.0.1:8000 (1)
[2019-12-02 11:39:22 +0000] [1] [INFO] Using worker: sync
[2019-12-02 11:39:22 +0000] [9] [INFO] Booting worker with pid: 9
2019-12-02 11:39:24.041188: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
2019-12-02 11:39:24.046495: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2208000000 Hz
2019-12-02 11:39:24.047129: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x5623e18b5200 executing computations on platform Host. Devices:
2019-12-02 11:39:24.047183: I tensorflow/compiler/xla/service/service.cc:175]   StreamExecutor device (0): Host, Default Version

أيضًا ، لقد فتحت المستودع حتى تتمكن من التجول إذا كنت تريد ذلك.
يمكن أن تكون مفيدة

https://gitlab.com/tlaanemaa/image-classifier

Listening at: http://127.0.0.1:8000 (1)

هل يمكن أن تكون المشكلة أن البونكورن يستمع إلى مضيف محلي داخل حاوية بحيث لا يمكن الوصول إليه من الخارج؟

لا أعتقد ذلك لأن تطبيق flask كان يفعل الشيء نفسه وكان ذلك يعمل.
أيضًا ، لا يسجل إصدار gunicorn إصدار tensorflow الذي يشير إلى حدوث المشكلة قبل سطر السجل هذا في الكود. عند الجري بدون gunicorn ، فقط قارورة ، ثم يسجل ذلك.
TensorFlow version is 2.0.0

ماذا تقول على مستوى التصحيح؟

tlaanemaa كيف يتم تكوين شبكة Docker daemon الخاصة بك؟ وفقًا لتعليق من CaselIT ، يبدو من المحتمل أن عميلك غير قادر على الوصول إلى منفذ Gunicorn عبر شبكة Docker.

هل يمكنك محاولة بدء Gunicorn بـ arg -b 0.0.0.0:8000 ؟

لا أعتقد أن المشكلة تكمن في الشبكة لأنه يبدو ، من السجلات على الأقل ، أن الخادم لا يبدأ على الإطلاق لأنه لا يصل أبدًا إلى خطوط السجل التي تأتي بعد استيراد tensorflow

ومع ذلك فقد جربت اقتراحك ولكنه يعطيني خطأ

CMD [ "gunicorn", "-b", "0.0.0.0:8000", "--chdir", "src", "api:app" ]

_سجل_

usage: gunicorn [OPTIONS] [APP_MODULE]
gunicorn: error: unrecognized arguments: -d

إذا كنت تريد أن تجرب نفسك ثم هي صورة comtainer المتاحة في registry.gitlab.com/tlaanemaa/image-classifier

tlaanemaa هل يمكنك إعادة نشر أمر إنشاء الصورة وأمر تشغيل الحاوية Dockerfile المحدّث؟

تضمين التغريدة

  • ملف Dockerfile: https://gitlab.com/tlaanemaa/image-classifier/blob/master/Dockerfile
  • أمر البناء: docker build -t tlaanemaa/image-classifier .
  • تم تشغيل الحاوية عبر Portainer ، لست متأكدًا من الأمر الذي تستخدمه للقيام بذلك للأسف. لا شيء مجنون يتم القيام به هناك ، الأشياء القياسية ، المنفذ 8000 يتم إعادة توجيهها.

_Dockerfile وقت الإرسال: _

FROM python:3.7

RUN pip install gunicorn

WORKDIR /usr/src/app

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

CMD [ "gunicorn", "-b", "0.0.0.0:8000", "--chdir", "src", "api:app" ]

ما هو سجل عامل الإرساء الكامل ، هل يمكنك لصق سطر الأوامر الذي يستخدمه أخيرًا؟

ما لم يكن يفعل شيئًا لا يمكن التخلي عنه أثناء تصحيح هذه المشكلة ، فهل يمكنك تشغيله بدون Portainer في الوقت الحالي؟

هذا يعمل بالنسبة لي ، Docker Desktop for Mac 2.1.0.5:

docker build -t tlaanemaa/image-classifier .
docker run -it --rm -p 8000:8000 tlaanemaa/image-classifier

يقبل طلبات POST .

الرجاء تشغيل ونشر الإخراج والنتيجة كاملة.

لقد جربته وهو يعمل الآن.
هل يمكن أن يكون العلم -b الذي أصلحه؟

شكرا جزيلا!

ما هو مثير للاهتمام الآن هو أنه عندما أقوم بطلبات POST ، فإن الهدف يكون سريعًا ولكن طلبات GET تكون بطيئة للغاية. بعد فترة من القيام بطلبات GET ، تصبح هذه الطلبات سريعة ولكن بعد ذلك يصبح POST بطيئًا للغاية وينتهي العامل. بمجرد استجابتها لهذا POST ، تكون POSTs سريعة مرة أخرى و GETs بطيئة. يبدو كما لو كان بإمكانه القيام بسرعة واحدة ويستغرق الأمر وقتًا للتبديل: D

هذه هي السجلات عندما يكون GET سريعًا ويكون POST بطيئًا بسبب انتهاء مهلة العامل:

[2020-01-10 09:34:46 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:72)
[2020-01-10 09:34:46 +0000] [72] [INFO] Worker exiting (pid: 72)
[2020-01-10 09:34:47 +0000] [131] [INFO] Booting worker with pid: 131
TensorFlow version is  2.0.0
2020-01-10 09:34:48.946351: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
2020-01-10 09:34:48.951124: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2208000000 Hz
2020-01-10 09:34:48.951612: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x56481dbabd80 executing computations on platform Host. Devices:
2020-01-10 09:34:48.951665: I tensorflow/compiler/xla/service/service.cc:175]   StreamExecutor device (0): Host, Default Version

 * Server ready!

أيضًا ، في بعض الحالات ، لا يبدو أن السجل * Server ready! يظهر في سجلات عامل الإرساء. كان من الممكن أن يكون مضللًا أيضًا. لست متأكدا ما سبب ذلك

سيتم تكوين الخادم الحالي في Docker الخاص بك بشكل فردي / متزامن ، والذي سيكون تافهًا لجعله مشغولًا / محظورًا ، لذلك من المحتمل أنك ترى ذلك. حاول إضافة بعض الوسائط مثل --workers=2 --threads=4 --worker-class=gthread .

شكرا ياjavabrett
التي أصلحت ذلك!

كان لديه نفس المشكلة. بقدر ما أستطيع تخمينه من سجلاتي الخاصة ، يبدو أن tensorflow يستخدم gevent ، ولا يمكنك استخدام gevent في نفس الوقت في gunicorn . لا تُحدث العلامات --workers و --threads أي فرق بالنسبة لي ، لكن التغيير من --worker-class=gevent إلى --worker-class=gthread أصلح المشكلة بالنسبة لي. شكرا ياjavabrett

أهلا! بصفتي مشرفًا على gevent ومساهمًا في هذا المشروع ، يمكنني القول بشكل قاطع أن gevent و gunicorn يعملان معًا بشكل جيد. قد تتدخل مكتبات مختلفة ، لكن هذا ليس خطأ أي من gunicorn أو gevent. الرجاء فتح مشكلة جديدة إذا لم يكن الأمر كذلك بالنسبة لك. شكرا!

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات