繁体   English   中英

实例之间的Google App Engine对象交换

[英]Google App Engine object exchange between instances

我正在运行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:​​在后端计算了哈希表之后,我尝试将其保存在数据存储区中,但是出现错误,指出“ java.util.HashMap不是受支持的属性类型”。 因此,我没有创建地图,而是创建列表并尝试将其存储在数据存储区中。 但是由于对实体大小的限制(1mb),我无法将arraylist也存储在数据存储中。

Update2:我将地图转换为列表,将其拆分为多个较小的列表,并将其存储到数据存储区的不同实体中。 存储后,我启动了一个应该在前端执行的任务。 此任务从数据存储中读取较小的列表,从中创建一个大列表,最后创建一个我保存在内存中的映射。

您至少有五个选择:

  1. POST(我不确定App Engine的限制是多少,但我想最多10MB应该可以)。
  2. 数据存储(无限制)。
  3. Google云端存储(无限制)。
  4. 专用的内存缓存(最大1MB)。
  5. 由数据存储支持的常规内存缓存(最大1MB)。

假设您的对象适合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。 如果更大,则跳过内存缓存部分,仅使用数据存储区即可:

Query q = new Query("Entry");
// etc.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM