Armazenar em cache os dados de um app do Spring Boot com o Memorystore

O Memorystore para Redis é um serviço Redis totalmente gerenciado para o Google Cloud. Os aplicativos em execução no Google Cloud podem ter um desempenho extremo utilizando o serviço Redis altamente escalonável, disponível e seguro, sem a necessidade de gerenciar implantações complexas do Redis. Ele pode ser usado como back-end para armazenamento em cache de dados a fim de melhorar o desempenho dos apps do Spring Boot. O codelab explica como configurá-lo.

O que você aprenderá

  • Como usar o Memorystore como back-end de cache em um app de inicialização do Spring.

O que é necessário

  • um projeto do Google Cloud;
  • Um navegador, como o Google Chrome
  • Conhecer os editores de texto padrão do Linux (como Vim, Emacs e GNU Nano)

Como você usará o codelab?

Somente leitura Leitura e conclusão dos exercícios

Como você classificaria sua experiência com os serviços do Google Cloud?

Iniciante Intermediário Proficiente

Configuração de ambiente personalizada

Se você ainda não tem uma Conta do Google (Gmail ou Google Apps), crie uma. Faça login no Console do Google Cloud Platform (console.cloud.google.com) e crie um novo projeto:

Captura de tela de 10/02/2016 12:45:26.png

Lembre-se do código do projeto, um nome exclusivo em todos os projetos do Google Cloud. O nome acima já foi escolhido e não servirá para você. Faremos referência a ele mais adiante neste codelab como PROJECT_ID.

Em seguida, você precisará ativar o faturamento no Console do Cloud para usar os recursos do Google Cloud.

A execução por meio deste codelab terá um custo baixo, mas poderá ser mais se você decidir usar mais recursos ou se deixá-los em execução. Consulte a seção "limpeza" no final deste documento.

Novos usuários do Google Cloud Platform estão qualificados para um teste sem custo financeiro de US$300.

Ativa o Google Cloud Shell

No Console do GCP, clique no ícone do Cloud Shell na barra de ferramentas localizada no canto superior direito:

Em seguida, clique em "Start Cloud Shell":

O provisionamento e a conexão ao ambiente levarão apenas alguns instantes para serem concluídos:

Essa máquina virtual contém todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Praticamente todo o seu trabalho neste laboratório pode ser feito em um navegador ou no seu Google Chromebook.

Depois que você se conectar ao Cloud Shell, sua autenticação já terá sido feita, e o projeto estará definido com seu PROJECT_ID.

Execute o seguinte comando no Cloud Shell para confirmar se a conta está autenticada:

gcloud auth list

Resposta ao comando

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

Resposta ao comando

[core]
project = <PROJECT_ID>

Se o projeto não estiver configurado, faça a configuração usando este comando:

gcloud config set project <PROJECT_ID>

Resposta ao comando

Updated property [core/project].

Inicie o Cloud Shell.

Depois que o Cloud Shell for iniciado, será possível usar a linha de comando para criar uma nova instância do Memorystore.

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

Se a API Memorystore não estiver ativada, será perguntado se você quer ativá-la. Responda 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].

Quando a operação for concluída, a instância estará pronta para uso.

Para descobrir o endereço IP da instância do Redis da instância, execute o comando abaixo. Você precisará usá-lo novamente mais tarde ao configurar o app Spring Boot.

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

Ao acessar Storage > Memorystore no Console do Google Cloud, você verá a instância no estado "ready":

Crie uma instância do Compute Engine na mesma região.

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

Quando a operação for concluída, a instância estará pronta para uso.

Conecte-se à sua instância via SSH acessando Compute > Compute Engine > Instâncias de VM e clique em SSH na coluna Conectar:

No shell da instância de máquina virtual (VM), e não no Cloud Shell, instale o OpenJDK, Maven e telnet:

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

Aguarde a conclusão da instalação e siga para a próxima etapa.

Crie um novo projeto Spring Boot com dependências web, redis e 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

Edite o arquivo application.properties para configurar o app para usar o endereço IP da instância do Memorystore para host do Redis.

$ nano src/main/resources/application.properties

Adicione a linha a seguir com seu endereço IP do Memorystore para Redis (de algumas etapas atrás):

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

Adicione uma nova linha depois disso e crie uma classe Java do controlador REST:

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

Coloque o seguinte conteúdo no arquivo:

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

A anotação @RequestMapping expõe o método como um endpoint HTTP e mapeia parte do caminho para um parâmetro de método (conforme indicado pela anotação @PathVariable).

A anotação @Cacheable("hello") indica que a execução do método deve ser armazenada em cache e que o nome do cache é "hello." É usado em combinação com o valor do parâmetro como uma chave de cache. Você verá um exemplo mais adiante no codelab.

Além disso, é necessário ativar o armazenamento em cache na classe do app Spring Boot.

Editar DemoApplication.java:

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

Importe org.springframework.cache.annotation.EnableCaching e faça uma anotação na classe com essa anotação. O resultado ficará assim:

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

Agora está tudo pronto para você executar o app.

$ mvn spring-boot:run

Abra outra conexão SSH com a instância, como fez antes. Na nova janela SSH, acesse o endpoint /hello/ várias vezes, transmitindo "bob" como nome.

$ 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

A primeira vez que a solicitação levou cinco segundos, mas a próxima foi significativamente mais rápida, apesar de você ter Thread.sleep(5000)invocação no método. Isso ocorre porque o método real é executado apenas uma vez e o resultado é colocado no cache. Cada chamada subsequente retorna o resultado diretamente do cache.

Você pode ver exatamente o que o app armazena em cache. No mesmo terminal que você usou na etapa anterior, conecte-se ao host do Memorystore para Redis usando telnet:

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

Para ver a lista de chaves de cache, use o seguinte comando:

KEYS *
hello::bob

Como podemos ver, o nome do cache é usado como prefixo da chave, e o valor do parâmetro é usado como a segunda parte.

Para recuperar o valor, use o comando GET:

$ GET hello::bob
   Hello bob!

Use o comando QUIT para sair.

Para fazer a limpeza, exclua as instâncias do Compute Engine e Memorystore do Cloud Shell.

Exclua a instância do Compute:

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

Exclua a instância do Memorystore for Redis:

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

Você criou o Memorystore para Redis e uma instância do Compute Engine. Além disso, você configurou um aplicativo Spring Boot para usar o Memorystore com o cache de inicialização do Spring.

Saiba mais

Licença

Este conteúdo está sob a licença Atribuição 2.0 Genérica da Creative Commons.