Conectarse a una instancia de Redis desde funciones de Cloud Run

Puedes conectarte a una instancia de Redis desde funciones de Cloud Run mediante Acceso a VPC sin servidor.

Configuración

Si ya has instalado la CLI de Google Cloud y has creado una instancia de Redis, puedes saltarte estos pasos.

  1. Instala gcloud CLI e inicialízala:

    gcloud init
    
  2. Sigue la guía de inicio rápido para crear una instancia de Redis. Anota la zona, la dirección IP y el puerto de la instancia de Redis.

Configurar Acceso a VPC sin servidor

Para conectarte desde tus funciones de Cloud Run a la red VPC autorizada de tu instancia de Redis, debes configurar Acceso a VPC sin servidor.

  1. Para encontrar la red autorizada de tu instancia de Redis, ejecuta el siguiente comando:

    gcloud redis instances describe INSTANCE_ID --region REGION
  2. Sigue las instrucciones de la sección Crear un conector para crear un conector de Acceso a VPC sin servidor. Asegúrate de crear el conector en la misma región en la que quieras implementar tu función y de que el conector esté conectado a la red VPC autorizada de la instancia de Redis. Recuerda el nombre del conector.

Función de ejemplo

Esta función de ejemplo establece una conexión con una instancia de Redis desde funciones de Cloud Run.

Clona el repositorio del lenguaje de programación que quieras y ve a la carpeta que contiene el código de ejemplo:

Go

git clone https://github.com/GoogleCloudPlatform/golang-samples
cd golang-samples/functions/memorystore/redis

Node.js

git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples
cd nodejs-docs-samples/functions/memorystore/redis

Python

git clone https://github.com/GoogleCloudPlatform/python-docs-samples
cd python-docs-samples/functions/memorystore/redis

El código de muestra incrementa un contador de Redis cada vez que se activa la función:

Go

Esta función usa el cliente github.com/gomodule/redigo/redis.


// Package visitcount provides a Cloud Function that connects
// to a managed Redis instance.
package visitcount

import (
	"errors"
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/GoogleCloudPlatform/functions-framework-go/functions"
	"github.com/gomodule/redigo/redis"
)

var redisPool *redis.Pool

func init() {
	// Register the HTTP handler with the Functions Framework
	functions.HTTP("VisitCount", visitCount)
}

// initializeRedis initializes and returns a connection pool
func initializeRedis() (*redis.Pool, error) {
	redisHost := os.Getenv("REDISHOST")
	if redisHost == "" {
		return nil, errors.New("REDISHOST must be set")
	}
	redisPort := os.Getenv("REDISPORT")
	if redisPort == "" {
		return nil, errors.New("REDISPORT must be set")
	}
	redisAddr := fmt.Sprintf("%s:%s", redisHost, redisPort)

	const maxConnections = 10
	return &redis.Pool{
		MaxIdle: maxConnections,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", redisAddr)
			if err != nil {
				return nil, fmt.Errorf("redis.Dial: %w", err)
			}
			return c, err
		},
	}, nil
}

// visitCount increments the visit count on the Redis instance
// and prints the current count in the HTTP response.
func visitCount(w http.ResponseWriter, r *http.Request) {
	// Initialize connection pool on first invocation
	if redisPool == nil {
		// Pre-declare err to avoid shadowing redisPool
		var err error
		redisPool, err = initializeRedis()
		if err != nil {
			log.Printf("initializeRedis: %v", err)
			http.Error(w, "Error initializing connection pool", http.StatusInternalServerError)
			return
		}
	}

	conn := redisPool.Get()
	defer conn.Close()

	counter, err := redis.Int(conn.Do("INCR", "visits"))
	if err != nil {
		log.Printf("redis.Int: %v", err)
		http.Error(w, "Error incrementing visit count", http.StatusInternalServerError)
		return
	}
	fmt.Fprintf(w, "Visit count: %d", counter)
}

Node.js

Esta función usa el módulo redis.


const functions = require('@google-cloud/functions-framework');
const redis = require('redis');

const REDISHOST = process.env.REDISHOST || 'localhost';
const REDISPORT = process.env.REDISPORT || 6379;

const redisClient = redis.createClient({
  socket: {
    host: REDISHOST,
    port: REDISPORT,
  },
});
redisClient.on('error', err => console.error('ERR:REDIS:', err));
redisClient.connect();

functions.http('visitCount', async (req, res) => {
  try {
    const response = await redisClient.incr('visits');
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end(`Visit count: ${response}`);
  } catch (err) {
    console.log(err);
    res.status(500).send(err.message);
  }
});

Python

Esta función usa el paquete redis-py.


import os

import functions_framework
import redis

redis_host = os.environ.get("REDISHOST", "localhost")
redis_port = int(os.environ.get("REDISPORT", 6379))
redis_client = redis.StrictRedis(host=redis_host, port=redis_port)


@functions_framework.http
def visit_count(request):
    value = redis_client.incr("visits", 1)
    return f"Visit count: {value}"

Desplegar el ejemplo en Cloud Run Functions

Despliega la función con Google Cloud CLI:

Go

gcloud run deploy visit-count \
    --region=REGION \
    --source=. \
    --base-image=BASE_IMAGE \
    --function=VisitCount \
    --vpc-connector=projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR_NAME \
    --set-env-vars=REDISHOST=REDIS_IP,REDISPORT=REDIS_PORT

Node.js

gcloud run deploy visit-count \
    --region=REGION \
    --source=. \
    --base-image=BASE_IMAGE \
    --entry-point=visitCount \
    --vpc-connector=projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR_NAME \
    --set-env-vars=REDISHOST=REDIS_IP,REDISPORT=REDIS_PORT

Python

gcloud run deploy visit-count \
    --region=REGION \
    --source=. \
    --base-image=BASE_IMAGE \
    --function=visit_count \
    --vpc-connector=projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR_NAME \
    --set-env-vars=REDISHOST=REDIS_IP,REDISPORT=REDIS_PORT

Sustituye:

  • REGION con la región en la que quieras implementar la función.
  • BASE_IMAGE con la imagen base de la función (por ejemplo, go116, nodejs16 o python310). Para obtener más información, consulta Runtimes e imágenes base de los idiomas admitidos.
  • PROJECT_ID por el ID de tu proyecto. Google Cloud
  • CONNECTOR_NAME con el nombre del conector.
  • REDIS_IP y REDIS_PORT con la dirección IP y el número de puerto de tu instancia de Redis.

Una vez que se haya completado la implementación de la función, obtén su URL:

gcloud run services describe visit-count \
--region=REGION \

Verás cómo aumenta el contador cada vez que activas la función enviando una solicitud GET a su URL.