Computer >> 컴퓨터 >  >> 프로그래밍 >> Redis

서버리스 아키텍처:확장 가능하고 비용 효과적인 앱을 위한 AWS Lambda, Upstash Redis 및 Go

소개

서버리스 컴퓨팅 플랫폼은 훌륭하지만 서버리스 데이터베이스가 없으면 너무 제한적입니다.

다가오는 과정인 The Elements of CI/CD를 위한 플랫폼을 구축하는 동안 특정 작업을 위한 서버로 AWS Lambda를 사용하기로 결정했기 때문에 서버리스 데이터베이스가 필요했습니다. 제가 갖고 있는 요구 사항은 다음과 같습니다:

  1. 종량제 가격 . 시간당이나 노드당 비용을 지불하는 것이 아니라 사용량(요청, 스토리지 등)에 따라 비용을 지불하고 싶습니다. 사용을 시작하는 것은 매우 저렴해야 하며 사용량이 증가함에 따라 비용도 그에 비례하여 증가합니다.
  2. 낮은 지연 시간 . 느린 응답을 좋아하는 사람은 아무도 없으므로 AWS 지역(예:eu-west-1) 내부에서 데이터베이스 쿼리가 빨라야 합니다. ).
  3. 훌륭한 개발자 경험(DevX) . 또 다른 틈새 DSL을 배우거나 웹 사이트를 만지작거리느라 시간을 낭비하지 않고도 데이터베이스에 대한 멋진 인터페이스를 갖는 것이 좋습니다.

Upstash Redis는 위의 요구 사항을 모두 충족하며 그 역할을 훌륭하게 수행합니다.

  • 사용한 만큼 지불하시겠습니까?
    • ✅ 시작 비용이 매우 저렴하고 규모도 큽니다!
  • 낮은 지연 시간?
    • < AWS Lambda 내부에서 쿼리하면 지연 시간이 1ms입니다!
  • 훌륭한 DevX?
    • ✅ 표준 Redis입니다. 그렇군요.

이 기사에서는 AWS Lambda 내부에서 Upstash Redis를 사용하여 요구 사항에 맞게 충분히 빠른지 확인하는 동시에 로컬에서 테스트하거나 필요한 경우 다른 플랫폼에 배포할 수 있도록 코드를 유지 관리할 수 있도록 유지하는 방법을 살펴보겠습니다.

우리는 무엇을 구현하고 있나요?

단순화를 위해 3개의 API 엔드포인트만 구현하겠습니다:

  1. GET|POST /login userId을 허용하는 엔드포인트 GET의 쿼리 매개변수로 또는 POST와 함께 제출된 양식 값 내부 요청. 이 엔드포인트는 세션 ID를 생성하여 Redis에 저장하고 후속 방문을 위한 쿠키도 설정합니다. GET 테스트하기가 더 쉬워졌습니다.🙃
  2. GET /lessons/completed 엔드포인트는 로그인한 사용자(예:세션 ID가 있는 쿠키 보유)를 요구하며 사용자가 완료한 모든 강의와 시간이 포함된 JSON 응답을 반환합니다.
  3. POST /lessons/{lessonSlug}/mark-complete 엔드포인트에는 로그인한 사용자가 필요하며(예:세션 ID가 있는 쿠키 보유) 강의를 lessonSlug로 표시합니다. 현재 시간으로 완료되었습니다.

참고:아래 코드에는 몇 가지 누락된 내용이 있으므로 바로 복사하여 붙여넣을 수 있는 코드가 아닙니다. 예를 들어, 주어진 lessonSlug 업데이트하기 전에 존재합니다. 또한 로그인 엔드포인트는 비밀번호를 허용하고 세션 ID 등을 생성하기 전에 적절한 솔트/해시 확인을 수행해야 합니다.

1. 설정

  • 아래에 설명된 전체 코드는 내 aws-playground에도 있습니다. 모든 것이 어떻게 조화를 이루는지 확인하려면 저장소를 참조하세요.

