Cloud Run 함수에서 Redis 인스턴스에 연결

서버리스 VPC 액세스를 사용하여 Cloud Run 함수에서 Redis 인스턴스에 연결할 수 있습니다.

설정

이미 Google Cloud CLI를 설치하고 Redis 인스턴스를 만들었다면 아래 단계를 건너뛸 수 있습니다.

  1. gcloud CLI를 설치하고 초기화합니다.

    gcloud init
    
  2. 빠른 시작 가이드에 따라 Redis 인스턴스를 만듭니다. Redis 인스턴스의 영역, IP 주소, 포트를 기록합니다.

서버리스 VPC 액세스 구성

Cloud Run 함수에서 Redis 인스턴스의 승인된 VPC 네트워크에 연결하려면 서버리스 VPC 액세스를 설정해야 합니다.

  1. 다음 명령어를 실행하여 Redis 인스턴스의 승인된 네트워크를 찾습니다.

    gcloud redis instances describe INSTANCE_ID --region REGION
  2. 커넥터 만들기의 안내에 따라 서버리스 VPC 액세스 커넥터를 만듭니다. 함수를 배포하려는 리전과 동일한 리전에 커넥터를 만들고 커넥터가 Redis 인스턴스의 승인된 VPC 네트워크에 연결되어 있는지 확인합니다. 커넥터의 이름을 기억하세요.

샘플 함수

이 샘플 함수는 Cloud Run 함수에서 Redis 인스턴스에 연결을 설정합니다.

원하는 프로그래밍 언어의 저장소를 클론하고 샘플 코드가 포함된 폴더로 이동합니다.

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

샘플 코드는 함수가 트리거될 때마다 Redis 카운터를 증가시킵니다.

Go

이 함수는 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

이 함수는 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

이 함수는 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}"

Cloud Run 함수에 샘플 배포

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

다음과 같이 바꿉니다.

  • REGION을 함수를 배포하려는 리전으로 바꿉니다.
  • BASE_IMAGE을 함수의 기본 이미지로 바꿉니다(예: go116, nodejs16, python310). 자세한 내용은 지원되는 언어 런타임 및 기본 이미지를 참고하세요.
  • PROJECT_ID를 Google Cloud 프로젝트 ID로 바꿉니다.
  • CONNECTOR_NAME을 커넥터 이름으로 바꿉니다.
  • REDIS_IPREDIS_PORT를 Redis 인스턴스의 IP 주소와 포트 번호로 바꿉니다.

함수 배포가 완료되면 함수 URL을 검색합니다.

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

URL에 GET 요청을 전송하여 함수를 트리거할 때마다 카운터 증가를 확인할 수 있습니다.