Google App Engine api的命名空间管理器的范围是什么?

时间:2017-10-25 23:27:29

标签: python python-2.7 google-app-engine google-cloud-datastore

我正在通过多个域提供的Google App Engine Python标准环境中使用Flask构建API。

API可用于存储数据和获取数据。

我想使用云数据存储的多租户来存储或获取仅由访问API的域确定的命名空间中的数据。

我能看到的唯一方法是使用google.appengine.api.namespace_manager在请求时或在I / O时在上下文管理器中设置命名空间。

我写了这个上下文管理器:

@contextmanager
def multitenancy_namespace(namespace):
    original_namespace = namespace_manager.get_namespace()
    if namespace:
        new_namespace = to_namespace_safe_url(namespace)
        namespace_manager.set_namespace(new_namespace)

    yield

    namespace_manager.set_namespace(original_namespace)

它按预期工作。

我担心的是namespace_manager的范围。我无法找到任何关于此的文档。

如果我的API被> 1000个用户同时线程化并使用,假设namespace_manager.set_namespace(...)设置的命名空间是全局的,我会期待一些冲突 - 数据存储在错误的命名空间中,因为另一个请求叫{ {1}}在第一个请求之后,但在第一个请求执行其I / O之前。

我编写了一个传递的线程测试here,它告诉我set_namespace的范围至少局限于单个线程(这对我的Flask应用程序来说已经足够了)。

namespace的上下文? namespace_manager实际上做了什么?命名空间设置保存在哪里?是否存在名称空间冲突可能发生的用例?

1 个答案:

答案 0 :(得分:1)

如果您查看count的{​​{3}},您会看到它通过将命名空间设置为环境变量来实现:

namespace_manager.set_namespace(...)

当线程切换上下文时,AppEngine备份&根据需要恢复环境变量。保证它们受到请求限制,因此对用户的代码不透明。我不记得是否有这方面的文档,我想我已经在某个论坛帖子中学到了这一点。

评论def set_namespace(namespace): """Set the default namespace for the current HTTP request. Args: namespace: A string naming the new namespace to use. A value of None will unset the default namespace value. """ if namespace is None: os.environ.pop(_ENV_CURRENT_NAMESPACE, None) else: validate_namespace(namespace) os.environ[_ENV_CURRENT_NAMESPACE] = namespace 隐含地证实了这一点。

我们在source code使用了几年,这从来都不是问题。

如此放松,您可以安全地在多线程环境中使用它!