아래에서 볼 수 있듯이 우리는 두 개의 진입점, 즉 두 개의 실행 가능한 명령을 생성하고 있습니다. 하나는 일반 로컬 서버용이고 다른 하나는 AWS Lambda용입니다. 이렇게 하면 전체 논리를 로컬에서 테스트할 수 있으며 원하는 경우 표준 단위/통합 테스트를 사용할 수 있습니다.

이들 간의 유일한 차이점은 아래 섹션 1.2와 1.3에 나와 있습니다.

1.1 작업공간

코드를 살펴보기 전에 Go용 작업 디렉터리를 설정해 보겠습니다.

  1. Go를 다운로드하세요.
  2. 선택한 지역에 Upstash Redis 계정과 데이터베이스를 생성하세요. 이상적으로는 Lambda를 배포할 AWS 지역과 동일해야 합니다. eu-west-1를 사용하겠습니다. (유럽, 아일랜드).

서버리스 아키텍처:확장 가능하고 비용 효과적인 앱을 위한 AWS Lambda, Upstash Redis 및 Go

위의 작업을 완료한 후 이제 작업 공간을 만들 수 있습니다. 기사의 나머지 부분에서는 코드가 ~/dev/aws-lambda-upstash-redis 아래에 있다고 가정합니다. .

mkdir -p ~/dev/aws-lambda-upstash-redis
cd ~/dev/aws-lambda-upstash-redis

그런 다음 Go 패키지를 만듭니다.

go mod init com.upstash/example/aws-lambda-upstash-redis

1.2 로컬 서버 진입점

  • 다음 코드를 ~/dev/aws-lambda-upstash-redis/cmd/server/main.go에 붙여넣으세요. .
package main
 
import (
 "log"
 "net/http"
 "os"
 
 "com.upstash/example/aws-lambda-upstash-redis/core"
)
 
func main() {
 mux := core.NewMux()
 port := os.Getenv("PORT")
 if len(port) == 0 {
 port = "5000"
 }
 if err := http.ListenAndServe(":"+port, mux); err != nil {
 log.Fatal(err)
 }
}

1.3 AWS Lambda 진입점

  • ~/dev/aws-lambda-upstash-redis/cmd/lambda/main.go에 다음 코드를 붙여넣으세요. .
package main
 
import (
 "com.upstash/example/aws-lambda-upstash-redis/core"
 "github.com/aws/aws-lambda-go/lambda"
 "github.com/awslabs/aws-lambda-go-api-proxy/httpadapter"
)
 
func main() {
 mux := core.NewMux()
 lambda.Start(httpadapter.NewV2(mux).ProxyWithContext)
}

1.4 핵심 로직

우리의 주요 핵심 로직은 core에 들어갈 것입니다. 위의 두 진입점에서 공유할 패키지입니다.

  • 다음 코드를 ~/dev/aws-lambda-upstash-redis/core/lib.go에 붙여넣으세요. .
package core
 
import (
 "github.com/go-chi/chi/v5"
)
 
func NewMux() *chi.Mux {
 r := chi.NewRouter()
 return r
}

1.5 빌드/컴파일

저는 보통 makefile를 작게 씁니다. 컴파일할 때마다 긴 명령을 입력하지 않으려면 다음을 ~/dev/aws-lambda-upstash-redis/makefile에 복사하세요. :

default: build
 
clean:
 rm -rf build/
 
build: build-lambda build-server
 
build-lambda: clean
 GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o build/handler cmd/lambda/main.go
 cd build/ && zip handler.zip ./handler
 
build-server: clean
 CGO_ENABLED=0 go build -o build/server cmd/server/main.go

지금은 세부사항에 대해 너무 걱정하지 마세요. 하지만 이를 통해 다음을 수행할 수 있습니다.

  • make build-server :로컬에서 서버를 실행하기 위한 바이너리를 빌드합니다(실행 파일 ./build/server). ).
  • make build-lambda :AWS Lambda에서 서버를 실행하기 위한 바이너리를 빌드합니다(실행 가능 ./build/handler./build/handler.zip ).
  • make 또는 make build 둘 다 수행합니다.

