我目前有以下情况,现在困扰了我几个月。
案例
我已经构建了一个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上为此设置一些负载平衡吗?我想解决这个服务器端。
答案 0 :(得分:1)
您显然遇到热身请求和需要很长时间的查询的问题。你有通常的选择:
如果这些选项对您不起作用,则应该并行化计算。我想到的一件事是,如果您只是将请求拆分为多个并行请求,则可以可靠地减少请求时间,如下所示:
在服务器端这样做很难,但是如果现在(很多)较小的接收在几秒钟内恢复就应该可以。
或者,您可以立即返回作业ID,并在几秒钟内对客户端进行轮询。然而,这需要在客户端进行少量更改。这是imho的更好选择,特别是如果您想使用任务队列来创建响应。