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

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

我目前遇到以下情况,这已经困扰了我几个月。

案例

我已经构建了一个 Java (FX) 应用程序,用作我商店的现金登记处。应用程序包含很多类(例如Customer、Customer、Transaction等),这些类与服务器API共享。服务器 API 托管在 Google App Engine 上。

因为我们也有一个在线商店,所以我选择在应用程序启动时构建整个数据库的缓存。为此,我为每个类/表调用数据 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 转换回对象列表。首先,我按顺序加载必要的类(因为否则应用程序将无法启动),然后我使用单独的线程在后台加载其余的类。

问题

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

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

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

最佳答案

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

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

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

  • 假设您的表格包含 5000 行。
  • 然后您创建 50 个请求,每个请求处理 100 行。
  • 汇总服务器端或客户端的结果并做出响应

仅在服务器端执行此操作非常困难,但如果您现在(小得多)的任务在几秒钟内返回,那么这应该是可能的。

或者,您可以立即返回作业 ID,并让客户端在几秒钟内轮询结果。然而,这需要在客户端进行一些小的改变。恕我直言,这是更好的选择,特别是如果您想使用任务队列来创建响应。

关于java - 从 App Engine 构建缓存时如何平衡负载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32986696/

相关文章:

java - 我可以在一个命令中链接 observableListclear() 和 addAll() 吗?

java - 何时/何地在 Google App Engine 中为搜索 API 创建索引 - Java

javascript - 将 Javascript 库与 Google App Engine 集成

java - 将 JDBC 数据源配置设置为 XML

java - 我不明白为什么我制作的类(class)不起作用

caching - Apollo Client v3 在给定时间段后删除缓存条目

java - hibernate 缓存和 Spring 框架缓存有什么区别?

caching - 缓存大小的容量规划

java - 修改 Koloboke Hashmap 时对其进行迭代

.htaccess - Google App-Engine 按国家/地区阻止传入流量?