CGO_ENABLED=0 옵션은 실행 가능한 바이너리가 자체 포함되어 있는지 확인합니다(즉, 정적으로 컴파일됨). GOOS=linux GOARCH=amd64 Mac 또는 Windows 시스템을 로컬에서 사용하는 경우 AWS Lambda의 Linux 환경을 크로스 컴파일하고 일치시키려면 옵션이 필요합니다.

다음으로 go mod tidy을 실행하세요. 모든 코드 종속성을 가져옵니다. Go 종속성을 추가하거나 제거할 때마다 이를 실행하는 것을 잊지 마세요.

마지막으로 make을 실행하세요. 코드를 더 자세히 살펴보기 전에 모든 것을 빌드하고 작업 공간이 설정되었는지 확인하기 위해 한 번만 수행하세요.

2. API 구현

이 섹션에서는 항상 ~/dev/aws-lambda-upstash-redis/core/lib.go 내부에서 작업합니다. 파일.

다음 몇 줄은 놀라운 go-chi을 사용하여 앞서 논의한 API 엔드포인트를 정의합니다. 도서관.

import (
 //...
 "github.com/go-chi/chi/v5"
 "github.com/go-chi/chi/v5/middleware"
)
 
func NewMux() *chi.Mux {
 r := chi.NewRouter()
 
 r.Use(middleware.RequestID)
 r.Use(middleware.Logger)
 r.Use(middleware.Recoverer)
 
 r.Get("/login", login)
 r.Post("/login", login)
 r.Group(func(r chi.Router) {
 r.Use(UsersWithSessionOnly)
 r.Get("/lessons/completed", listLessonsCompleted)
 r.Post("/lessons/{lessonSlug}/mark-complete", markLessonComplete)
 })
 
 return r
}

위 스니펫에서 r.Group(...) 내부에 정의된 모든 경로에 대해 공통 미들웨어를 적용할 수 있는 공유 레이어를 생성합니다. 이 경우에는 자체 미들웨어 UsersWithSessionOnly를 추가합니다. , 나중에 살펴보겠지만 요청에 활성 세션 ID가 있는 쿠키가 포함되어 있음을 보장합니다.

2.1 UsersWithSessionOnly 미들웨어

이 미들웨어에서는 다음을 구현하려고 합니다:

  1. 세션 ID가 포함된 쿠키를 추출하고 그렇지 않으면 실패합니다.
  2. Redis를 쿼리하여 세션 ID를 기반으로 사용자 세부정보를 가져오고, 제공된 세션 ID가 활성 상태가 아니면 실패합니다.
  3. 요청의 context.Context에 사용자 ID를 저장합니다. 다운스트림 미들웨어나 핸들러에서 사용할 수 있도록 하기 위함입니다.

먼저, 모든 곳에서 사용되는 일부 가져오기 및 정의에 대한 상용구 코드가 필요합니다.

import (
 //...
 "log"
 "os"
 "strings"
 
 "github.com/go-redis/redis/v8"
)
 
type contextKey struct {
 name string
}
const (
 COOKIE_AUTH_NAME = "xxx_session_id"
)
var (
 CTX_USER_ID = &contextKey{"LoggedInUserId"}
 redisDb = NewClient()
)
 
func NewClient() *redis.Client {
 redisUrl := strings.TrimSpace(os.Getenv("UPSTASH_REDIS_URL"))
 if redisUrl == "" {
 log.Fatalln("Required env UPSTASH_REDIS_URL not set!")
 }
 opt, _ := redis.ParseURL(redisUrl)
 redisDb := redis.NewClient(opt)
 
 return redisDb
}

이제 인증 미들웨어의 주요 논리입니다.

