简体   繁体   English

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

[英]Google App Engine object exchange between instances

I am running a GAE java application and using backend instance for some computation. 我正在运行GAE Java应用程序,并使用后端实例进行一些计算。 After computation, backend instance creates a map which should be used by frontend while serving http requests. 经过计算,后端实例创建一个映射,供http请求使用时前端应使用该映射。

Initially I created the static map and I updated the map values using cron job running on backend instance. 最初,我创建了静态地图,并使用在后端实例上运行的cron作业更新了地图值。 But when I try to retrieve the value by sending http request, I still get old value. 但是当我尝试通过发送http请求来检索值时,我仍然得到旧值。 This is my code 这是我的代码

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
}

} }

This is my cron.xml 这是我的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>

And this is my backends.xml 这是我的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>

I believe both frontend and backend instances run separately and do not share objects. 我相信前端和后端实例都是单独运行的,并且不会共享对象。 When I run the cron job on frontend, it picks up the correct data. 当我在前端运行cron作业时,它将获取正确的数据。 So I am looking for a way so that I can use the same computed map by backend instance in frontend. 因此,我正在寻找一种方法,以便可以在前端通过后端实例使用相同的计算图。

Update1: After computing the hashmap on backend, I tried saving it in datastore, but I got an error stating "java.util.HashMap is not a supported property type". Update1:​​在后端计算了哈希表之后,我尝试将其保存在数据存储区中,但是出现错误,指出“ java.util.HashMap不是受支持的属性类型”。 So instead of creating a map, I created list and tried storing it in datastore. 因此,我没有创建地图,而是创建列表并尝试将其存储在数据存储区中。 But due to restriction on entity size (which is 1mb), I wasn't able to store the arraylist also in the datastore. 但是由于对实体大小的限制(1mb),我无法将arraylist也存储在数据存储中。

Update2: I converted my map into list, splitter it up into multiple smaller lists and stored them into different entities of datastore. Update2:我将地图转换为列表,将其拆分为多个较小的列表,并将其存储到数据存储区的不同实体中。 After storing, I fired up a task which should get executed on frontend. 存储后,我启动了一个应该在前端执行的任务。 This task reads the smaller lists from datastore, creates a big list out of them and finally creates a map which I am keeping in memory. 此任务从数据存储中读取较小的列表,从中创建一个大列表,最后创建一个我保存在内存中的映射。

You have at least five options: 您至少有五个选择:

  1. POST (I am not sure what the limit on App Engine is, but I would guess that up to 10MB should be fine). POST(我不确定App Engine的限制是多少,但我想最多10MB应该可以)。
  2. Datastore (no limit). 数据存储(无限制)。
  3. Google Cloud Storage (no limit). Google云端存储(无限制)。
  4. Dedicated memcache (up to 1MB). 专用的内存缓存(最大1MB)。
  5. Regular memcache backed by a datastore (up to 1MB). 由数据存储支持的常规内存缓存(最大1MB)。

The last option is probably the most cost-effective assuming your object fits in Memcache. 假设您的对象适合Memcache,则最后一个选项可能是最具成本效益的。 Your backend instance creates a map, puts it in a datastore and puts it into the Memcache. 您的后端实例会创建一个地图,将其放入数据存储区,然后将其放入Memcache。 Your front-end instance tries to load it from Memcache. 您的前端实例尝试从Memcache加载它。 If it's not available there, it loads it from the datastore and puts it into the Memcache in case it needs it again. 如果那里不可用,它将从数据存储加载它,并将其放入Memcache中,以备再次需要时使用。

UPDATE: 更新:

While your map is large, you can still go with the last, most effective, option. 当您的地图很大时,您仍然可以选择最后一个最有效的选择。 On the backend: 在后端:

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);

This will work if you don't need to know all keys on the front-end. 如果您不需要知道前端的所有键,这将起作用。 If you do, then check if your keySet() is smaller than 1MB so you can put it in Memcache as an object. 如果这样做,则检查keySet()是否小于1MB,以便可以将其作为对象放入Memcache。 If it's larger, then skip the memcache part and simply use the datastore: 如果更大,则跳过内存缓存部分,仅使用数据存储区即可:

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

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

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