Является ли Memcache (Java) для Google App Engine глобальным кешем?

Я новичок в Google App Engine, и я провел последние несколько дней, создав приложение, используя GAE Memcache для хранения данных. Основываясь на моих первоначальных выводах, похоже, что GAE Memcache НЕ глобальный?

Позвольте мне объяснить далее. Я знаю, что разные запросы к GAE потенциально могут обслуживаться разными экземплярами (на самом деле это происходит довольно часто). Именно по этой причине я использую Memcache для хранения некоторых общих данных, в отличие от статической карты. Я подумал (возможно, неправильно), что это было целью использования распределенного кеша, чтобы доступ к данным мог получить любой node.

Другая определенная возможность заключается в том, что я делаю что-то неправильно. Я пробовал как JCache, так и низкоуровневый API Memcache (я пишу Java, а не Python). Это то, что я делаю, чтобы извлечь кеш:

MemcacheService cache = MemcacheServiceFactory.getMemcacheService();

После развертывания это то, что я просматриваю (через журналы приложений):

  • Исходный запрос обслуживается конкретным node, а данные хранятся в кэше, полученном выше.
  • Новые несколько запросов извлекают этот же кеш и данные там.
  • Когда новый запрос node генерируется для обслуживания запроса (из журналов, которые я знаю, когда это происходит, потому что GAE регистрирует тот факт, что "этот запрос вызвал новый процесс для вашего приложения.." ), кеш извлекается и является ПУСТОЙ!

Теперь я также знаю, что нет гарантии того, сколько данных будет в Memcache, но из моих выводов кажется, что данные ушли в тот момент, когда экземпляр diff пытается получить доступ к кешу. Кажется, это противоречит всей концепции распределенного глобального кеша?

Надеюсь, кто-то может прояснить, как это должно быть СЛЕДУЕТ. Если Memcache НЕ должен быть глобальным, и каждый экземпляр сервера имеет свою собственную копию, то почему даже использовать Memcache? Я мог бы просто использовать статический HashMap (который я изначально сделал, пока не понял, что он не будет глобальным из-за того, что разные экземпляры обслуживают мои запросы).

Помощь?

Ответы

Ответ 1

Да, Memcache используется во всех экземплярах вашего приложения.

Ответ 2

Я нашел проблему и получил ее работу. Сначала я использовал API JCache и не мог заставить его работать, поэтому я перешел на низкоуровневый API Memcache, но забыл удалить старый код JCache. Таким образом, они реализовали две реализации друг на друга.

Я не уверен, почему реализация JCache не работала, поэтому я поделюсь кодом:

    try {
        if (CacheManager.getInstance().getCache(CACHE_GEO_CLIENTS) == null) {
            Cache cache = CacheManager.getInstance().getCacheFactory().createCache(Collections.emptyMap());
            cache.put(CACHE_GEO_CLIENTS, new HashMap<String, String>());
            CacheManager.getInstance().registerCache(CACHE_GEO_CLIENTS, cache);
        }

    } catch (CacheException e) {

        log.severe("Exception while creating cache: " + e);

    }

Этот блок кода находится внутри частного конструктора для одноэлементного имени CacheService. Этот синглтон служит фасадом кэш-памяти. Обратите внимание: поскольку запросы могут обслуживаться разными узлами, каждый node будет иметь этот экземпляр Singleton. Поэтому, когда Singleton создается в первый и единственный раз, он проверяет, доступен ли мой кеш. Если нет, это создаст его. Это должно произойти технически только один раз, так как Memcache глобально да? Другая несколько странная вещь, которую я здесь делаю, - создать единую запись кэша типа HashMap для хранения моих фактических значений. Я делаю это, потому что мне нужно перечислить все ключи и что-то, что я не могу сделать с Memcache изначально.

Что я здесь делаю неправильно?

Ответ 3

Джерри, есть два вопроса, которые я вижу с кодом, который вы указали выше:

1) Вы используете версию API javax.cache. Согласно Google, это устарело: http://groups.google.com/group/google-appengine-java/browse_thread/thread/5820852b63a7e673/9b47f475b81fb40e?pli=1

Вместо этого предполагается, что мы используем библиотеку net.sf.jsr107 до тех пор, пока JSR не будет завершена.

Я не знаю, что использование старого API вызовет определенную проблему, но все еще может быть проблемой.

2) Я не вижу, как вы кладете и получаете из кеша, но у вас есть оператор put:

cache.put(CACHE_GEO_CLIENTS, новый HashMap());

Похоже, вы кладете второй кеш в основной кеш.

У меня очень похожий код, но я помещаю и получаю отдельные объекты в кеш, а не Карты, с помощью уникального идентификатора. И он отлично работает для меня в нескольких экземплярах GAE.

-Джон