// UsersWithSessionOnly middleware restricts access to just logged-in users.
// If validation passes, then the context will contain the user id (CTX_USER_ID).
func UsersWithSessionOnly(next http.Handler) http.Handler {
 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 c, err := r.Cookie(COOKIE_AUTH_NAME)
 if err != nil {
 render.Status(r, http.StatusForbidden)
 render.JSON(w, r, struct{}{})
 return
 }
 
 ctx := r.Context()
 userId, err := redisDb.Get(ctx, "session:"+c.Value).Result()
 if err == redis.Nil {
 // If session is not found then user is forbidden from accessing the API!
 render.Status(r, http.StatusForbidden)
 render.JSON(w, r, struct{}{})
 return
 } else if err != nil {
 // Something went wrong querying Redis!
 render.Status(r, http.StatusInternalServerError)
 render.JSON(w, r, struct{ Message string }{Message: "We could not validate the provided session ID"})
 return
 }
 // Set it for downstream middleware and handlers.
 next.ServeHTTP(w, r.WithContext(context.WithValue(ctx, CTX_USER_ID, userId)))
 })
}

2.2 markLessonComplete(...)

이는 lessonSlug으로 표시된 레슨을 Redis에 저장하려는 간단한 작업입니다. 경로 매개변수는 요청 현재 시간에 완료됩니다.

Redis에서는 맵의 각 키-값 쌍이 강의가 키이고 완료 날짜가 값이 되는 각 사용자에 대한 맵을 유지하려고 합니다. 따라서 HSET을 사용합니다. 레디스 명령. 수업마다 별도의 키를 저장할 수도 있지만 이렇게 하면 나중에 사용자의 모든 수업을 한 번에 가져오기가 더 쉬워집니다.

func markLessonComplete(w http.ResponseWriter, r *http.Request) {
 ctx := r.Context()
 lessonSlug := chi.URLParam(r, "lessonSlug")
 userId := r.Context().Value(CTX_USER_ID).(string)
 timeNow := time.Now().Format(time.RFC3339)
 
 err := redisDb.HSet(ctx, "lessons:"+userId, lessonSlug, timeNow).Err()
 if err != nil {
 render.Status(r, http.StatusInternalServerError)
 render.JSON(w, r, struct{ Message string }{Message: "We could not save your progression..."})
 return
 }
 
 render.JSON(w, r, struct {
 LessonSlug string
 LastCompleted string
 }{
 lessonSlug,
 timeNow,
 })
}

2.3 목록수업완료(...)

이전 섹션과 비슷한 방식으로 여기서는 수업 완료의 전체 맵을 반환하고 이를 JSON 응답으로 사용자에게 반환하려고 합니다. 우리는 HGETALL을 사용합니다 이에 대한 명령입니다.

func listLessonsCompleted(w http.ResponseWriter, r *http.Request) {
 ctx := r.Context()
 userId := r.Context().Value(CTX_USER_ID).(string)
 
 lessons, err := redisDb.HGetAll(ctx, "lessons:"+userId).Result()
 if err == redis.Nil {
 lessons = map[string]string{}
 } else if err != nil {
 render.Status(r, http.StatusInternalServerError)
 render.JSON(w, r, struct{ Message string }{Message: "We could not load your lessons..."})
 return
 }
 
 render.JSON(w, r, struct {
 Lessons map[string]string
 }{
 lessons,
 })
}

2.4 로그인(...)

마지막으로 로그인 엔드포인트입니다. 다시 한 번 말씀드리지만, 다음 코드는 어떤 종류의 유효성 검사도 수행하지 않으므로 프로덕션 환경에 복사하지 마세요. 이 기사의 목적상 우리는 Redis를 쿼리하는 방법과 세션 ID에 대한 쿠키를 설정하는 방법에만 관심이 있습니다.

