【问题标题】:New Google App Engine Datastore API doesn't seem to throw as many exceptions?新的 Google App Engine Datastore API 似乎没有抛出那么多异常?
【发布时间】:2012-05-19 02:43:08
【问题描述】:

我针对 Java Google App Engine 1.6.4.1 API 编写了一些代码,为了让我的代码能够编译,我必须处理很多异常,例如 ConcurrentModificationException。我升级到 1.6.5,现在我可以删除大部分异常处理程序,并且我的代码编译得很好。怎么回事?

更新:不再抛出几类异常;因为这可能是由于不同的原因导致不同的异常而发生的,这里是不再被抛出的异常

  • IllegalArgumentException

  • IllegalStateException

  • DatastoreFailureException

  • ConcurrentModificationException

以下是有人在 GAE 中获得 IllegalArgumentException 的示例:Google App Engine - "java.lang.IllegalArgumentException: datastore transaction or write too big." 这种情况不能再发生了吗?

事务接口文档说你可以在执行 commit() 时获得最后三个中的任何一个:https://developers.google.com/appengine/docs/java/javadoc/com/google/appengine/api/datastore/Transaction#commit()

投掷:

java.lang.IllegalStateException - 如果事务已经 提交、回滚、提交或回滚正在进行中(通过 异步调用),或者尝试提交或回滚已经失败。 如果在此方法运行时有任何未完成的异步数据存储调用 调用时,此方法将在这些调用完成时阻塞 在继续之前。

DatastoreFailureException - 如果发生数据存储错误。

java.util.ConcurrentModificationException - 如果有其他事务 同时修改了相同的实体组。

但我不再需要处理它们来编译我的代码。这似乎很奇怪。

【问题讨论】:

    标签: java google-app-engine exception-handling google-cloud-datastore


    【解决方案1】:

    最新版本的 Google App Engine 要求在 appengine-web.xml 中设置 <threadsafe>true</threadsafe> 属性。在此版本之前,这不是必需的。

    当您的应用程序中的一个对象实例同时被多个线程修改时,会发生 ConcurrentModificationExceptions。这当然会导致数据和结果不一致,并且某些类会抛出此异常,以代替返回错误数据或对数据库进行不一致的更改。

    将 threadsafe 属性设置为 true,现在可以启用并发请求。

    Using Concurrent Requests

    默认情况下,App Engine 将请求串行发送到给定的网络服务器。您可以通过将元素添加到 appengine-web.xml 来配置 App Engine 以并行发送多个请求:

    <threadsafe>true</threadsafe>
    

    在 1.6.5 之前,threadsafe 指令是可选的,在 1.4.3 中引入:

    Java applications can enable concurrent request support by setting <threadsafe>
    to True in their appengine-web.xml. This flag indicates that request handlers
    for your app are thread safe and multiple request handlers may safely run
    at the same time in the same memory space for your application.
    

    虽然现在需要这样做,但似乎没有任何立即可用的信息可以解释为什么您的 ConcurrentModificationExceptions 突然消失了。如果您没有按照 1.4.3 发行说明中的​​建议对代码进行更改以使其成为线程安全的,那么这些线程安全问题很可能仍然存在。

    以下是博文Announcing App Engine 1.4.3 Release 中有关 1.4.3 版本的更多信息:

    并发请求:到目前为止,Java 应用程序依赖于启动额外的实例来动态扩展以适应更高的流量水平。现在支持并发请求,每个应用程序实例可以同时服务多个用户请求。首先,确保您的应用程序代码是线程安全的,然后通过将标志添加到您的 appengine-web.xml 来启用并发请求。

    如果您报告的异常已经消失,您的代码可能仍然存在一些线程安全问题。您可能没有看到这些,因为您增加了实例数量或在应用程序中执行了其他操作来缓解 ConcurrentModificationExceptions。

    考虑到 1.6.5 发布不到一个月,我会非常犹豫是否要从我的代码中删除我的异常处理程序。毕竟,他们的工作是检测和处理发生的问题,如果您删除它们,那么您将失去在删除它们之前可能已经存在的任何优雅降级。

    此外,不存在某些东西,例如异常,并不构成证明某些东西不会在未来某个未知时间点再次出现。

    来自javadocs for ConcurrentModificationException

    当这种修改是不允许的时,检测到对象的并发修改的方法可能会抛出此异常。

    例如,通常不允许一个线程在另一个线程对其进行迭代时修改 Collection。一般来说,在这些情况下,迭代的结果是不确定的。如果检测到此行为,某些 Iterator 实现(包括 JRE 提供的所有集合实现的那些)可能会选择抛出此异常。执行此操作的迭代器被称为快速失败迭代器,因为它们快速而干净地失败,而不是在未来不确定的时间冒着任意、非确定性行为的风险。

    【讨论】:

    • 我认为这个解释是不正确的,或者至少不是重点;请参阅 com.google.appengine.api.datastore.Transaction.commit() 的文档,我现在在问题的更新版本中链接到该文档;具体来说, Transaction.commit() 的文档说,如果“ConcurrentModificationException - 如果其他一些事务同时修改了相同的实体组”,则可以抛出它;这种情况与一个 Java VM 中的多线程无关,而是与数据存储的并发访问有关。
    • Daniel,我们一直要求人们在提出问题时要清楚,这样我们就不会浪费时间回答我们认为是问题的问题。也许我弄错了,但我不记得你最初的问题特别提到了交易。此外,当 any 集合被修改而另一个线程正在对其进行迭代时,可能会引发 ConcurrentModificationExceptions。这不仅限于数据存储,您的所有代码都必须是线程安全的。
    • 话虽如此,我仍然不是 100% 清楚你在问什么。您为什么不在问题中发布一些代码,这将提供一些有关您所指内容的上下文和示例。它肯定会帮助您获得您寻求的答案。此外,编辑您的问题会将其撞回“活动”页面的顶部,以便其他人以新修订的形式看到它。祝你好运!
    • 即使你假设开启线程安全是升级 GAE 所带来的不同,那是否会关闭在其他情况下抛出的 ConcurrentModificationExceptions,例如修改集合?
    • 问题现在很清楚我要问的是:数据存储区 API 似乎已停止抛出它们过去常常抛出的异常,例如我上面所说的 Transaction.commit()。跨度>
    【解决方案2】:

    我针对 Java Google App Engine 1.6.4.1 API 编写了一些代码,为了让我的代码能够编译,我必须处理很多异常,例如 ConcurrentModificationException。

    这里有些奇怪:ConcurrentModificationException 和您列出的其他异常是 RuntimeException 的子类。你永远不需要捕捉那些来满足 Java 编译器。

    【讨论】:

      猜你喜欢
      • 2012-07-09
      • 1970-01-01
      • 1970-01-01
      • 2010-11-19
      • 1970-01-01
      • 2013-06-02
      • 1970-01-01
      • 2013-03-03
      • 1970-01-01
      相关资源
      最近更新 更多