Connettersi a un'istanza Redis dalle funzioni Cloud Run

Puoi connetterti a un'istanza Redis dalle funzioni Cloud Run utilizzando il traffico in uscita VPC diretto.

Configurazione

Se hai già installato Google Cloud CLI e creato un'istanza Redis, puoi saltare questi passaggi.

  1. Installa gcloud CLI e inizializza:

    gcloud init
    
  2. Segui la guida rapida per creare un'istanza Redis. Prendi nota della zona, dell'indirizzo IP e della porta dell'istanza Redis.

Prepara l'uscita della rete VPC per la configurazione

Per connettersi all'istanza Redis, la funzione Cloud Run deve avere accesso alla rete VPC autorizzata dell'istanza Redis.

Per trovare il nome di questa rete, esegui il seguente comando:

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

Prendi nota del nome della rete.

Funzione SAMPLE

Questa funzione di esempio stabilisce una connessione a un'istanza Redis da Cloud Run Functions.

Clona il repository per il linguaggio di programmazione che preferisci e vai alla cartella che contiene il codice campione:

Vai

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

Il codice campione incrementa un contatore Redis ogni volta che viene attivata la funzione:

Vai

Questa funzione utilizza il 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

Questa funzione utilizza il modulo 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

Questa funzione utilizza il pacchetto 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}"

Deployment dell'esempio in Cloud Run Functions

Per eseguire il deployment della funzione:

  1. Copia Dockerfile nella directory di origine:

    cp cloud_run_deployment/Dockerfile .
    
  2. Crea un'immagine container utilizzando Cloud Build eseguendo il seguente comando:

    gcloud builds submit --tag gcr.io/PROJECT_ID/visit-count
    
  3. Esegui il deployment del container in Cloud Run eseguendo questo comando:

        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
    

    dove:

    • PROJECT_ID è l'ID del tuo progetto Google Cloud .
    • REGION è la regione in cui si trova l'istanza Redis.
    • NETWORK è il nome della rete VPC autorizzata a cui è collegata l'istanza Redis.
    • SUBNET è il nome della subnet. La subnet deve essere /26 o superiore. L'uscita VPC diretta supporta gli intervalli RFC 1918, RFC 6598 e IPv4 di classe E.
    • REDIS_IP e REDIS_PORT sono l'indirizzo IP e il numero di porta dell'istanza Redis.

Al termine del deployment della funzione, recupera l'URL della funzione:

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

Puoi vedere il contatore aumentare ogni volta che attivi la funzione inviando una richiesta GET al suo URL.