세션 ID는 ksuid에 의해 생성됩니다. 일반 UUID에 비해 몇 가지 장점이 있는 라이브러리이며 1시간 동안만 활성화된 것으로 간주합니다. Redis SET의 TTL 기능을 사용합니다. 한 시간 후에 데이터베이스에서 자동으로 제거하는 명령입니다.

import (
 // ...
 "github.com/segmentio/ksuid"
)
 
func login(w http.ResponseWriter, r *http.Request) {
 // Check credentials and update redis session and return Set-Cookie
 // WARNING: You should do an actual validation in production for credentials!
 // ...
 // For now we always assume correctness and automatically create a session token
 // by saving it to Redis, and also setting it as a cookie.
 userId := strings.TrimSpace(r.FormValue("userId"))
 if userId == "" {
 render.Status(r, http.StatusBadRequest)
 render.JSON(w, r, struct{ Message string }{Message: "Missing required userId"})
 return
 }
 
 sessionId := ksuid.New()
 redisDb.Set(r.Context(), "session:"+sessionId.String(), userId, time.Hour*1)
 http.SetCookie(w, &http.Cookie{
 Name: COOKIE_AUTH_NAME, Value: sessionId.String(),
 Path: "/", MaxAge: int((time.Hour * 1).Seconds()),
 // This should be true when deploying in production (https), but locally we need it false (http).
 Secure: false,
 })
 
 http.Redirect(w, r, "/lessons/completed", http.StatusTemporaryRedirect)
}

3. 데모 - 로컬

휴, 코드가 너무 많네요😅

모든 것이 예상대로 작동하는지 간단한 데모를 통해 확인해 보겠습니다.

  • 먼저 UPSTASH_REDIS_URL를 설정하세요. 위의 섹션 1에서 생성한 데이터베이스의 URL에 대한 환경 변수입니다. 세부정보에서 확인하실 수 있습니다 데이터베이스 페이지의 탭(위 섹션 1.1 참조)
export UPSTASH_REDIS_URL="<your-url-here>"
  • 그런 다음 로컬 서버를 구축하고 실행합니다.
make build-server && ./build/server

브라우저 테스트

이제 http://localhost:5000/lessons/completed를 방문하여 브라우저에서 몇 가지 테스트를 수행해 보겠습니다.

서버리스 아키텍처:확장 가능하고 비용 효과적인 앱을 위한 AWS Lambda, Upstash Redis 및 Go

403 - Forbidden을 얻습니다. , http://localhost:5000/login?userId=lambros를 방문하여 로그인해 보겠습니다.

서버리스 아키텍처:확장 가능하고 비용 효과적인 앱을 위한 AWS Lambda, Upstash Redis 및 Go

이제 로그인되었으며 자동으로 /lessons/completed로 리디렉션되었습니다. , 그러나 비어 있습니다. 이제 강의를 완료로 표시해 보겠습니다. console에서 브라우저의 devtools 탭에서 다음을 실행하세요:

await (
 await fetch("http://localhost:5000/lessons/123/mark-complete", {
 method: "POST",
 credentials: "same-origin",
 })
).json();
 
// Should output something like:
// {LessonSlug: '123', LastCompleted: '2022-10-12T02:01:14+03:00'}

http://localhost:5000/lessons/completed를 방문하면 이 강의가 지금 표시된 대로 표시됩니다:

{ "Lessons": { "123": "2022-10-12T02:01:14+03:00" } }

짜잔. 모든 것이 잘 작동합니다!

최근 출시된 온라인 데이터 브라우저를 사용해 Redis 데이터베이스 자체를 살펴봐도 예상했던 데이터가 있다는 것을 확인할 수 있습니다.

서버리스 아키텍처:확장 가능하고 비용 효과적인 앱을 위한 AWS Lambda, Upstash Redis 및 Go

4. AWS 람다

AWS Lambda를 테스트하고 배포하기 위해 sam을 사용하겠습니다. 클리.

  • 먼저 SAM CLI를 설정하고 사용자/역할에 올바른 권한이 있는지 확인하세요.

  • sam cli가 작동하려면 Cloudformation 템플릿이 필요하므로 다음을 aws-iac/sam-template.yml에 복사하세요. :

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: Defines all the AWS resources we need for our Upstash Redis API.
 
