Almacena datos en caché desde una app de Spring Boot con Memorystore

Memorystore para Redis es un servicio de Redis completamente administrado para Google Cloud. Las apps que se ejecutan en Google Cloud pueden lograr un rendimiento extremo aprovechando el servicio de Redis altamente escalable, disponible y seguro sin la carga de administrar implementaciones complejas de Redis. Se puede usar como backend para el almacenamiento en caché de datos a fin de mejorar el rendimiento de las apps de Spring Boot. En el codelab, se explica cómo configurarlo.

Qué aprenderás

  • Cómo usar Memorystore como backend de caché para una app de Spring Boot

Requisitos

  • Un proyecto de Google Cloud
  • Un navegador, como Google Chrome
  • Se recomienda estar familiarizado con editores de texto estándares de Linux, como Vim, Emacs y GNU Nano.

¿Cómo usarás el codelab?

Solo lectura Leer y completar los ejercicios

¿Cómo calificarías tu experiencia con los servicios de Google Cloud?

Principiante Intermedio Avanzado

Configuración del entorno a su propio ritmo

Si aún no tienes una Cuenta de Google (Gmail o Google Apps), debes crear una. Accede a Google Cloud Platform Console (console.cloud.google.com) y crea un proyecto nuevo:

Captura de pantalla de 2016-02-10 12:45:26.png

Recuerde el ID de proyecto, un nombre único en todos los proyectos de Google Cloud (el nombre anterior ya se encuentra en uso y no lo podrá usar). Se mencionará más adelante en este codelab como PROJECT_ID.

A continuación, debes habilitar la facturación en Cloud Console para usar los recursos de Google Cloud.

Ejecutar este codelab debería costar solo unos pocos dólares, pero su costo podría aumentar si decides usar más recursos o si los dejas en ejecución (consulta la sección “Limpiar” al final de este documento).

Los usuarios nuevos de Google Cloud Platform son aptos para obtener una prueba gratuita de USD 300.

Activar Google Cloud Shell

En GCP Console, haga clic en el ícono de Cloud Shell en la barra de herramientas superior derecha:

Haga clic en "Start Cloud Shell":

El aprovisionamiento y la conexión al entorno debería llevar solo unos minutos:

Esta máquina virtual está cargada con todas las herramientas para desarrolladores que necesitará. Ofrece un directorio principal persistente de 5 GB y se ejecuta en Google Cloud, lo que permite mejorar considerablemente el rendimiento de la red y la autenticación. Gran parte de su trabajo, si no todo, se puede hacer simplemente con un navegador o su Google Chromebook.

Una vez conectado a Cloud Shell, debería ver que ya está autenticado y que el proyecto ya está configurado con su PROJECT_ID.

En Cloud Shell, ejecute el siguiente comando para confirmar que está autenticado:

gcloud auth list

Resultado del comando

Credentialed accounts:
 - <myaccount>@<mydomain>.com (active)
gcloud config list project

Resultado del comando

[core]
project = <PROJECT_ID>

De lo contrario, puede configurarlo con este comando:

gcloud config set project <PROJECT_ID>

Resultado del comando

Updated property [core/project].

Inicie Cloud Shell.

Después de que se inicie Cloud Shell, podrá usar la línea de comandos para crear una nueva instancia de Memorystore.

$ gcloud redis instances create myinstance --size=1 --region=us-central1

Si la API de Memorystore no estaba habilitada, se te preguntará si deseas habilitarla. Responde y.

API [redis.googleapis.com] not enabled on project [204466653457].
Would you like to enable and retry (this will take a few minutes)?
(y/N)?  y
Enabling service redis.googleapis.com on project 204166153457...
Waiting for async operation operations/tmo-acf.c8909997-1b4e-1a62-b6f5-7da75cce1416 to complete...
Operation finished successfully. The following command can describe the Operation details:
 gcloud services operations describe operations/tmo-acf.c8909997-1b4e-1a62-b6f5-7da75cce1416
Create request issued for: [myinstance]
Waiting for operation [operation-1538645026454-57763b937ad39-2564ab37-3fea7701] to complete...done.
Created instance [myinstance].

Cuando se complete la operación, tu instancia estará lista para usar.

Obtenga el redis host ip-address de la instancia con el siguiente comando. La volverás a usar más adelante cuando configures tu app de Spring Boot.

$ gcloud redis instances describe myinstance --region=us-central1 \
  | grep host
host: 10.0.0.4

Si navega a Storage > Memorystore en Google Cloud Console, debería poder ver su instancia en el estado "Ready" (Listo):

