【发布时间】:2021-07-14 11:35:18
【问题描述】:
我注意到,当我使用 GAE 提供的请求线程工厂创建新线程时,新线程与父线程具有 相同 Environment。 (当前环境的identityHashCode在两个线程中都是一样的。)
一方面,这很好,因为新创建的线程以与父线程相同的上下文开始。 问题是环境不是一成不变的。它包含在命名空间处理中使用的“.currentNamespace”属性。如果其中一个线程更改了当前命名空间,它将应用于所有线程,这显然不是我想要的。
我解决这个问题的想法是我创建了一个自己的环境实现,当创建一个新线程时,我将当前环境的内容复制到这个新环境中,并将这个环境设置为新线程上的当前环境。因此,新线程以相同的上下文开始,但以后可以独立更改。
此解决方案在初始测试期间有效,但后来我遇到了问题
Caused by: java.lang.ClassCastException: MyEnvironmentImplementation cannot be cast to com.google.apphosting.runtime.ApiProxyImpl$EnvironmentImpl
at com.google.apphosting.runtime.ApiProxyImpl.log(ApiProxyImpl.java:67)
我无法访问com.google.apphosting.runtime.ApiProxyImpl 的代码,但很明显,此方法会尝试将接收到的接口转换为自己的实现类而不检查类型。
我觉得这很奇怪,因为 ApiProxy 中有一个 void setEnvironmentFactory(ApiProxy.EnvironmentFactory factory),因此预计有人可能会使用与默认实现不同的 Environment 接口实现。
还有其他方法可以在不同的请求线程中使用不同的命名空间吗?
这种未经检查的强制转换被认为是一个错误,还是使用我自己的环境实现从根本上是错误的?
我将应用引擎标准与 1.9.84 的 java sdk 一起使用。
编辑: 实际上记录了“这不应该从用户代码中使用”。在 ApiProxy.setEnvironmentForCurrentThread() 和 ApiProxy.setEnvironmentFactory() 方法。所以我建议的解决方法预计不会奏效。你也不应该尝试这样的事情。
【问题讨论】:
-
为什么需要在上下文中创建线程?只是为了了解您的背景和限制。
-
我有几个用例。最难替换为例如延迟任务是,当我需要使用不支持异步请求的客户端库发送多个远程调用时,对结果进行一些处理,然后在每个任务时在主线程中收集结果完成并继续请求。
-
根据您提到的内容,我将通过 GCP 问题跟踪器上的功能请求报告此问题。 cloud.google.com/support/docs/issue-trackersAFAIK,您无法在不同的请求线程中使用不同的命名空间,因此最好在那里报告它,以便将来可以对其进行审查
标签: java google-app-engine google-cloud-platform