Resources:
 # https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html
 GoUpstashRedis:
 Type: AWS::Serverless::Function
 Properties:
 CodeUri: ../build/handler.zip
 Handler: handler
 Runtime: go1.x
 MemorySize: 512
 FunctionUrlConfig:
 AuthType: NONE
 Cors:
 AllowCredentials: false
 AllowMethods: ["*"]
 AllowOrigins: ["*"]
 
Outputs:
 GoUpstashRedisApi:
 Description: "Endpoint URL"
 Value: !GetAtt GoUpstashRedisUrl.FunctionUrl
 GoUpstashRedis:
 Description: "Lambda Function ARN"
 Value: !GetAtt GoUpstashRedis.Arn
 GoUpstashRedisIamRole:
 Description: "Implicit IAM Role created for GoUpstashRedis"
 Value: !GetAtt GoUpstashRedisRole.Arn
  • AWS Lambda용 핸들러 번들을 빌드합니다.
make build-lambda
  • makefile에 다음을 추가하세요. 코드를 변경한 후 쉽게 배포할 수 있도록 하기 위해:
sam-deploy: build-lambda
 sam deploy -t aws-iac/sam-template.yml --stack-name "UpstashRedisGoArticleStackDemo" --region eu-west-1 --resolve-s3 --no-confirm-changeset --no-fail-on-empty-changeset --capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM CAPABILITY_AUTO_EXPAND
  • 지정된 지역에 배포합니다(이전 명령 참조).
make sam-deploy
  • 다음과 같은 출력이 표시됩니다.
CloudFormation outputs from deployed stack
-----------------------------------------------------------------------------------------------------------------------------------------------------------
Outputs
-----------------------------------------------------------------------------------------------------------------------------------------------------------
Key GoUpstashRedis
Description Lambda Function ARN
Value arn:aws:lambda:eu-west-1:<redacted>:function:UpstashRedisGoArticleStackDem-GoUpstashRedis-baB8dQPkTfg0
 
Key GoUpstashRedisIamRole
Description Implicit IAM Role created for GoUpstashRedis
Value arn:aws:iam::<redacted>:role/UpstashRedisGoArticleStac-GoUpstashRedisRole-16UWC7HR6KII8
 
Key GoUpstashRedisApi
Description Endpoint URL
Value https://6pmmwqmg5vec3bcsldabckaf5i0nlgje.lambda-url.eu-west-1.on.aws/
-----------------------------------------------------------------------------------------------------------------------------------------------------------
 
