java - Google App Engine 数据存储持久性太慢

标签 java google-app-engine jdo datanucleus google-cloud-endpoints

我正在开发一个 GAE/J 应用程序,使用 JDO 来管理数据存储区。它提供了许多端点来与数据交互等。我还在为这些端点开发一个 Javascript 客户端。

情况:

首先,我有一个端点方法Token getSessionToken(User usr),它生成一个 session token ,将其分配给用户并将用户和 session token 存储在数据存储区中。

然后我有另一个端点方法 Info getInfo(Token token) ,它接收 session token ,检查该 session token 是否对应于用户,如果是,则返回一些信息。

问题

从我的 Javascript 客户端,我调用第一个方法,一切都很好。然后,我使用之前检索的 session token 调用第二个方法,并且收到一条错误,指出该 session token 不对应于任何用户...

我已经检查过,我意识到发生此错误只是因为新的 session token 尚未持久化!

问题

我目前的解决方案是让Javascript客户端调用第二个方法一次,如果收到错误,等待一段时间再调用...有更好的解决方案吗?

<小时/>

编辑:

这是第一个方法调用中涉及的代码,以了解为什么需要这么长时间......

端点:

@ApiMethod(
    name = "getSessionToken",
    path = "get_session_token",
    httpMethod = HttpMethod.GET
)
public SessionToken getSessionToken (@Named("email") String email, @Named("password") String password) 
        throws InternalServerErrorException {       
    SessionToken sessionToken = new UsersController().getSessionToken(email, password);
    return sessionToken;
}

控制:

public SessionToken getSessionToken(String email, String password) throws InternalServerErrorException {        
    SessionToken sessionToken = null;
    
    PersistenceManager pm = PMF.get().getPersistenceManager();      
    Transaction txn = DatastoreServiceFactory.getDatastoreService().beginTransaction();
    try {
        DAO dao = new DAO(pm);
        
        User user = dao.getUserByLogin(email, password);
        
        dao.deleteSessionToken(user.getSessionToken());
        sessionToken = SessionTokenManager.generateToken(user.getEmail(), user.getPassword());
        user.setSessionToken(sessionToken);
        
        user = dao.insertUser(user);    
    
        txn.commit();   
    
    } catch (Exception e) {
        throw new InternalServerErrorException();
    } finally {
        if (txn.isActive()) {
            txn.rollback();
        }
        pm.close();
    }       
    return sessionToken;
}

DAO:

public User getUserByLogin(String email, String password) throws InternalServerErrorException {
    User user = null;
    Query query = null;
    try {
        query = this.pm.newQuery(User.class);
        query.setFilter("email == emailParam && password == passwordParam");
        query.declareParameters("String emailParam, String passwordParam");     
        List<User> results = (List<User>) query.execute(email, password);
        user = results.get(0);
    } catch (Exception e) {
        e.printStackTrace();
        throw new InternalServerErrorException("Error in DAO.getUserByLogin()");
    } finally {
        query.closeAll();
    }
    return user;
}

/////

public void deleteSessionToken(SessionToken sessionToken) throws InternalServerErrorException {
    try {
        this.pm.deletePersistent(sessionToken);
    } catch (Exception e) {
        e.printStackTrace();
        throw new InternalServerErrorException("Error in DAO.deleteSessionToken()");
    }
}

/////

public User insertUser(User user) throws InternalServerErrorException {     
    try {
        this.pm.makePersistent(user);
    } catch (Exception e) {
        e.printStackTrace();
        throw new InternalServerErrorException("Error in DAO.insertUser()", e);
    }                
    return user;
}

型号:

@PersistenceCapable
public class User { 
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Key key;    
    @Persistent
    private String name;
    @Persistent
    private String email;
    @Persistent
    private String password;    
    @Persistent
    private Folder rootFolder;  
    @Persistent
    private SessionToken sessionToken;  
    @Persistent(defaultFetchGroup = "true")
    private AccountContainer accountContainer;
    //getters & setters
}

/////

@PersistenceCapable
public class SessionToken {         
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Key key;
    @Persistent
    private String token;
    @Persistent
    private Long created;
    @Persistent
    private String sha1;
    //getters & setters
}

最佳答案

也许以下其中一种是可能的并且适合您的需求

  • 您能否将这两个调用合并为“getSessionTokenAndInfo”调用?您将 token 和信息一起返回的地方。根据您的代码的工作方式, token 和用户对象可能已经可用并且不需要加载?

  • 使用某种形式的缓存,以便第一个端点在 memcache 中留下一些内容,这样就不需要在第二次调用中尝试从数据存储中检索它(至少在大多数情况下,memcache 应该是可靠的)对于这种情况来说足够了)。

关于java - Google App Engine 数据存储持久性太慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16441387/

相关文章:

java - 当自定义 Servlet Filter 中抛出错误时, doFilter 方法会被多次调用

java - 缓冲图像 : extract subimage with same data

java - Google App Engine - 无法编译生成的 JSP java 文件

python - Google App Engine 标准环境中的 Gunicorn 服务器

java - 仅存储 24 小时变量值

java - GWT + JDO + GAE,如何安排我的数据以提高性能

java - 让 JDO 持久性管理器保持 Activity 状态而不是关闭它?

java - 如何在 Unix 机器上使用 Java 从 Bloomberg 检索日终证券价格?

javascript - 在 Selenium Webdriver 中使用 Ctrl + 单击组合打开一个新选项卡

java - App Engine 日志中的/_ah/queue/__deferred__