运行 具有 Python-compact 的 GAE 柔性环境中的后台线程

Running background thread in GAE flexible environment with Python-compact

我正在努力将现有的 python GAE (Google App Engine) 标准环境应用程序迁移到灵活的环境。我通读了 guide 并决定试用 python-compact 运行 时间,因为尽可能多地重复使用代码总是好的。

在标准环境应用程序中,我们使用 background_thread.start_new_background_thread() 生成一堆无限循环线程以永远处理一些后台工作。但是,即使对于一些非常简单的应用程序,我也无法在灵活的环境中工作 start_new_background_thread。就像这个示例应用程序: github.com/GoogleCloudPlatform/python-docs-samples/tree/master/appengine/background

在云中 运行 应用程序时,我不断收到以下 error(尽管在本地运行良好)。

我使用云调试器对其进行了调试,但是在 background_thread.py

中引发异常时根本没有任何可用的错误消息

知道如何在 python-compact 运行time 的灵活环境中 运行 长期运行的后台线程吗?谢谢!

App Engine 标准版和 App Engine 灵活版之间的一个区别是,对于 Flex,我们实际上只是 运行 一个 docker 容器。我可以想到两种尝试方法。

1。只需使用 Python 多处理

App Engine 标准强制执行沙箱,这主要意味着不直接使用线程或进程。使用 Flex,您应该 能够只使用标准 Python 库来启动新的子进程:

https://docs.python.org/3/library/subprocess.html

2。使用 supervisord 和 docker

如果这不起作用,您可以在此处采用的另一种方法是自定义您在 Flex 中使用的 docker 图像,并使用 supervisord 启动多个进程。首先,通过 cd-ing 将源文件和 运行:

放入文件夹来生成 docker 文件

gcloud preview app gen-config --custom

这将创建一个您可以自定义的 Dockerfile。现在,您将要启动 2 个进程 - 我们正在启动的进程(我认为 python-compat 是 gunicorn)和您的后台进程。使用 docker 最简单的方法是使用 supervisord:

https://docs.docker.com/engine/admin/using_supervisord/

修改您的 Dockerfile 并添加 supervisord.conf 后,您可以像通常使用 gcloud preview app deploy 一样部署您的应用程序。

希望对您有所帮助!

我希望文档说 background_thread 不受支持 API。

无论如何,我发现了一些技巧可以帮助解决一些 线程不兼容问题。 App Engine 使用 os.environ 读取大量设置。您的应用程序中的 "real" 线程将在那里设置一堆环境变量。您启动的后台线程将有 none。我使用的一种技巧是复制一些环境变量。例如,为了让 App Engine 云存储库正常工作,我需要在后台线程中复制设置 SERVER_SOFTWARE 变量。我们使用类似的东西:

_global_server_software = None
_SERVER_SOFTWARE = 'SERVER_SOFTWARE'

def environ_wrapper(function, args):
    if _global_server_software is not None:
        os.environ[_SERVER_SOFTWARE] = _global_server_software
    function(*args)

def start_thread_with_app_engine_environ(function, *args):
    # HACK: Required for the cloudstorage API on Flexible environment threads to work
    # App Engine relies on a lot of environment variables to work correctly. New threads get none
    # of those variables. loudstorage uses SERVER_SOFTWARE to determine if it is a test instance
    global _global_server_software
    if _global_server_software is None and os.environ.get(_SERVER_SOFTWARE) is not None:
        _global_server_software = os.environ[_SERVER_SOFTWARE]

    t = threading.Thread(target=environ_wrapper, args=(
        function, args))
    t.start()