【问题标题】:How to handle write transactions when request time out in google app engine谷歌应用引擎中请求超时时如何处理写入事务
【发布时间】:2011-10-20 09:47:18
【问题描述】:

我是谷歌应用引擎的新手。我正在阅读昨天的应用引擎。我对请求超时期间的写入事务有疑问。

假设我正在创建 10,000 个对象并尝试通过这样的单个事务(假设 DatastoreService 就像一个 Hibernate 事务)来保存它

    String greeting = "test";
    String guestBookName = "default";
    DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService();
    Key guestBookKey = KeyFactory.createKey("GuestBook", guestBookName);
    for(int i=0;i<10000;i++)
    {
        Entity entity = new Entity("Greeting", guestBookKey);
        entity.setProperty("date", new Date());
        entity.setProperty("greeting", greeting);
        datastoreService.put(entity);
    }

假设保存1000个对象后,请求超时会删除1000个对象吗?

我已在应用引擎上运行此代码,在将 1164 个对象保存到数据存储区后,请求超时。我收到了这个错误

....Uncaught exception from servlet
com.google.apphosting.api.DeadlineExceededException: This request (0000000000000000)
started at 2011/10/20 07:18:36.726 UTC and was still executing at 2011/10/20 07:19:36.143 UTC.....

对象未从数据存储中删除。此外我读到here

数据存储可以在单个事务中执行多个操作。根据定义,除非事务中的每个操作都成功,否则事务不能成功。如果任何操作失败,事务将自动回滚。这对于分布式 Web 应用程序特别有用,其中多个用户可能同时访问或操作相同的数据。

谁能帮我清楚地理解这一点。

提前谢谢大家。

【问题讨论】:

  • 在阅读了网络上的各种帖子后,我想我找到了问题的答案。我正在考虑执行以下操作 编写一个 catch 块,每当时间到时,记录“i”的值并再次发送重定向到发送“i”作为参数的同一请求。现在,如果参数存在于 url 中,则取“i”的值并保存其余对象。方法对吗?
  • 更好的方法是在任务队列中执行此操作,而不是面向用户的请求。此外,将所有实体放在一个实体组中将对您可以支持的更新速率施加严格限制。
  • 谢谢@NickJohnson。能否请您给我一个适当的链接,我可以获得更多详细信息?

标签: google-app-engine


【解决方案1】:

GAE 事务仅适用于 Entity Group(具有相同根/父级的元素)。其次 - 它使用 乐观锁定,这意味着当其他线程在当前之前进行更改时,事务会失败。

这不是传统的交易。如果您的代码交易失败,您的对象将不会被删除

请阅读http://code.google.com/intl/en/appengine/docs/java/datastore/overview.html#Transactions_and_Entity_Groups

【讨论】:

  • 您好 splix,我无法理解您的回复,请您详细说明一下。谢谢
【解决方案2】:

我现在了解了如何处理对数据存储的写入。如果请求超时,我可以使用此代码回滚保存的对象。首先,我尝试了没有 Thread.sleep(int) 且 i

我现在对事务和数据存储有了一些了解。谢谢@splix

package guestbook;

import java.io.IOException;
import java.util.Date;
import java.util.logging.Logger;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Transaction;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.apphosting.api.DeadlineExceededException;

@SuppressWarnings("serial")
public class Test extends HttpServlet
{
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
    {
        Transaction transaction=null;
        try
        {
            String greeting = "test";
            String guestBookName = "default";
            UserService userService = UserServiceFactory.getUserService();
            User user = userService.getCurrentUser();
            DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService();
            transaction = datastoreService.beginTransaction();
            Key guestBookKey = KeyFactory.createKey("GuestBook", guestBookName);
            for(int i=0;i<4;i++)
            {
                Entity entity = new Entity("Greeting", guestBookKey);
                entity.setProperty("user", user);
                entity.setProperty("date", new Date());
                entity.setProperty("greeting", greeting+" "+i);
                datastoreService.put(entity);
                try {
                    Thread.sleep(1000*2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            transaction.commit();
        }catch(DeadlineExceededException e)
        {
            e.printStackTrace();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            Logger logger = Logger.getLogger(Test.class.getName());
            logger.info(""+transaction.isActive());
            if(transaction!=null)
                if(transaction.isActive())
                    transaction.rollback();
            logger.info(""+transaction.isActive());
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    • 2023-03-30
    • 1970-01-01
    • 2021-06-12
    • 2019-06-07
    • 2017-04-10
    • 1970-01-01
    相关资源
    最近更新 更多