2

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

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

在云中运行应用程序时,我不断收到以下错误(虽然它在本地运行良好)。

我使用云调试器对其进行了调试,但是在 background_thread.py 中引发异常时,根本没有任何错误消息可用

知道如何使用 python-compact 运行时在灵活的环境中运行长寿命的后台线程吗?谢谢!

4

2 回答 2

2

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

1.只用Python多处理

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

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

2.使用supervisord和docker

如果这不起作用,您可以在此处采用的另一种方法是自定义您在 Flex 中使用的 docker 映像,并使用 supervisord 启动多个进程。首先,通过 cd-ing 到包含源代码的文件夹并运行来生成 dockerfile:

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

希望这可以帮助!

于 2016-05-29T22:20:25.563 回答
2

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

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

_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()
于 2016-10-05T21:35:22.323 回答