【问题标题】:Environment sharing between request threads in Google App EngineGoogle App Engine 中请求线程之间的环境共享
【发布时间】: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


【解决方案1】:

无需使用 Google API 线程。不要让 Google API 给您带来麻烦。正如我在此处描述的那样,在浏览器之外自行执行此操作。

编写一个对浏览器进行子类化的程序,并对每个打开的窗口进行子类化。然后在每个页面上运行 javascript,将结果保存到位置栏,以便以后轻松收集。然后从位置栏中收集该信息,然后将以前的(位于位置栏中的)放回其中,以便将其视为与以前相同。

如果您想在不同的网页中使用该数据,请通过单独的程序将其放在那里。

理论上,每个打开的浏览器窗口都可以运行一个单独的 google api 进程。

通过您的程序分别对所有浏览器窗口进行子类化,让您的程序在它们之间共享信息,而不会混淆 google api。

像这样:

编写一个程序(在 VB6 sp5 中我是几年前做的。永远不要使用任何更高版本的 Visual Studio。在 C++11 中应该可以。)。

在本示例中使用 FireFox 作为浏览器。

(1) 启动您的程序并继承 FireFox。

(2) 让您的程序告诉 Firefox 打开一个新窗口(可能需要将此设置为 FireFox 的“新标签页”,也可能不需要)。

(3) 告诉你的程序获取新打开的窗口的预句柄。快速执行此操作并继续尝试(如果您的操作系统过载,则最多 30 秒)直到获得预句柄,然后为该新窗口或新选项卡分配一个新窗口的句柄。

(4) 使用那个新句柄并将 javascript 发送到地址栏(减去“j”),这意味着您将整个“avascript...”发送到该地址栏,然后添加之前的“j”因为如果 FireFox 检测到您将任何带有整个单词“javascript”的命令放入地址栏中,它将阻止您做一些事情(如果我没记错的话)。

(5) 运行 javascript 从每个页面中获取或放入您的更改。

(6) 浏览器中的网页,其中运行 javascript 完成部分工作。

(7) 无需使用 Google API 线程。

【讨论】:

  • 嗨!我不明白这一切与这个问题有什么关系。问题是关于 Google App Engine。这个解决方案根本不适合。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-04-23
  • 1970-01-01
  • 2016-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多