Conéctate a una instancia de Redis desde Cloud Run Functions

Puedes conectarte a una instancia de Redis desde Cloud Run Functions a través de la salida de VPC directa.

Configuración

Si ya instalaste Google Cloud CLI y creaste una instancia de Redis, puedes omitir estos pasos.

  1. Instala la CLI de gcloud y, luego, 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.

Prepara la salida de la red de VPC para la configuración

Para conectarte a tu instancia de Redis, tu función de Cloud Run debe tener acceso a la red de VPC autorizada de la instancia de Redis.

Para encontrar el nombre de esta red, ejecuta el siguiente comando:

  gcloud redis instances describe INSTANCE_ID --region REGION --format "value(authorizedNetwork)"

Toma nota del nombre de la red.

Función de muestra

Esta función de muestra establece una conexión con una instancia de Redis desde Cloud Run Functions.

Clona el repositorio de tu lenguaje de programación deseado y navega a la carpeta que contiene el código de muestra:

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

En esta función, se 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

En esta función, se 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

En esta función, se 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}"

Implementa la muestra en Cloud Run Functions

Sigue estos pasos para implementar la función:

  1. Copia el archivo Dockerfile en el directorio fuente:

    cp cloud_run_deployment/Dockerfile .
    
  2. Ejecuta el siguiente comando para compilar una imagen de contenedor con Cloud Build:

    gcloud builds submit --tag gcr.io/PROJECT_ID/visit-count
    
  3. Ejecuta el siguiente comando para implementar el contenedor en Cloud Run:

        gcloud run deploy \
        --image gcr.io/PROJECT_ID/visit-count \
        --allow-unauthenticated \
        --region REGION \
        --network NETWORK \
        --subnet SUBNET \
        --set-env-vars REDISHOST=REDIS_IP,REDISPORT=REDIS_PORT
    

    Donde:

    • PROJECT_ID es el ID de tu proyecto de Google Cloud .
    • REGION es la región en la que se encuentra tu instancia de Redis.
    • NETWORK es el nombre de la red de VPC autorizada a la que está conectada tu instancia de Redis.
    • SUBNET es el nombre de la subred. La subred debe ser /26 o mayor. La salida de VPC directa admite los rangos IPv4 RFC 1918, RFC 6598 y clase E.
    • REDIS_IP y REDIS_PORT son la dirección IP y el número de puerto de tu instancia de Redis.

Cuando finalice la implementación de la función, recupera su URL:

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

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