GCP(应用引擎)上的问题 运行 python Flask Restplus API
problems running python Flask Restplus API on GCP (app engine)
我正在开发一个必须在 GCP 上运行的 API Rest 应用程序。该应用程序 运行 在本地运行良好,但当我将其部署到 GPC 时却无法运行。
我在 Python 3.7 中编写了 web 服务,使用 Flask、SQLAlchemy、Flask-SQLAlchemy、Flask-Restplus(为了拥有 Swagger)。
我在部署时没有任何错误,但是当我想访问文档时(招摇)我有 "No Api definition provided" 消息,当我尝试 运行 GET 方法时我'有一个(严重的)工人超时错误。
如果你能给我任何帮助,我将不胜感激。
祝你有美好的一天!!
下面是部分代码:
项目结构:
app.yaml
config.py
main.py
requirements.txt
apis/
__init__.py
log_resource.py
trm_resource.py
...
marshal_models/
__init__.py
log_marshal.py
trm_marshal.py
...
models/
__init__.py
log_model.py
trm_model.py
...
res/
__init__.py
text_messages.py
spa_exceptions.py
main.py
from flask import Flask, send_from_directory
from config import config_by_name
from flask_sqlalchemy import SQLAlchemy
from models import db
from apis import api
app = Flask(__name__)
app.config.from_object(config_by_name['prod'])
api.init_app(app)
db.init_app(app)
if __name__ == '__main__':
app.run(debug=True)
requirements.txt
-i https://pypi.org/simple
aniso8601==8.0.0
attrs==19.3.0
click==7.0
flask-restplus==0.13.0
flask-sqlalchemy==2.4.1
flask-swagger-ui==3.20.9
flask==1.1.1
importlib-metadata==0.23 ; python_version < '3.8'
itsdangerous==1.1.0
jinja2==2.10.3
jsonschema==3.2.0
markupsafe==1.1.1
more-itertools==7.2.0
mysql-connector-python==8.0.18
mysqlclient==1.4.4
protobuf==3.10.0
pyrsistent==0.15.5
pytz==2019.3
simplejson==3.17.0
six==1.13.0
sqlalchemy==1.3.11
werkzeug==0.16.0
zipp==0.6.0
gunicorn==19.9.0
app.yaml
runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app
runtime_config:
python_version: 3
config.py
class Config(object):
DEBUG = False
TESTING = False
connection_type = 'gcp' #tcp/ip
DB_SERVER = 'XXX.XXX.XXX.XXX'
DB_USERNAME = 'XXXX'
DB_PASSWORD = 'XXXX'
DB_NAME = 'XXXXX'
SQLALCHEMY_DATABASE_URI = f"mysql+mysqlconnector://{DB_USERNAME}:{DB_PASSWORD}@{DB_SERVER}/{DB_NAME}"
SQLALCHEMY_TRACK_MODIFICATIONS = False
class ProductionConfig(Config):
pass
config_by_name = dict(
dev = DevelopmentConfig,
test = TestingConfig,
prod = ProductionConfig
)
apis\__init__.py
from flask_restplus import Api
from .spa_system_resource import api as spa_name_space
from .stage_resource import api as stage_name_space
from .consolidated_resource import api as consolidated_name_space
from .cost_cat_resource import api as cost_cat_name_space
from .cost_resource import api as cost_name_space
from .log_resource import api as log_name_space
from .trm_resource import api as trm_name_space
from .energy_resource import api as energy_price_name_space
api = Api (
title='API - Spa System',
version='1.0',
description='XXXXXX',
contact='XXXXX',
contact_email='XXXXXXXXXXX',
contact_url='XXXXXXXX',
default_mediatype='application/json',
)
api.add_namespace(spa_name_space)
api.add_namespace(stage_name_space)
api.add_namespace(consolidated_name_space)
api.add_namespace(cost_name_space)
api.add_namespace(cost_cat_name_space)
api.add_namespace(log_name_space)
api.add_namespace(trm_name_space)
api.add_namespace(energy_price_name_space)
一个资源文件的提取:apis\log_resource.py
import datetime
from flask import current_app as app
from flask import Flask, request, jsonify, make_response
from flask_sqlalchemy import sqlalchemy
from flask_restplus import Namespace, Resource, reqparse, abort, fields
from werkzeug.exceptions import HTTPException
from res import DatabaseIntegrityError, DatabaseError, EngMsg as msg
from sqlalchemy.exc import SQLAlchemyError, IntegrityError
from models import Log, ModelList
from marshal_models import log_model_dict
api = Namespace('logs', description=msg.API_NAMESPACE_LOG_DESCRIPTION)
log_model = api.model('log', log_model_dict)
@api.route('/<log_id>')
@api.doc(responses={ 200: msg.API_DOC_RESPONSES_200,
400: msg.API_DOC_RESPONSES_400,
409: msg.API_DOC_RESPONSES_409,
500: msg.API_DOC_RESPONSES_500 })
class LogRes(Resource):
@api.doc(params={"log_id": msg.API_DOC_PARAMS_LOG_ID})
@api.marshal_with(log_model, skip_none=True)
def get(self, log_id):
try:
if log_id.isdigit():
return Log.query.get(log_id)
else:
app.logger.error(TypeError(msg.ERROR_TYPE_ERROR))
return msg.API_DOC_RESPONSES_400, 400
except DatabaseIntegrityError as err:
app.logger.error(err)
return msg.API_DOC_RESPONSES_409, 409
except HTTPException as err:
app.logger.error(f'HTTException: {err}')
return msg.API_DOC_RESPONSES_400, 400
except (Exception, DatabaseError) as err:
app.logger.error(err)
return msg.API_DOC_RESPONSES_500, 500
@api.doc(params={"log_id": msg.API_DOC_PARAMS_LOG_ID})
@api.expect(log_model, validate=True)
@api.marshal_with(log_model, skip_none=True)
def put(self, log_id):
try:
if log_id.isdigit():
log = Log.query.get(log_id)
if log:
log.update(api.payload)
return log
else:
app.logger.error(TypeError(msg.ERROR_TYPE_ERROR))
return msg.API_DOC_RESPONSES_400, 400
except DatabaseIntegrityError as err:
app.logger.error(err)
return msg.API_DOC_RESPONSES_409, 409
except HTTPException as err:
app.logger.error(f'HTTException: {err}')
return msg.API_DOC_RESPONSES_400, 400
except (Exception, DatabaseError) as err:
app.logger.error(err)
return msg.API_DOC_RESPONSES_500, 500
@api.doc(params={"log_id": msg.API_DOC_PARAMS_LOG_ID})
@api.response(204, msg.API_DOC_RESPONSES_204)
def delete(self, log_id):
try:
if log_id.isdigit():
log = Log.query.get(log_id)
if log:
log.delete()
return msg.API_DOC_RESPONSES_204, 204
else:
app.logger.error(TypeError(msg.ERROR_TYPE_ERROR))
return msg.API_DOC_RESPONSES_400, 400
except DatabaseIntegrityError as err:
app.logger.error(err)
return msg.API_DOC_RESPONSES_409, 409
except HTTPException as err:
app.logger.error(f'HTTException: {err}')
return msg.API_DOC_RESPONSES_400, 400
except (Exception, DatabaseError) as err:
app.logger.error(err)
return msg.API_DOC_RESPONSES_500, 500
浏览器中尝试调用 GET 方法的错误消息(2019 年 11 月 27 日更新):
gcp 中的错误日志(2019 年 11 月 27 日更新)
[
{
"protoPayload": {
"@type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
"appId": "p~maximal-beach-255318",
"versionId": "20191126t083944",
"requestId": "5dde722800ff01c4db2055869d0001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"ip": "217.182.175.162",
"startTime": "2019-11-27T12:55:04.115931Z",
"endTime": "2019-11-27T12:55:35.620208Z",
"latency": "31.504277s",
"megaCycles": "672",
"method": "HEAD",
"resource": "/stages/",
"httpVersion": "HTTP/1.1",
"status": 502,
"responseSize": "122",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36",
"urlMapEntry": "auto",
"host": "maximal-beach-255318.appspot.com",
"cost": 1.3634e-8,
"instanceIndex": -1,
"finished": true,
"instanceId": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49",
"appEngineRelease": "1.9.71",
"traceId": "66545566d74d32b65a44ef6b5e8eb3e1",
"first": true,
"traceSampled": true
},
"insertId": "5dde72470009773abcebccc9",
"httpRequest": {
"status": 502
},
"resource": {
"type": "gae_app",
"labels": {
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944"
}
},
"timestamp": "2019-11-27T12:55:04.115931Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/appengine.googleapis.com%2Frequest_log",
"operation": {
"id": "5dde722800ff01c4db2055869d0001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"producer": "appengine.googleapis.com/request_id",
"first": true,
"last": true
},
"trace": "projects/maximal-beach-255318/traces/66545566d74d32b65a44ef6b5e8eb3e1",
"receiveTimestamp": "2019-11-27T12:55:35.626061163Z",
"traceSampled": true
},
{
"textPayload": "[2019-11-27 12:45:27 +0000] [20] [INFO] Booting worker with pid: 20",
"insertId": "5dde6fe70007e247c06a652a",
"resource": {
"type": "gae_app",
"labels": {
"version_id": "20191126t083944",
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318"
}
},
"timestamp": "2019-11-27T12:45:27.516679Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T12:45:27.671289763Z"
},
{
"textPayload": "[2019-11-27 12:45:26 +0000] [7] [CRITICAL] WORKER TIMEOUT (pid:19)",
"insertId": "5dde6fe6000528928a3fd08e",
"resource": {
"type": "gae_app",
"labels": {
"version_id": "20191126t083944",
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318"
}
},
"timestamp": "2019-11-27T12:45:26.338066Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T12:45:26.344938571Z"
},
{
"protoPayload": {
"@type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
"appId": "p~maximal-beach-255318",
"versionId": "20191126t083944",
"requestId": "5dde6fc700ff0b4dadaec6e11e0001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"ip": "190.217.67.6",
"startTime": "2019-11-27T12:44:55.740781Z",
"endTime": "2019-11-27T12:45:27.355877Z",
"latency": "31.615096s",
"megaCycles": "662",
"method": "GET",
"resource": "/logs/",
"httpVersion": "HTTP/1.1",
"status": 502,
"responseSize": "690",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
"urlMapEntry": "auto",
"host": "maximal-beach-255318.appspot.com",
"cost": 7.7113e-8,
"instanceIndex": -1,
"finished": true,
"instanceId": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49",
"appEngineRelease": "1.9.71",
"traceId": "17ca3e3af386e29af2197260dd20ca5b",
"first": true,
"traceSampled": true
},
"insertId": "5dde6fe700056f2d0a6185c7",
"httpRequest": {
"status": 502
},
"resource": {
"type": "gae_app",
"labels": {
"version_id": "20191126t083944",
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318"
}
},
"timestamp": "2019-11-27T12:44:55.740781Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/appengine.googleapis.com%2Frequest_log",
"operation": {
"id": "5dde6fc700ff0b4dadaec6e11e0001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"producer": "appengine.googleapis.com/request_id",
"first": true,
"last": true
},
"trace": "projects/maximal-beach-255318/traces/17ca3e3af386e29af2197260dd20ca5b",
"receiveTimestamp": "2019-11-27T12:45:27.357040172Z",
"traceSampled": true
},
{
"textPayload": "[2019-11-27 12:44:50 +0000] [19] [INFO] Booting worker with pid: 19",
"insertId": "5dde6fc200029a6115a11cd3",
"resource": {
"type": "gae_app",
"labels": {
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944",
"module_id": "default",
"zone": "us-east1-3"
}
},
"timestamp": "2019-11-27T12:44:50.170593Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T12:44:50.177293952Z"
},
{
"textPayload": "[2019-11-27 12:44:48 +0000] [7] [CRITICAL] WORKER TIMEOUT (pid:18)",
"insertId": "5dde6fc0000ccba4ab7daec2",
"resource": {
"type": "gae_app",
"labels": {
"zone": "us-east1-3",
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944",
"module_id": "default"
}
},
"timestamp": "2019-11-27T12:44:48.838564Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T12:44:48.846320557Z"
},
{
"protoPayload": {
"@type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
"appId": "p~maximal-beach-255318",
"versionId": "20191126t083944",
"requestId": "5dde6fa200ff00ffb6f6484c386b0001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"ip": "190.217.67.6",
"startTime": "2019-11-27T12:44:18.046838Z",
"endTime": "2019-11-27T12:44:49.927998Z",
"latency": "31.881160s",
"megaCycles": "638",
"method": "GET",
"resource": "/stages/",
"httpVersion": "HTTP/1.1",
"status": 502,
"responseSize": "690",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
"urlMapEntry": "auto",
"host": "maximal-beach-255318.appspot.com",
"cost": 7.7113e-8,
"instanceIndex": -1,
"finished": true,
"instanceId": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49",
"appEngineRelease": "1.9.71",
"traceId": "f9abbbb57697d19e094bc6a7afe46fc4",
"first": true,
"traceSampled": true
},
"insertId": "5dde6fc1000e377f4c815764",
"httpRequest": {
"status": 502
},
"resource": {
"type": "gae_app",
"labels": {
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944"
}
},
"timestamp": "2019-11-27T12:44:18.046838Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/appengine.googleapis.com%2Frequest_log",
"operation": {
"id": "5dde6fa200ff00ffb6f6484c386b0001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"producer": "appengine.googleapis.com/request_id",
"first": true,
"last": true
},
"trace": "projects/maximal-beach-255318/traces/f9abbbb57697d19e094bc6a7afe46fc4",
"receiveTimestamp": "2019-11-27T12:44:49.941671848Z",
"traceSampled": true
},
{
"protoPayload": {
"@type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
"appId": "p~maximal-beach-255318",
"versionId": "20191126t083944",
"requestId": "5dde6f9000ff09e526316e53900001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"ip": "190.217.67.6",
"startTime": "2019-11-27T12:44:00.648486Z",
"endTime": "2019-11-27T12:44:05.324856Z",
"latency": "4.676370s",
"megaCycles": "2744",
"method": "GET",
"resource": "/favicon.ico",
"httpVersion": "HTTP/1.1",
"status": 404,
"responseSize": "385",
"referrer": "http://maximal-beach-255318.appspot.com/stages/",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
"urlMapEntry": "auto",
"host": "maximal-beach-255318.appspot.com",
"cost": 4.3027e-8,
"instanceIndex": -1,
"finished": true,
"instanceId": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49",
"appEngineRelease": "1.9.71",
"traceId": "18628020e642702bce4c2e0b3187e2ce",
"first": true,
"traceSampled": true
},
"insertId": "5dde6f9500069b4e77b19ab5",
"httpRequest": {
"status": 404
},
"resource": {
"type": "gae_app",
"labels": {
"zone": "us-east1-3",
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944",
"module_id": "default"
}
},
"timestamp": "2019-11-27T12:44:00.648486Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/appengine.googleapis.com%2Frequest_log",
"operation": {
"id": "5dde6f9000ff09e526316e53900001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"producer": "appengine.googleapis.com/request_id",
"first": true,
"last": true
},
"trace": "projects/maximal-beach-255318/traces/18628020e642702bce4c2e0b3187e2ce",
"receiveTimestamp": "2019-11-27T12:44:05.434941402Z",
"traceSampled": true
},
{
"textPayload": "[2019-11-27 12:44:00 +0000] [18] [INFO] Booting worker with pid: 18",
"insertId": "5dde6f900009af56ce378348",
"resource": {
"type": "gae_app",
"labels": {
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944",
"module_id": "default",
"zone": "us-east1-3"
}
},
"timestamp": "2019-11-27T12:44:00.634710Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T12:44:00.697087376Z"
},
{
"textPayload": "[2019-11-27 12:43:59 +0000] [7] [CRITICAL] WORKER TIMEOUT (pid:15)",
"insertId": "5dde6f8f00057bd7123ebed3",
"resource": {
"type": "gae_app",
"labels": {
"zone": "us-east1-3",
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944",
"module_id": "default"
}
},
"timestamp": "2019-11-27T12:43:59.359383Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T12:43:59.367903796Z"
},
{
"protoPayload": {
"@type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
"appId": "p~maximal-beach-255318",
"versionId": "20191126t083944",
"requestId": "5dde6f7100ff03b1470e1729150001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"ip": "190.217.67.6",
"startTime": "2019-11-27T12:43:29.241991Z",
"endTime": "2019-11-27T12:44:00.433791Z",
"latency": "31.191800s",
"megaCycles": "670",
"method": "GET",
"resource": "/stages/",
"httpVersion": "HTTP/1.1",
"status": 502,
"responseSize": "690",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
"urlMapEntry": "auto",
"host": "maximal-beach-255318.appspot.com",
"cost": 7.7113e-8,
"instanceIndex": -1,
"finished": true,
"instanceId": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49",
"appEngineRelease": "1.9.71",
"traceId": "2eb1e05b6e3607b82bc6eb1581f7030b",
"first": true,
"traceSampled": true
},
"insertId": "5dde6f900006aa2783948800",
"httpRequest": {
"status": 502
},
"resource": {
"type": "gae_app",
"labels": {
"zone": "us-east1-3",
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944",
"module_id": "default"
}
},
"timestamp": "2019-11-27T12:43:29.241991Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/appengine.googleapis.com%2Frequest_log",
"operation": {
"id": "5dde6f7100ff03b1470e1729150001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"producer": "appengine.googleapis.com/request_id",
"first": true,
"last": true
},
"trace": "projects/maximal-beach-255318/traces/2eb1e05b6e3607b82bc6eb1581f7030b",
"receiveTimestamp": "2019-11-27T12:44:00.443084831Z",
"traceSampled": true
},
{
"textPayload": "[2019-11-27 07:52:18 +0000] [7] [INFO] Shutting down: Master",
"insertId": "5dde2b32000662725bdd088d",
"resource": {
"type": "gae_app",
"labels": {
"version_id": "20191126t083531",
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318"
}
},
"timestamp": "2019-11-27T07:52:18.418418Z",
"labels": {
"clone_id": "00c61b117c8a2ff2cf91e014f80fd771ceb13ae6f293bfa1dfe53396a1fe807c93d66bb6"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T07:52:18.465138763Z"
},
{
"textPayload": "[2019-11-27 07:52:17 +0000] [20] [INFO] Worker exiting (pid: 20)",
"insertId": "5dde2b31000cbb519c6bb001",
"resource": {
"type": "gae_app",
"labels": {
"version_id": "20191126t083531",
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318"
}
},
"timestamp": "2019-11-27T07:52:17.834385Z",
"labels": {
"clone_id": "00c61b117c8a2ff2cf91e014f80fd771ceb13ae6f293bfa1dfe53396a1fe807c93d66bb6"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T07:52:18.129370130Z"
},
{
"textPayload": "[2019-11-27 07:52:17 +0000] [7] [INFO] Handling signal: term",
"insertId": "5dde2b310009e8722b2030e5",
"resource": {
"type": "gae_app",
"labels": {
"version_id": "20191126t083531",
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318"
}
},
"timestamp": "2019-11-27T07:52:17.649330Z",
"labels": {
"clone_id": "00c61b117c8a2ff2cf91e014f80fd771ceb13ae6f293bfa1dfe53396a1fe807c93d66bb6"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T07:52:17.795680101Z"
},
{
"textPayload": "[2019-11-27 02:15:44 +0000] [15] [INFO] Booting worker with pid: 15",
"insertId": "5ddddc5000013018cd840898",
"resource": {
"type": "gae_app",
"labels": {
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944",
"module_id": "default",
"zone": "us-east1-3"
}
},
"timestamp": "2019-11-27T02:15:44.077848Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T02:15:44.269814707Z"
},
{
"textPayload": "[2019-11-27 02:15:43 +0000] [7] [INFO] Using worker: sync",
"insertId": "5ddddc4f000e3a8221b4647f",
"resource": {
"type": "gae_app",
"labels": {
"version_id": "20191126t083944",
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318"
}
},
"timestamp": "2019-11-27T02:15:43.932482Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T02:15:44.269814707Z"
},
{
"textPayload": "[2019-11-27 02:15:43 +0000] [7] [INFO] Listening at: http://0.0.0.0:8081 (7)",
"insertId": "5ddddc4f000e3a5ed3d9fe86",
"resource": {
"type": "gae_app",
"labels": {
"zone": "us-east1-3",
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944",
"module_id": "default"
}
},
"timestamp": "2019-11-27T02:15:43.932446Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T02:15:44.269814707Z"
},
{
"textPayload": "[2019-11-27 02:15:43 +0000] [7] [INFO] Starting gunicorn 19.9.0",
"insertId": "5ddddc4f000e32a95dc08c06",
"resource": {
"type": "gae_app",
"labels": {
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944"
}
},
"timestamp": "2019-11-27T02:15:43.930473Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T02:15:43.935820537Z"
},
{
"protoPayload": {
"@type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
"appId": "p~maximal-beach-255318",
"versionId": "20191126t083944",
"requestId": "5ddddc4e00ff05cca307340a140001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"ip": "186.84.21.80",
"startTime": "2019-11-27T02:15:42.380067Z",
"endTime": "2019-11-27T02:15:45.795201Z",
"latency": "3.415134s",
"megaCycles": "4969",
"method": "GET",
"resource": "/favicon.ico",
"httpVersion": "HTTP/1.1",
"status": 404,
"responseSize": "380",
"referrer": "http://maximal-beach-255318.appspot.com/stages/",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
"urlMapEntry": "auto",
"host": "maximal-beach-255318.appspot.com",
"cost": 4.2468e-8,
"wasLoadingRequest": true,
"instanceIndex": -1,
"finished": true,
"instanceId": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49",
"line": [
{
"time": "2019-11-27T02:15:45.794925Z",
"severity": "INFO",
"logMessage": "This request caused a new process to be started for your application, and thus caused your application code to be loaded for the first time. This request may thus take longer and use more CPU than a typical request for your application."
}
],
"appEngineRelease": "1.9.71",
"traceId": "55744f06ecd2c9f36584f78dd72858dd",
"first": true,
"traceSampled": true
},
"insertId": "5ddddc51000c22e862aa1128",
"httpRequest": {
"status": 404
},
"resource": {
"type": "gae_app",
"labels": {
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944"
}
},
"timestamp": "2019-11-27T02:15:42.380067Z",
"severity": "INFO",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/appengine.googleapis.com%2Frequest_log",
"operation": {
"id": "5ddddc4e00ff05cca307340a140001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"producer": "appengine.googleapis.com/request_id",
"first": true,
"last": true
},
"trace": "projects/maximal-beach-255318/traces/55744f06ecd2c9f36584f78dd72858dd",
"receiveTimestamp": "2019-11-27T02:15:45.804618825Z",
"traceSampled": true
},
多亏了你提供的错误信息,事情现在更清楚了。所以这条消息
Mixed Content: The page at '*****' was loaded over HTTPS, but
requested an insecure resource 'http://****/swagger.json'. This
content should also be served over HTTPS.
表示您的 App Engine 正在尝试通过 HTTPS 提供内容。但是,您的 Flask Restplus 正在发送 HTTP 请求。这里它试图获取“http://****/swagger.json”
使用 HTTP 请求。由于这种不匹配,呼叫被阻止,您收到“未提供 API 定义”。
为了解决这个问题,我注意到您正在使用“werkzeug”中间件。
将此代码添加到您的 Flask 初始化中:
from werkzeug.middleware.proxy_fix import ProxyFix
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app)
您可以阅读原始问题 here。
希望对您有所帮助。
我正在开发一个必须在 GCP 上运行的 API Rest 应用程序。该应用程序 运行 在本地运行良好,但当我将其部署到 GPC 时却无法运行。
我在 Python 3.7 中编写了 web 服务,使用 Flask、SQLAlchemy、Flask-SQLAlchemy、Flask-Restplus(为了拥有 Swagger)。
我在部署时没有任何错误,但是当我想访问文档时(招摇)我有 "No Api definition provided" 消息,当我尝试 运行 GET 方法时我'有一个(严重的)工人超时错误。
如果你能给我任何帮助,我将不胜感激。
祝你有美好的一天!!
下面是部分代码:
项目结构:
app.yaml
config.py
main.py
requirements.txt
apis/
__init__.py
log_resource.py
trm_resource.py
...
marshal_models/
__init__.py
log_marshal.py
trm_marshal.py
...
models/
__init__.py
log_model.py
trm_model.py
...
res/
__init__.py
text_messages.py
spa_exceptions.py
main.py
from flask import Flask, send_from_directory
from config import config_by_name
from flask_sqlalchemy import SQLAlchemy
from models import db
from apis import api
app = Flask(__name__)
app.config.from_object(config_by_name['prod'])
api.init_app(app)
db.init_app(app)
if __name__ == '__main__':
app.run(debug=True)
requirements.txt
-i https://pypi.org/simple
aniso8601==8.0.0
attrs==19.3.0
click==7.0
flask-restplus==0.13.0
flask-sqlalchemy==2.4.1
flask-swagger-ui==3.20.9
flask==1.1.1
importlib-metadata==0.23 ; python_version < '3.8'
itsdangerous==1.1.0
jinja2==2.10.3
jsonschema==3.2.0
markupsafe==1.1.1
more-itertools==7.2.0
mysql-connector-python==8.0.18
mysqlclient==1.4.4
protobuf==3.10.0
pyrsistent==0.15.5
pytz==2019.3
simplejson==3.17.0
six==1.13.0
sqlalchemy==1.3.11
werkzeug==0.16.0
zipp==0.6.0
gunicorn==19.9.0
app.yaml
runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app
runtime_config:
python_version: 3
config.py
class Config(object):
DEBUG = False
TESTING = False
connection_type = 'gcp' #tcp/ip
DB_SERVER = 'XXX.XXX.XXX.XXX'
DB_USERNAME = 'XXXX'
DB_PASSWORD = 'XXXX'
DB_NAME = 'XXXXX'
SQLALCHEMY_DATABASE_URI = f"mysql+mysqlconnector://{DB_USERNAME}:{DB_PASSWORD}@{DB_SERVER}/{DB_NAME}"
SQLALCHEMY_TRACK_MODIFICATIONS = False
class ProductionConfig(Config):
pass
config_by_name = dict(
dev = DevelopmentConfig,
test = TestingConfig,
prod = ProductionConfig
)
apis\__init__.py
from flask_restplus import Api
from .spa_system_resource import api as spa_name_space
from .stage_resource import api as stage_name_space
from .consolidated_resource import api as consolidated_name_space
from .cost_cat_resource import api as cost_cat_name_space
from .cost_resource import api as cost_name_space
from .log_resource import api as log_name_space
from .trm_resource import api as trm_name_space
from .energy_resource import api as energy_price_name_space
api = Api (
title='API - Spa System',
version='1.0',
description='XXXXXX',
contact='XXXXX',
contact_email='XXXXXXXXXXX',
contact_url='XXXXXXXX',
default_mediatype='application/json',
)
api.add_namespace(spa_name_space)
api.add_namespace(stage_name_space)
api.add_namespace(consolidated_name_space)
api.add_namespace(cost_name_space)
api.add_namespace(cost_cat_name_space)
api.add_namespace(log_name_space)
api.add_namespace(trm_name_space)
api.add_namespace(energy_price_name_space)
一个资源文件的提取:apis\log_resource.py
import datetime
from flask import current_app as app
from flask import Flask, request, jsonify, make_response
from flask_sqlalchemy import sqlalchemy
from flask_restplus import Namespace, Resource, reqparse, abort, fields
from werkzeug.exceptions import HTTPException
from res import DatabaseIntegrityError, DatabaseError, EngMsg as msg
from sqlalchemy.exc import SQLAlchemyError, IntegrityError
from models import Log, ModelList
from marshal_models import log_model_dict
api = Namespace('logs', description=msg.API_NAMESPACE_LOG_DESCRIPTION)
log_model = api.model('log', log_model_dict)
@api.route('/<log_id>')
@api.doc(responses={ 200: msg.API_DOC_RESPONSES_200,
400: msg.API_DOC_RESPONSES_400,
409: msg.API_DOC_RESPONSES_409,
500: msg.API_DOC_RESPONSES_500 })
class LogRes(Resource):
@api.doc(params={"log_id": msg.API_DOC_PARAMS_LOG_ID})
@api.marshal_with(log_model, skip_none=True)
def get(self, log_id):
try:
if log_id.isdigit():
return Log.query.get(log_id)
else:
app.logger.error(TypeError(msg.ERROR_TYPE_ERROR))
return msg.API_DOC_RESPONSES_400, 400
except DatabaseIntegrityError as err:
app.logger.error(err)
return msg.API_DOC_RESPONSES_409, 409
except HTTPException as err:
app.logger.error(f'HTTException: {err}')
return msg.API_DOC_RESPONSES_400, 400
except (Exception, DatabaseError) as err:
app.logger.error(err)
return msg.API_DOC_RESPONSES_500, 500
@api.doc(params={"log_id": msg.API_DOC_PARAMS_LOG_ID})
@api.expect(log_model, validate=True)
@api.marshal_with(log_model, skip_none=True)
def put(self, log_id):
try:
if log_id.isdigit():
log = Log.query.get(log_id)
if log:
log.update(api.payload)
return log
else:
app.logger.error(TypeError(msg.ERROR_TYPE_ERROR))
return msg.API_DOC_RESPONSES_400, 400
except DatabaseIntegrityError as err:
app.logger.error(err)
return msg.API_DOC_RESPONSES_409, 409
except HTTPException as err:
app.logger.error(f'HTTException: {err}')
return msg.API_DOC_RESPONSES_400, 400
except (Exception, DatabaseError) as err:
app.logger.error(err)
return msg.API_DOC_RESPONSES_500, 500
@api.doc(params={"log_id": msg.API_DOC_PARAMS_LOG_ID})
@api.response(204, msg.API_DOC_RESPONSES_204)
def delete(self, log_id):
try:
if log_id.isdigit():
log = Log.query.get(log_id)
if log:
log.delete()
return msg.API_DOC_RESPONSES_204, 204
else:
app.logger.error(TypeError(msg.ERROR_TYPE_ERROR))
return msg.API_DOC_RESPONSES_400, 400
except DatabaseIntegrityError as err:
app.logger.error(err)
return msg.API_DOC_RESPONSES_409, 409
except HTTPException as err:
app.logger.error(f'HTTException: {err}')
return msg.API_DOC_RESPONSES_400, 400
except (Exception, DatabaseError) as err:
app.logger.error(err)
return msg.API_DOC_RESPONSES_500, 500
浏览器中尝试调用 GET 方法的错误消息(2019 年 11 月 27 日更新):
gcp 中的错误日志(2019 年 11 月 27 日更新)
[
{
"protoPayload": {
"@type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
"appId": "p~maximal-beach-255318",
"versionId": "20191126t083944",
"requestId": "5dde722800ff01c4db2055869d0001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"ip": "217.182.175.162",
"startTime": "2019-11-27T12:55:04.115931Z",
"endTime": "2019-11-27T12:55:35.620208Z",
"latency": "31.504277s",
"megaCycles": "672",
"method": "HEAD",
"resource": "/stages/",
"httpVersion": "HTTP/1.1",
"status": 502,
"responseSize": "122",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36",
"urlMapEntry": "auto",
"host": "maximal-beach-255318.appspot.com",
"cost": 1.3634e-8,
"instanceIndex": -1,
"finished": true,
"instanceId": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49",
"appEngineRelease": "1.9.71",
"traceId": "66545566d74d32b65a44ef6b5e8eb3e1",
"first": true,
"traceSampled": true
},
"insertId": "5dde72470009773abcebccc9",
"httpRequest": {
"status": 502
},
"resource": {
"type": "gae_app",
"labels": {
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944"
}
},
"timestamp": "2019-11-27T12:55:04.115931Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/appengine.googleapis.com%2Frequest_log",
"operation": {
"id": "5dde722800ff01c4db2055869d0001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"producer": "appengine.googleapis.com/request_id",
"first": true,
"last": true
},
"trace": "projects/maximal-beach-255318/traces/66545566d74d32b65a44ef6b5e8eb3e1",
"receiveTimestamp": "2019-11-27T12:55:35.626061163Z",
"traceSampled": true
},
{
"textPayload": "[2019-11-27 12:45:27 +0000] [20] [INFO] Booting worker with pid: 20",
"insertId": "5dde6fe70007e247c06a652a",
"resource": {
"type": "gae_app",
"labels": {
"version_id": "20191126t083944",
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318"
}
},
"timestamp": "2019-11-27T12:45:27.516679Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T12:45:27.671289763Z"
},
{
"textPayload": "[2019-11-27 12:45:26 +0000] [7] [CRITICAL] WORKER TIMEOUT (pid:19)",
"insertId": "5dde6fe6000528928a3fd08e",
"resource": {
"type": "gae_app",
"labels": {
"version_id": "20191126t083944",
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318"
}
},
"timestamp": "2019-11-27T12:45:26.338066Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T12:45:26.344938571Z"
},
{
"protoPayload": {
"@type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
"appId": "p~maximal-beach-255318",
"versionId": "20191126t083944",
"requestId": "5dde6fc700ff0b4dadaec6e11e0001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"ip": "190.217.67.6",
"startTime": "2019-11-27T12:44:55.740781Z",
"endTime": "2019-11-27T12:45:27.355877Z",
"latency": "31.615096s",
"megaCycles": "662",
"method": "GET",
"resource": "/logs/",
"httpVersion": "HTTP/1.1",
"status": 502,
"responseSize": "690",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
"urlMapEntry": "auto",
"host": "maximal-beach-255318.appspot.com",
"cost": 7.7113e-8,
"instanceIndex": -1,
"finished": true,
"instanceId": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49",
"appEngineRelease": "1.9.71",
"traceId": "17ca3e3af386e29af2197260dd20ca5b",
"first": true,
"traceSampled": true
},
"insertId": "5dde6fe700056f2d0a6185c7",
"httpRequest": {
"status": 502
},
"resource": {
"type": "gae_app",
"labels": {
"version_id": "20191126t083944",
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318"
}
},
"timestamp": "2019-11-27T12:44:55.740781Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/appengine.googleapis.com%2Frequest_log",
"operation": {
"id": "5dde6fc700ff0b4dadaec6e11e0001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"producer": "appengine.googleapis.com/request_id",
"first": true,
"last": true
},
"trace": "projects/maximal-beach-255318/traces/17ca3e3af386e29af2197260dd20ca5b",
"receiveTimestamp": "2019-11-27T12:45:27.357040172Z",
"traceSampled": true
},
{
"textPayload": "[2019-11-27 12:44:50 +0000] [19] [INFO] Booting worker with pid: 19",
"insertId": "5dde6fc200029a6115a11cd3",
"resource": {
"type": "gae_app",
"labels": {
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944",
"module_id": "default",
"zone": "us-east1-3"
}
},
"timestamp": "2019-11-27T12:44:50.170593Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T12:44:50.177293952Z"
},
{
"textPayload": "[2019-11-27 12:44:48 +0000] [7] [CRITICAL] WORKER TIMEOUT (pid:18)",
"insertId": "5dde6fc0000ccba4ab7daec2",
"resource": {
"type": "gae_app",
"labels": {
"zone": "us-east1-3",
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944",
"module_id": "default"
}
},
"timestamp": "2019-11-27T12:44:48.838564Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T12:44:48.846320557Z"
},
{
"protoPayload": {
"@type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
"appId": "p~maximal-beach-255318",
"versionId": "20191126t083944",
"requestId": "5dde6fa200ff00ffb6f6484c386b0001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"ip": "190.217.67.6",
"startTime": "2019-11-27T12:44:18.046838Z",
"endTime": "2019-11-27T12:44:49.927998Z",
"latency": "31.881160s",
"megaCycles": "638",
"method": "GET",
"resource": "/stages/",
"httpVersion": "HTTP/1.1",
"status": 502,
"responseSize": "690",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
"urlMapEntry": "auto",
"host": "maximal-beach-255318.appspot.com",
"cost": 7.7113e-8,
"instanceIndex": -1,
"finished": true,
"instanceId": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49",
"appEngineRelease": "1.9.71",
"traceId": "f9abbbb57697d19e094bc6a7afe46fc4",
"first": true,
"traceSampled": true
},
"insertId": "5dde6fc1000e377f4c815764",
"httpRequest": {
"status": 502
},
"resource": {
"type": "gae_app",
"labels": {
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944"
}
},
"timestamp": "2019-11-27T12:44:18.046838Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/appengine.googleapis.com%2Frequest_log",
"operation": {
"id": "5dde6fa200ff00ffb6f6484c386b0001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"producer": "appengine.googleapis.com/request_id",
"first": true,
"last": true
},
"trace": "projects/maximal-beach-255318/traces/f9abbbb57697d19e094bc6a7afe46fc4",
"receiveTimestamp": "2019-11-27T12:44:49.941671848Z",
"traceSampled": true
},
{
"protoPayload": {
"@type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
"appId": "p~maximal-beach-255318",
"versionId": "20191126t083944",
"requestId": "5dde6f9000ff09e526316e53900001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"ip": "190.217.67.6",
"startTime": "2019-11-27T12:44:00.648486Z",
"endTime": "2019-11-27T12:44:05.324856Z",
"latency": "4.676370s",
"megaCycles": "2744",
"method": "GET",
"resource": "/favicon.ico",
"httpVersion": "HTTP/1.1",
"status": 404,
"responseSize": "385",
"referrer": "http://maximal-beach-255318.appspot.com/stages/",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
"urlMapEntry": "auto",
"host": "maximal-beach-255318.appspot.com",
"cost": 4.3027e-8,
"instanceIndex": -1,
"finished": true,
"instanceId": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49",
"appEngineRelease": "1.9.71",
"traceId": "18628020e642702bce4c2e0b3187e2ce",
"first": true,
"traceSampled": true
},
"insertId": "5dde6f9500069b4e77b19ab5",
"httpRequest": {
"status": 404
},
"resource": {
"type": "gae_app",
"labels": {
"zone": "us-east1-3",
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944",
"module_id": "default"
}
},
"timestamp": "2019-11-27T12:44:00.648486Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/appengine.googleapis.com%2Frequest_log",
"operation": {
"id": "5dde6f9000ff09e526316e53900001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"producer": "appengine.googleapis.com/request_id",
"first": true,
"last": true
},
"trace": "projects/maximal-beach-255318/traces/18628020e642702bce4c2e0b3187e2ce",
"receiveTimestamp": "2019-11-27T12:44:05.434941402Z",
"traceSampled": true
},
{
"textPayload": "[2019-11-27 12:44:00 +0000] [18] [INFO] Booting worker with pid: 18",
"insertId": "5dde6f900009af56ce378348",
"resource": {
"type": "gae_app",
"labels": {
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944",
"module_id": "default",
"zone": "us-east1-3"
}
},
"timestamp": "2019-11-27T12:44:00.634710Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T12:44:00.697087376Z"
},
{
"textPayload": "[2019-11-27 12:43:59 +0000] [7] [CRITICAL] WORKER TIMEOUT (pid:15)",
"insertId": "5dde6f8f00057bd7123ebed3",
"resource": {
"type": "gae_app",
"labels": {
"zone": "us-east1-3",
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944",
"module_id": "default"
}
},
"timestamp": "2019-11-27T12:43:59.359383Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T12:43:59.367903796Z"
},
{
"protoPayload": {
"@type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
"appId": "p~maximal-beach-255318",
"versionId": "20191126t083944",
"requestId": "5dde6f7100ff03b1470e1729150001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"ip": "190.217.67.6",
"startTime": "2019-11-27T12:43:29.241991Z",
"endTime": "2019-11-27T12:44:00.433791Z",
"latency": "31.191800s",
"megaCycles": "670",
"method": "GET",
"resource": "/stages/",
"httpVersion": "HTTP/1.1",
"status": 502,
"responseSize": "690",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
"urlMapEntry": "auto",
"host": "maximal-beach-255318.appspot.com",
"cost": 7.7113e-8,
"instanceIndex": -1,
"finished": true,
"instanceId": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49",
"appEngineRelease": "1.9.71",
"traceId": "2eb1e05b6e3607b82bc6eb1581f7030b",
"first": true,
"traceSampled": true
},
"insertId": "5dde6f900006aa2783948800",
"httpRequest": {
"status": 502
},
"resource": {
"type": "gae_app",
"labels": {
"zone": "us-east1-3",
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944",
"module_id": "default"
}
},
"timestamp": "2019-11-27T12:43:29.241991Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/appengine.googleapis.com%2Frequest_log",
"operation": {
"id": "5dde6f7100ff03b1470e1729150001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"producer": "appengine.googleapis.com/request_id",
"first": true,
"last": true
},
"trace": "projects/maximal-beach-255318/traces/2eb1e05b6e3607b82bc6eb1581f7030b",
"receiveTimestamp": "2019-11-27T12:44:00.443084831Z",
"traceSampled": true
},
{
"textPayload": "[2019-11-27 07:52:18 +0000] [7] [INFO] Shutting down: Master",
"insertId": "5dde2b32000662725bdd088d",
"resource": {
"type": "gae_app",
"labels": {
"version_id": "20191126t083531",
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318"
}
},
"timestamp": "2019-11-27T07:52:18.418418Z",
"labels": {
"clone_id": "00c61b117c8a2ff2cf91e014f80fd771ceb13ae6f293bfa1dfe53396a1fe807c93d66bb6"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T07:52:18.465138763Z"
},
{
"textPayload": "[2019-11-27 07:52:17 +0000] [20] [INFO] Worker exiting (pid: 20)",
"insertId": "5dde2b31000cbb519c6bb001",
"resource": {
"type": "gae_app",
"labels": {
"version_id": "20191126t083531",
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318"
}
},
"timestamp": "2019-11-27T07:52:17.834385Z",
"labels": {
"clone_id": "00c61b117c8a2ff2cf91e014f80fd771ceb13ae6f293bfa1dfe53396a1fe807c93d66bb6"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T07:52:18.129370130Z"
},
{
"textPayload": "[2019-11-27 07:52:17 +0000] [7] [INFO] Handling signal: term",
"insertId": "5dde2b310009e8722b2030e5",
"resource": {
"type": "gae_app",
"labels": {
"version_id": "20191126t083531",
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318"
}
},
"timestamp": "2019-11-27T07:52:17.649330Z",
"labels": {
"clone_id": "00c61b117c8a2ff2cf91e014f80fd771ceb13ae6f293bfa1dfe53396a1fe807c93d66bb6"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T07:52:17.795680101Z"
},
{
"textPayload": "[2019-11-27 02:15:44 +0000] [15] [INFO] Booting worker with pid: 15",
"insertId": "5ddddc5000013018cd840898",
"resource": {
"type": "gae_app",
"labels": {
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944",
"module_id": "default",
"zone": "us-east1-3"
}
},
"timestamp": "2019-11-27T02:15:44.077848Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T02:15:44.269814707Z"
},
{
"textPayload": "[2019-11-27 02:15:43 +0000] [7] [INFO] Using worker: sync",
"insertId": "5ddddc4f000e3a8221b4647f",
"resource": {
"type": "gae_app",
"labels": {
"version_id": "20191126t083944",
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318"
}
},
"timestamp": "2019-11-27T02:15:43.932482Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T02:15:44.269814707Z"
},
{
"textPayload": "[2019-11-27 02:15:43 +0000] [7] [INFO] Listening at: http://0.0.0.0:8081 (7)",
"insertId": "5ddddc4f000e3a5ed3d9fe86",
"resource": {
"type": "gae_app",
"labels": {
"zone": "us-east1-3",
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944",
"module_id": "default"
}
},
"timestamp": "2019-11-27T02:15:43.932446Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T02:15:44.269814707Z"
},
{
"textPayload": "[2019-11-27 02:15:43 +0000] [7] [INFO] Starting gunicorn 19.9.0",
"insertId": "5ddddc4f000e32a95dc08c06",
"resource": {
"type": "gae_app",
"labels": {
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944"
}
},
"timestamp": "2019-11-27T02:15:43.930473Z",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/stderr",
"receiveTimestamp": "2019-11-27T02:15:43.935820537Z"
},
{
"protoPayload": {
"@type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
"appId": "p~maximal-beach-255318",
"versionId": "20191126t083944",
"requestId": "5ddddc4e00ff05cca307340a140001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"ip": "186.84.21.80",
"startTime": "2019-11-27T02:15:42.380067Z",
"endTime": "2019-11-27T02:15:45.795201Z",
"latency": "3.415134s",
"megaCycles": "4969",
"method": "GET",
"resource": "/favicon.ico",
"httpVersion": "HTTP/1.1",
"status": 404,
"responseSize": "380",
"referrer": "http://maximal-beach-255318.appspot.com/stages/",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
"urlMapEntry": "auto",
"host": "maximal-beach-255318.appspot.com",
"cost": 4.2468e-8,
"wasLoadingRequest": true,
"instanceIndex": -1,
"finished": true,
"instanceId": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49",
"line": [
{
"time": "2019-11-27T02:15:45.794925Z",
"severity": "INFO",
"logMessage": "This request caused a new process to be started for your application, and thus caused your application code to be loaded for the first time. This request may thus take longer and use more CPU than a typical request for your application."
}
],
"appEngineRelease": "1.9.71",
"traceId": "55744f06ecd2c9f36584f78dd72858dd",
"first": true,
"traceSampled": true
},
"insertId": "5ddddc51000c22e862aa1128",
"httpRequest": {
"status": 404
},
"resource": {
"type": "gae_app",
"labels": {
"module_id": "default",
"zone": "us-east1-3",
"project_id": "maximal-beach-255318",
"version_id": "20191126t083944"
}
},
"timestamp": "2019-11-27T02:15:42.380067Z",
"severity": "INFO",
"labels": {
"clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
},
"logName": "projects/maximal-beach-255318/logs/appengine.googleapis.com%2Frequest_log",
"operation": {
"id": "5ddddc4e00ff05cca307340a140001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
"producer": "appengine.googleapis.com/request_id",
"first": true,
"last": true
},
"trace": "projects/maximal-beach-255318/traces/55744f06ecd2c9f36584f78dd72858dd",
"receiveTimestamp": "2019-11-27T02:15:45.804618825Z",
"traceSampled": true
},
多亏了你提供的错误信息,事情现在更清楚了。所以这条消息
Mixed Content: The page at '*****' was loaded over HTTPS, but requested an insecure resource 'http://****/swagger.json'. This content should also be served over HTTPS.
表示您的 App Engine 正在尝试通过 HTTPS 提供内容。但是,您的 Flask Restplus 正在发送 HTTP 请求。这里它试图获取“http://****/swagger.json”
使用 HTTP 请求。由于这种不匹配,呼叫被阻止,您收到“未提供 API 定义”。
为了解决这个问题,我注意到您正在使用“werkzeug”中间件。
将此代码添加到您的 Flask 初始化中:
from werkzeug.middleware.proxy_fix import ProxyFix
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app)
您可以阅读原始问题 here。
希望对您有所帮助。