从App Engine构建缓存时如何平衡负载?

时间:2015-10-07 07:54:33

标签: java google-app-engine caching load-balancing

我目前有以下情况,现在困扰了我几个月。

案例

我已经构建了一个Java(FX)应用程序,它可以作为我店铺的现金登记处。该应用程序包含许多类(如客户,客户,事务等),这些类与服务器API共享。服务器API托管在Google App Engine上。

因为我们也有一个在线商店,所以我选择在应用程序启动时构建整个数据库的缓存。为此,我为每个类/表调用我的Data API的GET:

protected QueryBuilder performGet(HttpServletRequest req, HttpServletResponse res)
        throws ServletException, IOException, ApiException, JSONException {

    Connection conn = connectToCloudSQL();

    log.info("Parameters: "+Functions.parameterMapToString(req.getParameterMap()));

    String tableName = this.getTableName(req);
    log.info("TableName: "+tableName);
    GetQueryBuilder queryBuilder = DataManager.executeGet(conn, req.getParameterMap(), tableName, null);

    //Get the correct method to create the objects
    String camelTableName = Functions.snakeToCamelCase(tableName);
    String parsedTableName = Character.toUpperCase(camelTableName.charAt(0)) + camelTableName.substring(1);

    List<Object> objects = new ArrayList<>();
    try {

        log.info("Parsed Table Name: "+parsedTableName);
        Method creationMethod = ObjectManager.class.getDeclaredMethod("create"+parsedTableName, ResultSet.class, boolean.class);

        while (queryBuilder.getResultSet().next()) {

            //Create new objects with the ObjectManager
            objects.add(creationMethod.invoke(null, queryBuilder.getResultSet(), false));
        }
        log.info("List of objects created");

        creationMethod = null;
    }
    catch (Exception e) {
        camelTableName = null;
        parsedTableName = null;
        objects = null;
        throw new ApiException(e, "Something went wrong while iterating through ResultSet.", ErrorStatus.NOT_VALID);
    }

    Functions.listOfObjectsToJson(objects, res.getOutputStream());

    log.info("GET Request succeeded");

    //Clean up objects
    camelTableName = null;
    parsedTableName = null;
    objects = null;

    closeConnection(conn);

    return queryBuilder;

}

简单从我的Cloud SQL数据库中获取所请求表中的每一行。然后,它使用与客户端应用程序共享的类创建对象。最后,它使用GSON将这些类转换为JSON。我的一些表有10.000多行,然后它需要大约。这需要5-10秒。

在客户端,我使用相同的共享类将此JSON转换回对象列表。首先,我按顺序加载基本类(因为否则应用程序将无法启动),然后在后台使用单独的线程加载其余类。

问题

每次加载缓存时,服务器都会在某些较大的表上以DeadlineExceededException响应,有机会(1/4)。我认为这与Google App Engine无法及时启动新实例有关,因此计算时间超出限制。

我知道它与在后台线程中加载对象有关,因为这些都是在同一时间开始的。当我用3秒延迟这些线程的启动时,错误发生的次数要少得多,但仍然存在。因为应用程序在后台加载了15个类,所以延迟它们并不理想,因为应用程序只有在完成后才能部分工作。在开始之前加载所有内容也不是一个选项,因为这将花费超过2分钟。

有人知道如何在Google App Engine上为此设置一些负载平衡吗?我想解决这个服务器端。

1 个答案:

答案 0 :(得分:1)

您显然遇到热身请求和需要很长时间的查询的问题。你有通常的选择:

  • 进行一些分析并降低方法调用的成本
  • 使用缓存(memcache)缓存部分结果

如果这些选项对您不起作用,则应该并行化计算。我想到的一件事是,如果您只是将请求拆分为多个并行请求,则可以可靠地减少请求时间,如下所示:

  • 我们说你的桌子包含5k行。
  • 然后创建50个请求,每个请求处理100行。
  • 在服务器或客户端聚合结果并回复

在服务器端这样做很难,但是如果现在(很多)较小的接收在几秒钟内恢复就应该可以。

或者,您可以立即返回作业ID,并在几秒钟内对客户端进行轮询。然而,这需要在客户端进行少量更改。这是imho的更好选择,特别是如果您想使用任务队列来创建响应。