Crea una instancia de Compute Engine en la misma región.

$ gcloud compute instances create instance-1 --zone us-central1-c

Cuando se complete la operación, tu instancia estará lista para usar.

Conéctese a su instancia mediante SSH. Para ello, navegue a Compute > Compute Engine > Instancias de VM y haga clic en SSH en la columna Conectar:

En la shell de la instancia de máquina virtual (VM), instala OpenJDK, Maven o Telnet:

$ sudo apt-get install openjdk-8-jdk-headless maven telnet

Espere a que se complete la instalación y, luego, continúe con el siguiente paso.

Crea un proyecto nuevo de Spring Boot con dependencias web, redis y cache:

$ curl https://start.spring.io/starter.tgz \
  -d dependencies=web,redis,cache -d language=java -d baseDir=cache-app \
  | tar -xzvf - && cd cache-app

Edita el archivo application.properties a fin de configurar la aplicación para usar la dirección IP de la instancia de Memorystore para el host de Redis.

$ nano src/main/resources/application.properties

Agrega la siguiente línea a tu dirección IP de Memorystore para Redis (hace un par de pasos):

spring.redis.host=<memorystore-host-ip-address> 

Agrega una línea nueva después de esa instancia y crea una clase de Java del controlador de REST:

$ nano src/main/java/com/example/demo/HelloWorldController.java

Ingresa el siguiente contenido en el archivo:

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloWorldController {
@Autowired
private StringRedisTemplate template;

@RequestMapping("/hello/{name}")
@Cacheable("hello")
public String hello(@PathVariable String name) throws InterruptedException {
  Thread.sleep(5000);
  return "Hello " + name;
 }
}

La anotación @RequestMapping expone el método como un extremo HTTP y asigna parte de la ruta de acceso a un parámetro del método (como lo indica la anotación @PathVariable).

La anotación @Cacheable("hello") indica que la ejecución del método se debe almacenar en caché y que el nombre de la caché es hello. Se utiliza en combinación con el valor del parámetro como una clave de caché. Verás un ejemplo más adelante en el codelab.

Además, debes habilitar el almacenamiento en caché en la clase de la app de Spring Boot.

Edita DemoApplication.java:

$ nano src/main/java/com/example/demo/DemoApplication.java

Importa org.springframework.cache.annotation.EnableCaching y anota la clase con esta anotación. El resultado debería verse como el siguiente:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class DemoApplication {

public static void main(String[] args) {
  SpringApplication.run(DemoApplication.class, args);
 }
}

Ya estás listo para ejecutar la app.

$ mvn spring-boot:run

Abre otra conexión SSH a tu instancia como lo hiciste antes. En la ventana SSH nueva, accede al extremo /hello/ varias veces y pasa bob como nombre.

$ time curl http://localhost:8080/hello/bob 
Hello bob!

real        0m5.408s
user        0m0.036s
sys        0m0.009s

$ time curl http://localhost:8080/hello/bob 
Hello bob!

real        0m0.092s
user        0m0.021s
sys        0m0.027s

Observa que la primera vez que la solicitud tardó cinco segundos, la siguiente fue significativamente más rápida a pesar de que tienes Thread.sleep(5000)invocación en el método. Eso se debe a que el método real se ejecutó solo una vez y el resultado se colocó en la caché. Cada llamada posterior muestra el resultado directamente desde la caché.

En realidad, puedes ver exactamente lo que almacena la app en caché. Desde la misma terminal que usaste en el paso anterior, conéctate al host de Memorystore para Redis mediante telnet:

$ telnet <memorystore-host-ip-address> 6379

Para ver la lista de claves de caché, usa el siguiente comando:

KEYS *
hello::bob

Como puede ver, el nombre de la caché se utiliza como prefijo de la clave y el valor del parámetro se utiliza como la segunda parte.

Para recuperar el valor, usa el comando GET:

$ GET hello::bob
   Hello bob!

Usa el comando QUIT para salir.

Para limpiar, borra instancias de Compute Engine y Memorystore de Cloud Shell.

Borra la instancia de procesamiento:

$ gcloud compute instances delete instance-1 --zone us-central1-c

Borra la instancia de Memorystore para Redis:

$ gcloud redis instances delete myinstance --region=us-central1

Creaste Memorystore para Redis y una instancia de Compute Engine. Además, configuraste una app de Spring Boot para usar Memorystore con el almacenamiento en caché de Spring Boot.

Más información

Licencia

Este trabajo cuenta con una licencia Atribución 2.0 Genérica de Creative Commons.