Cloud Run 서비스에서 Redis 인스턴스에 연결

직접 VPC 이그레스 를 사용하여 Cloud Run에서 Redis 인스턴스에 연결할 수 있습니다.

설정

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

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

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

VPC 네트워크 이그레스 구성 준비

Redis 인스턴스에 연결하려면 Cloud Run 서비스에서 Redis 인스턴스의 승인된 VPC 네트워크에 액세스할 수 있어야 합니다.

이 네트워크의 이름을 찾으려면 다음 명령어를 실행하세요.

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

네트워크 이름을 기록해 둡니다.

샘플 애플리케이션

이 샘플 HTTP 서버 애플리케이션은 Cloud Run 서비스에서 Redis 인스턴스로 연결을 설정합니다.

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

Go

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

자바

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

Node.js

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

Python

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

이 샘플 애플리케이션은 / 엔드포인트에 액세스할 때마다 Redis 카운터를 증가시킵니다.

Go

이 애플리케이션은 github.com/gomodule/redigo/redis 클라이언트를 사용합니다. 다음 명령어를 실행하여 설치합니다.

go get github.com/gomodule/redigo/redis@latest

애플리케이션 예시:


// Package main is a basic app that connects to a managed Redis instance.
package main

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

	"github.com/gomodule/redigo/redis"
)

var redisPool *redis.Pool

func incrementHandler(w http.ResponseWriter, r *http.Request) {
	conn := redisPool.Get()
	defer conn.Close()

	counter, err := redis.Int(conn.Do("INCR", "visits"))
	if err != nil {
		http.Error(w, "Error incrementing visitor counter", http.StatusInternalServerError)
		return
	}
	fmt.Fprintf(w, "Visitor number: %d", counter)
}

func main() {
	redisHost := os.Getenv("REDISHOST")
	redisPort := os.Getenv("REDISPORT")
	redisAddr := fmt.Sprintf("%s:%s", redisHost, redisPort)

	const maxConnections = 10
	redisPool = &redis.Pool{
		MaxIdle: maxConnections,
		Dial:    func() (redis.Conn, error) { return redis.Dial("tcp", redisAddr) },
	}

	http.HandleFunc("/", incrementHandler)

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}
	log.Printf("Listening on port %s", port)
	if err := http.ListenAndServe(":"+port, nil); err != nil {
		log.Fatal(err)
	}
}

자바

이 애플리케이션은 Jetty 3.1 서블릿 기반입니다.

Jedis 라이브러리를 사용합니다.

<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>5.1.0</version>
</dependency>

AppServletContextListener 클래스는 장기 Redis 연결 풀을 만드는 데 사용됩니다.


package com.example.redis;

import java.io.IOException;
import java.util.Properties;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@WebListener
public class AppServletContextListener implements ServletContextListener {

  private Properties config = new Properties();

  private JedisPool createJedisPool() throws IOException {
    String host;
    Integer port;
    config.load(
        Thread.currentThread()
            .getContextClassLoader()
            .getResourceAsStream("application.properties"));
    host = config.getProperty("redis.host");
    port = Integer.valueOf(config.getProperty("redis.port", "6379"));

    JedisPoolConfig poolConfig = new JedisPoolConfig();
    // Default : 8, consider how many concurrent connections into Redis you will need under load
    poolConfig.setMaxTotal(128);

    return new JedisPool(poolConfig, host, port);
  }

  @Override
  public void contextDestroyed(ServletContextEvent event) {
    JedisPool jedisPool = (JedisPool) event.getServletContext().getAttribute("jedisPool");
    if (jedisPool != null) {
      jedisPool.destroy();
      event.getServletContext().setAttribute("jedisPool", null);
    }
  }

  // Run this before web application is started
  @Override
  public void contextInitialized(ServletContextEvent event) {
    JedisPool jedisPool = (JedisPool) event.getServletContext().getAttribute("jedisPool");
    if (jedisPool == null) {
      try {
        jedisPool = createJedisPool();
        event.getServletContext().setAttribute("jedisPool", jedisPool);
      } catch (IOException e) {
        // handle exception
      }
    }
  }
}

VisitCounterServlet 클래스는 Redis 카운터를 증가시키는 웹 서블릿입니다.


package com.example.redis;

import java.io.IOException;
import java.net.SocketException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

@WebServlet(name = "Track visits", value = "")
public class VisitCounterServlet extends HttpServlet {

  @Override
  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {