我正在运行GAE java应用程序并使用后端实例进行一些计算。 在计算之后,后端实例创建了一个映射,该映射应该在服务http请求时由前端使用。
最初我创建了静态地图,并使用在后端实例上运行的cron作业更新了地图值。但是当我尝试通过发送http请求来检索值时,我仍然得到旧值。这是我的代码
public class ServerServlet extends HttpServlet {
public static Map<String,String> highQualityMap;
protected void doGet( HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
try{
String uri = request.getRequestURI();
PrintWriter out = response.getWriter();
if(uri.equalsIgnoreCase("/getstatus")){
String id = request.getParameter("id");
out.write(highQualityMap.get(id));
}
else if(uri.equalsIgnoreCase("/recacheAll")){
System.out.println("recache all");
buildData();
}
if(out!=null)
out.close();
}
catch(Exception e){
e.printStackTrace();
}
}
private void buildData(){
// here after some processing, data is populated in highQualityMap
}
}
这是我的cron.xml
<?xml version="1.0" encoding="UTF-8"?>
<cronentries>
<cron>
<url>/recacheAll</url>
<description>Repopulate the cache every 3 hours</description>
<schedule>every 3 hours</schedule>
<target>backend</target>
</cron>
</cronentries>
这是我的backends.xml
<?xml version="1.0" encoding="UTF-8"?>
<backends>
<backend name="backend">
<class>B1</class>
<options>
<dynamic>true</dynamic>
<public>false</public>
</options>
</backend>
</backends>
我相信前端和后端实例分别运行并且不共享对象。当我在前端运行cron作业时,它会获取正确的数据。 所以我正在寻找一种方法,以便我可以在前端使用相同的计算映射。
Update1:在后端计算hashmap之后,我尝试将其保存在数据存储区中,但是我收到一条错误,指出“java.util.HashMap不是受支持的属性类型”。因此,我创建了列表并尝试将其存储在数据存储区中,而不是创建地图。但是由于对实体大小的限制(1mb),我无法将arraylist也存储在数据存储区中。
Update2:我将地图转换为列表,将其拆分为多个较小的列表,并将它们存储到数据存储的不同实体中。存储之后,我启动了一个应该在前端执行的任务。此任务从数据存储中读取较小的列表,从中创建一个大列表,最后创建一个我保留在内存中的映射。
答案 0 :(得分:0)
您至少有五个选择:
假设您的对象适合Memcache,最后一个选项可能是最具成本效益的。您的后端实例创建一个映射,将其放入数据存储区并将其放入Memcache中。您的前端实例尝试从Memcache加载它。如果它在那里不可用,它会从数据存储区加载它并将其放入Memcache中以备它再次需要它。
更新:
虽然您的地图很大,但您仍然可以使用最后一个最有效的选项。在后端:
ArrayList<Entity> batch = new ArrayList<Entity>(500);
for (String key : map.keySet()) {
memcache.put(key, map.get(key));
Entity entity = new Entity("Entry", key);
entity.setUnindexedProperty("value", map.getKey());
/* or, if a value can be longer than 500 characters
* entity.setUnindexedProperty("value", new Text(map.getKey()));
*/
batch.add(entity);
if (batch.size() == 500) {
datastore.put(batch);
batch.clear();
}
}
datastore.put(batch);
如果您不需要知道前端的所有按键,这将有效。如果这样做,那么检查你的keySet()是否小于1MB,这样你就可以把它作为一个对象放在Memcache中。如果它更大,则跳过memcache部分并简单地使用数据存储区:
Query q = new Query("Entry");
// etc.