2011-03-02 19 views
15

Soy nuevo en Google App Engine y durante los últimos días he dedicado a crear una aplicación utilizando Memcache de GAE para almacenar datos. En base a mis hallazgos iniciales, parece que el Memcache de GAE NO es global.¿Memcache (Java) para Google App Engine es un caché global?

Déjame explicarte más. Soy consciente de que diferentes solicitudes a GAE pueden ser atendidas por diferentes instancias (de hecho, esto parece suceder con bastante frecuencia). Es por esta razón que estoy usando Memcache para almacenar algunos datos compartidos, a diferencia de un Mapa estático. Pensé (quizás incorrectamente) que este era el punto de usar un caché distribuido para que cualquier nodo pudiera acceder a los datos.

Otra posibilidad definitiva es que estoy haciendo algo mal. He probado tanto JCache como la API de Memcache de bajo nivel (estoy escribiendo Java, no Python). Esto es lo que estoy haciendo para recuperar la memoria caché:

MemcacheService cache = MemcacheServiceFactory.getMemcacheService(); 

Después del despliegue, esto es lo que examino (a través de mis registros de la aplicación):

  1. La solicitud inicial es servido por un nodo en particular, y los datos se almacenan en la memoria caché recuperada anteriormente.
  2. Las nuevas solicitudes recuperan este mismo caché y los datos están allí.
  3. Cuando se genera un nuevo nodo para atender una solicitud (de los registros sé cuando esto sucede porque GAE registra el hecho de que "Esta solicitud provocó que se inicie un nuevo proceso para su aplicación ..."), se recupera la caché y está VACÍO !!

Ahora también sé que no hay garantía de cuánto tiempo estarán los datos en Memcache, pero de mis hallazgos parece que los datos desaparecen en el momento en que una instancia de diff intenta acceder al caché. Esto parece ir en contra de todo el concepto de un caché global distribuido, ¿no?

Esperemos que alguien pueda aclarar exactamente cómo esto DEBERÍA comportarse. Si no se supone que Memcache debe ser global y cada instancia de servidor tiene su propia copia, ¿por qué utilizar Memcache? Podría simplemente usar un HashMap estático (que inicialmente lo hice hasta que me di cuenta de que no sería global debido a las diferentes instancias que atendían mis solicitudes).

¿Ayuda?

+0

¿Puede mostrarnos el código que está poniendo y recuperando los valores de Memcache? –

+0

Parece probable que la memoria caché expulsada y su aplicación generada en una nueva instancia sean simplemente una coincidencia; ambas ocurrirían después de un período de inactividad, por ejemplo. Definitivamente no hay un enlace directo entre Memcache y las instancias de la aplicación. –

+0

Encontré el problema y lo puse en funcionamiento. Inicialmente estaba usando la API de JCache y no pude hacer que funcionara, así que cambié a la API de Memcache de bajo nivel, pero olvidé eliminar el código JCache anterior. Entonces las dos implementaciones se pisaron una a la otra. No estoy seguro de por qué la implementación de JCache no funcionó, así que compartiré el código. –

Respuesta

15

Sí, Memcache se comparte en todas las instancias de su aplicación.

1

Encontré el problema y lo puse en funcionamiento. Inicialmente estaba usando la API de JCache y no pude hacer que funcionara, así que cambié a la API de Memcache de bajo nivel, pero olvidé eliminar el código JCache anterior. Entonces las dos implementaciones se pisaron una a la otra.

no estoy seguro de por qué la aplicación de JCache no funcionaba, así que voy a compartir el código:

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

    } 

Este bloque de código es dentro de un constructor privado para un producto único llamado CacheService. Este singleton sirve como una fachada de caché. Tenga en cuenta que dado que las solicitudes pueden ser atendidas por diferentes nodos, cada nodo tendrá esta instancia de Singleton. Entonces, cuando Singleton se construye por primera y única vez, verificará si mi caché está disponible. Si no, lo creará. Esto debería ocurrir técnicamente una sola vez, ya que Memcache es global, sí? La otra cosa algo extraña que estoy haciendo aquí es crear una única entrada de caché de tipo HashMap para almacenar mis valores reales. Estoy haciendo esto porque necesito enumerar todas las claves y eso es algo que no puedo hacer con Memcache de forma nativa.

¿Qué estoy haciendo mal aquí?

0

Jerry, hay dos cuestiones que veo con el código que envió anteriormente:

1) Está usando la versión javax.cache de la API. Según Google, esto ha sido obsoleto: http://groups.google.com/group/google-appengine-java/browse_thread/thread/5820852b63a7e673/9b47f475b81fb40e?pli=1

En su lugar, se pretende que usemos la biblioteca net.sf.jsr107 hasta que finalice el JSR.

No sé si el uso de la antigua API causará un problema específico, pero aún podría ser un problema.

2) No veo cómo se está poniendo y conseguir de la caché, pero la declaración puesto que tienes es un poco extraño:

cache.put (CACHE_GEO_CLIENTS, nuevo HashMap());

Parece que está poniendo un segundo caché dentro del caché principal.

Tengo un código muy similar, pero estoy colocando y obteniendo objetos individuales en la memoria caché, no Maps, con una identificación única. Y funciona bien para mí en varias instancias en GAE.

-John

+0

Esto 'CacheFactory cacheFactory = CacheManager.getInstance(). GetCacheFactory(); caché cacheFactory.createCache (Collections.emptyMap()); cache.put (clave, valor); ' ¡No funciona para mí ni siquiera con net.sf.watever! –