¡La versión 2.0 de Play ya está lista! Ayúdanos a traducir la documentación de la útlima versión y sigue nuestro progreso.

Manuales, tutoriales & referencias

Consulte

Contenidos

Elija la versión

Buscar

Busque con google

Libros

Use una cache

Para crear sistemas de alto rendimiento, a veces tienes que utilizar una cache de datos. Play trae incluida una biblioteca de cache y usará Memcached cuando esté en un entorno distribuido.

Si no configura Memcached, Play usará una cache independiente que almacena los datos en el heap de la JVM. Al almancenar la información de la cache en la JVM, play rompe el principio de “sin información compartida” (share nothing): es decir que no podrás correr tu aplicación en varios servidores, y esperar que la aplicación se comporte de forma consistente. Cada instancia de la aplicación tendrá una copia diferente de los datos.

Es importante entender que el contrato de uso de la cache es claro: cuando pones datos en una cache, no puedes esperar que los datos se queden en ella para siempre. De hecho, no deberías. Una cache es rápida, pero los valores expiran, y la caché suele existir sólamente en la memoria (sin copia persistente).

Es decir que al utilizar una cache cache, debes estar en condiciones de repopularla cuando no contenga la información que esperas:

public static void allProducts() {
    List<Product> products = Cache.get("products", List.class);
    if(products == null) {
        products = Product.findAll();
        Cache.set("products", products, "30mn");
    }
    render(products);
}

La API de la cache

La API de la cache está incluida en la clase play.cache.Cache. Esta clase contiene un conjunto de métodos que le permite colocar, sustituir y extraer datos de la cache. El comportamiento exacto de cada método puedes consultarlo en la documentación de Memcached.

Algunos ejemplos:

public static void showProduct(String id) {
    Product product = Cache.get("product_" + id, Product.class);
    if(product == null) {
        product = Product.findById(id);
        Cache.set("product_" + id, product, "30mn");
    }
    render(product);
}
 
public static void addProduct(String name, int price) {
    Product product = new Product(name, price);
    product.save();
    showProduct(product.id);
}
 
public static void editProduct(String id, String name, int price) {
    Product product = Product.findById(id);
    product.name = name;
    product.price = price;
    Cache.set("product_" + id, product, "30mn");
    showProduct(id);
}
 
public static void deleteProduct(String id) {
    Product product = Product.findById(id);
    product.delete();
    Cache.delete("product_" + id);
    allProducts();
}

Algunos métodos comienzan con el prefijo safe, por ejemplo, safeDelete, safeSet. Los métodos estándard son no-bloqueantes. Esto significa que cuando ejecutas la llamada:

Cache.delete("product_" + id);

El método delete volverá inmediatamente y no esperará hasta que el objeto en cache se borre realmente. Así que si hay un error, por ejemplo de entrada/salida, el objeto aún puede estar presente.

Cuando necesite asegurarse de que el objeto se haya borrado antes de continuar, puede usar el método safeDelete:

Cache.safeDelete("product_" + id);

Este método es bloqueante y devuelve un valor booleano que indica si el objeto se ha borrado o no. Así, el patrón completo que asegura que un item se ha borrado de la cache es:

if(!Cache.safeDelete("product_" + id)) {
    throw new Exception("Oops, the product has not been removed from the cache");
}
...

Hay que tener en cuenta que dado que se trata de llamadas bloqueantes, los métodos safe ralentizarán su aplicación. De modo que úselos sólo cuando sean necesarios.

También hay que notar que cuando se especifica expiration == "0s" (cero segundos), el tiempo de expiración real puede variar entre las diferentes implementaciones de cache.

¡No use la Sesión como cache!

Si viene de trabajar con un framework de desarrollo que usa una implementación en memoria del objeto Session, puede sentirse frustado al ver que Play sólo permite que se salven en la sesión HTTP un conjunto pequeño de cadenas de texto. Pero esto es mucho mejor, porque una sesión no es el lugar para usar como caché de los datos de tu aplicación.

Así que si está acostumbrado a hacer cosas como estas:

httpServletRequest.getSession().put("userProducts", products);
...
// y en los requests siguientes
products = (List<Product>)httpServletRequest.getSession().get("userProducts");

En Play puede hacerse lo mismo de forma algo diferente. Creemos que esta es una forma mejor:

Cache.set(session.getId(), products);
...
// y en los requests siguientes
List<Product> products = Cache.get(session.getId(), List.class)

Aquí hemos usado un UUID único para mantener información única en la cache para cada usuario. Recuerda que, a diferencia de un objeto sesión, la cache no está vinculada a ningún usuario en particular.

Configuración de memcached

Cuando quieras habilitar una implementación real de Memcached, habilita Memcached con memcached configuration y define la dirección del proceso en la configuración memcached.host.

Próximos pasos

Aprenderemos a Enviar emails.