App Engine Flexible 不能将数据存储与 websockets 示例一起使用
App Engine Flexible can't use datastore with websockets example
我尝试将 websockets 示例项目添加到数据存储项目并且 websockets 工作,但是当页面查询数据存储或尝试放置新实体时,我收到 502 响应。在日志中,它显示了服务工作者的严重错误。如果我删除 websocket 代码,数据存储区代码将按预期工作。我能看到的唯一区别是应用示例的入口点略有不同
websocket 示例使用
entrypoint: gunicorn -b :$PORT -k flask_sockets.worker main:app
而数据存储示例使用
entrypoint: gunicorn -b :$PORT main:app
websocket 示例 https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/appengine/flexible/websockets
数据存储示例
https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/appengine/flexible/datastore
正如您所说,flask_socket.worker 似乎有问题,我已经对其进行了测试,但它不适用于数据存储客户端。
我已经尝试 Flask-SocketIO framework 使用 eventlet worker 并且数据存储查询工作正常。
entrypoint: gunicorn -b :$PORT --worker-class eventlet -w 1 main:app
还需要在requirements.txt文件中添加eventlet模块eventlet==0.24.1
这样做的缺点是它破坏了与websocket代码的兼容性,所以你需要重写这部分。请记住,代码示例只是为了在几行中展示如何使用 Google 云产品并在不修改配置的情况下复制粘贴它们 app.yaml 不是一个好主意。
问题似乎是 GRPC(云数据存储客户端的默认传输机制)与 gevent 不兼容。除了使用不同的 websockets 框架之外,您还可以通过使用以下代码激活 grpc 的 gevent 兼容性补丁来解决此问题:
import grpc.experimental.gevent as grpc_gevent
grpc_gevent.init_gevent()
作为 Andrew 回答的补充,您可以将 gunicorn worker class 扩展到 运行 gRPC 应用程序。
# gevent_grpc_worker.py
from gunicorn.workers.ggevent import GeventWorker
from grpc.experimental import gevent
class GeventGrpcWorker(GeventWorker):
def patch(self):
super(GeventGrpcWorker, self).patch()
gevent.init_gevent()
self.log.info('patched grpc')
# config.py for gunicorn
import multiprocessing
from gevent_grpc_worker import GeventGrpcWorker
# http://docs.gunicorn.org/en/stable/design.html#how-many-workers
workers = multiprocessing.cpu_count() * 2 + 1
worker_connections = 10000
# Use an asynchronous worker as most of the work is waiting for websites to load
worker_class = '.'.join([GeventGrpcWorker.__module__,
GeventGrpcWorker.__name__])
timeout = 30
然后通过以下方式启动您的托管应用程序:
gunicorn -c config.py app:app
我尝试将 websockets 示例项目添加到数据存储项目并且 websockets 工作,但是当页面查询数据存储或尝试放置新实体时,我收到 502 响应。在日志中,它显示了服务工作者的严重错误。如果我删除 websocket 代码,数据存储区代码将按预期工作。我能看到的唯一区别是应用示例的入口点略有不同
websocket 示例使用
entrypoint: gunicorn -b :$PORT -k flask_sockets.worker main:app
而数据存储示例使用
entrypoint: gunicorn -b :$PORT main:app
websocket 示例 https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/appengine/flexible/websockets
数据存储示例 https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/appengine/flexible/datastore
正如您所说,flask_socket.worker 似乎有问题,我已经对其进行了测试,但它不适用于数据存储客户端。
我已经尝试 Flask-SocketIO framework 使用 eventlet worker 并且数据存储查询工作正常。
entrypoint: gunicorn -b :$PORT --worker-class eventlet -w 1 main:app
还需要在requirements.txt文件中添加eventlet模块eventlet==0.24.1
这样做的缺点是它破坏了与websocket代码的兼容性,所以你需要重写这部分。请记住,代码示例只是为了在几行中展示如何使用 Google 云产品并在不修改配置的情况下复制粘贴它们 app.yaml 不是一个好主意。
问题似乎是 GRPC(云数据存储客户端的默认传输机制)与 gevent 不兼容。除了使用不同的 websockets 框架之外,您还可以通过使用以下代码激活 grpc 的 gevent 兼容性补丁来解决此问题:
import grpc.experimental.gevent as grpc_gevent
grpc_gevent.init_gevent()
作为 Andrew 回答的补充,您可以将 gunicorn worker class 扩展到 运行 gRPC 应用程序。
# gevent_grpc_worker.py
from gunicorn.workers.ggevent import GeventWorker
from grpc.experimental import gevent
class GeventGrpcWorker(GeventWorker):
def patch(self):
super(GeventGrpcWorker, self).patch()
gevent.init_gevent()
self.log.info('patched grpc')
# config.py for gunicorn
import multiprocessing
from gevent_grpc_worker import GeventGrpcWorker
# http://docs.gunicorn.org/en/stable/design.html#how-many-workers
workers = multiprocessing.cpu_count() * 2 + 1
worker_connections = 10000
# Use an asynchronous worker as most of the work is waiting for websites to load
worker_class = '.'.join([GeventGrpcWorker.__module__,
GeventGrpcWorker.__name__])
timeout = 30
然后通过以下方式启动您的托管应用程序:
gunicorn -c config.py app:app