Successfully created/updated stack - UpstashRedisGoArticleStackDemo in eu-west-1
  • 배포된 AWS Lambda의 URL은 인쇄된 출력에 표시됩니다(이 경우 https://6pmmwqmg5vec3bcsldabckaf5i0nlgje.lambda-url.eu-west-1.on.aws/). . 따라서 localhost을 사용하기 전에 브라우저에서 수행한 데모 단계를 자유롭게 반복하세요. 이제 실제 도메인을 사용하세요.
    • 또는 CloudFormation 스택 UpstashRedisGoArticleStackDemo의 출력에서 새로 생성된 함수의 URL을 찾을 수도 있습니다. Cloudformation 콘솔에서.
    • 참고: UPSTASH_REDIS_URL를 설정했는지 확인하세요. AWS Lambda 구성의 환경 변수도 마찬가지입니다. 그렇지 않으면 충돌이 발생합니다. AWS Lambda 콘솔을 방문한 후 새로 배포된 Lambda를 클릭하고 구성을 클릭하세요. 탭을 클릭한 다음 왼쪽 메뉴에서 환경 변수를 클릭합니다. . UPSTASH_REDIS_URL을 입력하세요. 키로, Upstash Redis URL을 값으로 사용하세요. 저장을 클릭하세요. , 이제 Lambda가 준비되었습니다.

4.1 SAM 로컬 테스트

sample-event.json를 제공하여 로컬에서 Lambda를 테스트할 수 있습니다. 올바른 경로/쿠키/쿼리 매개변수 등을 사용하세요. 이러한 JSON의 예는 aws-lambda-upstash-redis-article/sample-event.json에서 찾을 수 있습니다. .

  • 그런 다음 유효한 JSON 이벤트 파일이 있으면 다음을 실행하여 AWS Lambda에서 실행되는 것처럼 서버 로직을 호출합니다.
sam local invoke -t aws-iac/sam-template.yml -e sample-event.json

4.2 Upstash Redis URL의 보안

이 문서에서는 단순화를 위해 환경 변수를 통해 비밀번호가 포함된 Upstash Redis URL을 제공했습니다. 우리는 이것을 코드와 함께 버전이 관리되는 SAM Cloudformation 템플릿에 하드코딩하고 싶지 않기 때문에 AWS Lambda 콘솔을 통해 수동으로 구성해야 했습니다.

매번 Lambda 구성을 수정하지 않고 이 작업을 자동으로 수행하고 콘솔 액세스 권한이 있는 모든 사람에게 Redis 자격 증명/URL이 눈에 띄지 않도록 하는 더 좋은 방법이 있습니다.

AWS Systems Manager Parameter Store와 해당 Cloudformation 리소스 AWS::SSM::Parameter를 사용할 수 있습니다. URL을 보관하고(한 번 설정하고 배포 중에 보관할 수 있음) 런타임 시 매개변수 값을 가져오도록 Lambda 코드를 변경합니다. sam-template.yml 내부에 env 변수로 자동 주입할 수도 있습니다. , 하지만 콘솔에는 여전히 일반 텍스트로 표시됩니다.

진입점 분리로 인해 SSM 매개변수 저장소에서 가져오도록 코드를 변경하는 것이 쉽기 때문에 AWS Lambda(~/dev/aws-lambda-upstash-redis/cmd/lambda/main.go) 내부에서 실행될 때만 매개변수를 가져올 수 있었습니다. ) NewClient()로 전달합니다. Redis 클라이언트를 생성하는 함수입니다.

5. 얼마나 빠른가요?

대략 100-120 ms이 소요되는 첫 번째 콜드 스타트 호출을 제외하면 , 이후의 모든 호출은 매우 빠르며 항상 4 ms 아래에 있습니다. .

다음은 /login?userId=lambros에 대한 핫 호출의 예입니다. 위에 구현된 엔드포인트:

서버리스 아키텍처:확장 가능하고 비용 효과적인 앱을 위한 AWS Lambda, Upstash Redis 및 Go

보시다시피 요청의 총 기간은 2.06 ms입니다. . 예, 2밀리초입니다. , 세션 ID를 생성하려면 이를 Upstash Redis에 원격으로 쓰고 리디렉션 응답을 반환합니다.

로그 출력을 더 자세히 살펴보세요. 섹션에서 요청이 789.435μs 동안 지속되었음을 알 수 있습니다. , 적어도 우리 코드의 관점에서는 그렇습니다. 이는 우리 논리가 1 ms에서 잘 완료되었음을 의미합니다. (대략 0.790 ms ). 원격 데이터베이스를 사용하고 있다는 점을 고려하면 정말 놀랍습니다.🤯

결론

Upstash Redis의 성능에 정말 놀랐습니다. 특히 AWS Lambda와 같은 플랫폼에 적합한 서버리스 데이터베이스에 대해 이러한 성능을 찾기가 어렵기 때문입니다.

Redis API는 정말 편리합니다. Upstash Redis는 최고의 가격 모델과 뛰어난 개발자 경험을 갖추고 있으며 속도도 빠릅니다. 조합이 너무 좋아요!

AWS Lambda + Upstash Redis + Go =🚀❤️