Se connecter à une instance Redis depuis Cloud Run Functions

Vous pouvez vous connecter à une instance Redis depuis Cloud Run Functions à l'aide de la sortie VPC directe.

Configuration

Si vous avez déjà installé Google Cloud CLI et créé une instance Redis, vous pouvez ignorer ces étapes.

  1. Installez la gcloud CLI et initialisez-la :

    gcloud init
    
  2. Suivez le Guide de démarrage rapide pour créer une instance Redis. Retenez la zone, l'adresse IP et le port de l'instance Redis.

Préparer la sortie réseau VPC pour la configuration

Pour se connecter à votre instance Redis, votre fonction Cloud Run doit avoir accès au réseau VPC autorisé de votre instance Redis.

Pour trouver le nom de ce réseau, exécutez la commande suivante :

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

Notez le nom du réseau.

Exemple de fonction

Cet exemple de fonction établit une connexion à une instance Redis à partir de Cloud Run Functions.

Clonez le dépôt correspondant au langage de programmation souhaité et accédez au dossier contenant l'exemple de code :

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

L'exemple de code incrémente un compteur Redis chaque fois que la fonction est déclenchée :

Go

Cette fonction utilise le client 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

Cette fonction utilise le module 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

Cette fonction utilise le package 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}"

Déployer l'exemple sur les fonctions Cloud Run

Pour déployer la fonction, procédez comme suit :

  1. Copiez le fichier Dockerfile dans le répertoire source :

    cp cloud_run_deployment/Dockerfile .
    
  2. Créez une image de conteneur à l'aide de Cloud Build en exécutant la commande suivante :

    gcloud builds submit --tag gcr.io/PROJECT_ID/visit-count
    
  3. Déployez le conteneur sur Cloud Run en exécutant la commande suivante :

        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
    

    où :

    • PROJECT_ID est l'ID de votre projet Google Cloud .
    • REGION est la région dans laquelle se trouve votre instance Redis.
    • NETWORK est le nom du réseau VPC autorisé auquel votre instance Redis est associée.
    • SUBNET est le nom de votre sous-réseau. Le sous-réseau doit être /26 ou supérieur. La sortie VPC directe est compatible avec les plages IPv4 RFC 1918, RFC 6598 et de classe E.
    • REDIS_IP et REDIS_PORT sont l'adresse IP et le numéro de port de votre instance Redis.

Une fois le déploiement de la fonction terminé, récupérez son URL :

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

Vous pouvez voir le compteur augmenter chaque fois que vous déclenchez la fonction en envoyant une requête GET à son URL.