Almacena datos en caché de 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 y, así, 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
  • Conocimientos de editores de texto estándares de Linux, como Vim, Emacs y GNU Nano

¿Cómo usarás el codelab?

Solo leer Leer y completar los ejercicios

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

Principiante Intermedio Avanzado

Configuración del entorno de autoaprendizaje

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:

Screenshot from 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, deberás habilitar la facturación en la consola de Cloud 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.

Activa 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 que te conectes a Cloud Shell, deberías ver que ya te autenticaste y que el proyecto ya se configuró con tu PROJECT_ID.

En Cloud Shell, ejecuta el siguiente comando para confirmar que tienes la autenticación:

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, puedes configurarlo con el siguiente 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, puedes 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 está 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].

Una vez que se complete la operación, tu instancia estará lista para usar.

Ejecuta el siguiente comando para obtener la dirección IP del host de Redis de la instancia. 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 navegas a Almacenamiento > Memorystore en la consola de Google Cloud, deberías poder ver tu instancia en estado "lista":

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

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

Una vez que se complete la operación, tu instancia estará lista para usar.

Para conectarte a tu instancia a través de SSH, navega a Compute > Compute Engine > Instancias de VM y haz clic en SSH en la columna Conectar:

En el shell de la instancia de máquina virtual (VM) (no en Cloud Shell), instala OpenJDK, Maven y Telnet:

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

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

Crea un proyecto nuevo de Spring Boot con las 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 para configurar la app de modo que use la dirección IP del host de la instancia de Memorystore para Redis.

$ nano src/main/resources/application.properties

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

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

Agrega una línea nueva después de eso y crea una clase Java de controlador 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 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 debe almacenarse en caché y que el nombre de la caché es "hello". Se usa en combinación con el valor del parámetro como 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.

Editar 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 puedes ejecutar la app.

$ mvn spring-boot:run

Abre otra conexión SSH a tu instancia de la misma manera que lo hiciste antes. En la nueva ventana de SSH, 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

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

De hecho, puedes ver exactamente lo que la app almacenó en caché. Desde la misma terminal que usaste en el paso anterior, conéctate al host de Memorystore para Redis con telnet:

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

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

KEYS *
hello::bob

Como puedes ver, el nombre de la caché se usa como prefijo de la clave y el valor del parámetro se usa 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 las 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.