Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Redis

Kiến trúc phi máy chủ:AWS Lambda, Upstash Redis &Go dành cho các ứng dụng có khả năng mở rộng, tiết kiệm chi phí

Giới thiệu

Nền tảng điện toán serverless thật tuyệt vời nhưng nếu không có cơ sở dữ liệu serverless thì chúng quá hạn chế.

Trong khi xây dựng nền tảng cho khóa học sắp tới của mình, Các thành phần của CI/CD, tôi muốn có một cơ sở dữ liệu phi máy chủ vì tôi quyết định sử dụng AWS Lambda làm máy chủ cho một số thứ nhất định. Yêu cầu của tôi là:

  1. Định giá theo mức sử dụng . Tôi không muốn trả tiền theo giờ hoặc theo nút mà theo mức sử dụng (yêu cầu, dung lượng lưu trữ, v.v.). Sẽ rất rẻ khi bắt đầu sử dụng nó và khi mức sử dụng tăng lên thì chi phí sẽ tăng theo tỷ lệ.
  2. Độ trễ thấp . Không ai thích phản hồi chậm, vì vậy việc truy vấn cơ sở dữ liệu phải nhanh từ bên trong các khu vực AWS (ví dụ:eu-west-1 ).
  3. Trải nghiệm tuyệt vời dành cho nhà phát triển (DevX) . Ưu tiên có một giao diện đẹp cho cơ sở dữ liệu mà không cần phải tìm hiểu thêm một DSL thích hợp nào khác hoặc lãng phí hàng giờ để loay hoay với một trang web.

Upstash Redis đáp ứng tất cả các yêu cầu trên và nó làm rất tốt việc đó.

  • Thanh toán khi bạn di chuyển?
    • ✅ Giá cả thực sự phải chăng để bắt đầu và trên quy mô lớn!
  • Độ trễ thấp?
    • < Độ trễ 1ms khi truy vấn từ bên trong AWS Lambda!
  • DevX tuyệt vời?
    • ✅ Đó là Redis tiêu chuẩn. Đúng vậy.

Trong bài viết này, chúng ta sẽ tìm hiểu cách sử dụng Upstash Redis từ bên trong AWS Lambda, đảm bảo nó đủ nhanh cho nhu cầu của chúng ta, đồng thời giữ cho mã của chúng ta có thể duy trì được để có thể kiểm tra cục bộ hoặc triển khai sang một nền tảng khác nếu cần.

Chúng ta đang triển khai cái gì?

Để đơn giản, chúng tôi sẽ chỉ triển khai 3 điểm cuối API:

  1. GET|POST /login điểm cuối chấp nhận userId dưới dạng tham số truy vấn trong GET hoặc bên trong giá trị biểu mẫu được gửi bằng POST yêu cầu. Điểm cuối này sẽ tạo ID phiên, lưu trữ nó trong Redis và cũng đặt cookie cho các lần truy cập tiếp theo. GET chỉ làm cho việc kiểm tra dễ dàng hơn.🙃
  2. Số GET /lessons/completed điểm cuối yêu cầu người dùng đăng nhập (tức là có cookie với ID phiên) và trả về phản hồi JSON với tất cả các bài học mà người dùng đã hoàn thành và thời điểm hoàn thành.
  3. Số POST /lessons/{lessonSlug}/mark-complete điểm cuối yêu cầu người dùng đăng nhập (tức là có cookie với ID phiên) và đánh dấu bài học được biểu thị bằng lessonSlug như đã hoàn thành với thời điểm hiện tại.

Lưu ý:Trong mã bên dưới có một số thứ bị thiếu, do đó đây không phải là mã có thể sao chép và dán sẵn sàng sản xuất. Ví dụ:chúng ta nên kiểm tra xem lessonSlug đã cho tồn tại trước khi cập nhật nó. Điểm cuối đăng nhập cũng phải chấp nhận mật khẩu và thực hiện xác minh muối/băm thích hợp trước khi tạo ID phiên, v.v.

1. Thiết lập

  • Mã đầy đủ chi tiết bên dưới cũng tồn tại trong aws-playground của tôi kho lưu trữ nếu bạn muốn xem mọi thứ khớp với nhau như thế nào.

Như bạn sẽ thấy bên dưới, chúng tôi đang tạo hai điểm vào, tức là hai lệnh thực thi. Một cái sẽ dành cho máy chủ cục bộ bình thường và một cái sẽ dành cho AWS Lambda. Bằng cách này, chúng tôi sẽ có thể kiểm tra toàn bộ logic của mình một cách cục bộ và bằng các thử nghiệm đơn vị/tích hợp tiêu chuẩn nếu chúng tôi muốn.

Sự khác biệt duy nhất giữa chúng được thể hiện trong phần 1.2 và 1.3 bên dưới.

1.1 Không gian làm việc

Trước khi đi sâu vào mã, hãy thiết lập thư mục làm việc cho Go.

  1. Tải xuống Go.
  2. Tạo tài khoản và cơ sở dữ liệu Upstash Redis ở khu vực bạn chọn. Lý tưởng nhất là khu vực AWS mà bạn sẽ triển khai Lambda của mình. Tôi sẽ sử dụng eu-west-1 (Châu Âu, Ireland) trong bài viết này.

Kiến trúc phi máy chủ:AWS Lambda, Upstash Redis &Go dành cho các ứng dụng có khả năng mở rộng, tiết kiệm chi phí

Sau khi hoàn thành những điều trên, bây giờ chúng ta có thể tạo không gian làm việc của mình. Đối với phần còn lại của bài viết, giả sử mã của chúng tôi ở dưới ~/dev/aws-lambda-upstash-redis .

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

Sau đó, tạo gói Go:

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

1.2 Điểm vào máy chủ cục bộ

  • Dán đoạn mã sau vào ~/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 Điểm vào AWS Lambda

  • Dán đoạn mã sau vào ~/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 Logic cốt lõi

Logic cốt lõi chính của chúng tôi sẽ đi vào core gói được chia sẻ bởi cả hai điểm truy cập ở trên.

  • Dán đoạn mã sau vào ~/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 Xây dựng/Biên dịch

Tôi thường viết một makefile nhỏ để tránh phải gõ lệnh dài mỗi lần tôi muốn biên dịch, vì vậy hãy sao chép đoạn sau vào ~/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

Bây giờ đừng lo lắng quá nhiều về các chi tiết nhưng điều này cho phép chúng tôi làm:

  • make build-server :Xây dựng hệ nhị phân để chạy máy chủ cục bộ (có thể thực thi ./build/server ).
  • make build-lambda :Xây dựng tệp nhị phân để chạy máy chủ trên AWS Lambda (có thể thực thi ./build/handler./build/handler.zip ).
  • make hoặc make build làm cả hai.

CGO_ENABLED=0 tùy chọn đảm bảo các tệp nhị phân thực thi của chúng tôi được khép kín (tức là được biên dịch tĩnh). GOOS=linux GOARCH=amd64 cần có các tùy chọn để biên dịch chéo và khớp với môi trường linux của AWS Lambda trong trường hợp bạn đang sử dụng hệ thống Mac hoặc Windows cục bộ.

Tiếp theo, chạy go mod tidy để tìm nạp tất cả các phụ thuộc mã. Hãy nhớ chạy cái này mỗi khi bạn thêm hoặc xóa phần phụ thuộc của Go.

Cuối cùng, chạy make một lần, để xây dựng mọi thứ và đảm bảo không gian làm việc của bạn được thiết lập trước khi chúng ta đi sâu hơn vào mã.

2. Triển khai API

Đối với phần này, chúng tôi sẽ luôn làm việc bên trong ~/dev/aws-lambda-upstash-redis/core/lib.go tập tin.

Một số dòng sau đây xác định các điểm cuối API mà chúng ta đã thảo luận trước đó bằng cách sử dụng go-chi tuyệt vời thư viện.

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
}

Trong đoạn trích trên, r.Group(...) tạo một lớp chia sẻ nơi chúng ta có thể áp dụng phần mềm trung gian phổ biến cho bất kỳ tuyến đường nào được xác định bên trong nó. Trong trường hợp này, chúng tôi thêm phần mềm trung gian UsersWithSessionOnly của riêng mình , như chúng ta sẽ thấy sau, đảm bảo rằng yêu cầu chứa cookie có ID phiên hoạt động.

2.1 Phần mềm trung gian UsersWithSessionOnly

Trong phần mềm trung gian này, chúng tôi muốn triển khai những điều sau:

  1. Trích xuất cookie chứa ID phiên và không thực hiện được.
  2. Truy vấn Redis để tìm nạp chi tiết người dùng dựa trên ID phiên và không thành công nếu ID phiên được cung cấp không hoạt động.
  3. Lưu trữ ID người dùng trong context.Context của yêu cầu để cung cấp cho phần mềm trung gian hoặc trình xử lý xuôi dòng.

Đầu tiên, chúng ta cần một số mã soạn sẵn cho một số nội dung nhập và định nghĩa được sử dụng ở mọi nơi.

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
}

Và bây giờ là logic chính cho phần mềm trung gian xác thực.

// 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(...)

Đây là một thao tác đơn giản mà chúng tôi muốn lưu trữ trong Redis bài học được biểu thị bằng lessonSlug tham số đường dẫn được hoàn thành tại thời điểm hiện tại của yêu cầu.

Trong Redis, chúng tôi muốn giữ một bản đồ cho mỗi người dùng trong đó mỗi cặp khóa-giá trị trong bản đồ sẽ là bài học làm khóa và ngày hoàn thành là giá trị. Vì vậy, chúng tôi sử dụng HSET Lệnh Redis. Chúng tôi cũng có thể lưu trữ một khóa riêng cho mỗi bài học nhưng điều này giúp người dùng dễ dàng tìm nạp tất cả các bài học cùng một lúc sau đó.

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 danh sáchBài học đã hoàn thành(...)

Tương tự như phần trước, ở đây chúng tôi chỉ muốn trả về toàn bộ bản đồ hoàn thành bài học và trả lại cho người dùng dưới dạng phản hồi JSON. Chúng tôi sử dụng HGETALL lệnh cho việc này.

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 đăng nhập(...)

Cuối cùng là điểm cuối đăng nhập. Một lần nữa, vui lòng không sao chép đoạn mã sau vào sản xuất vì nó không thực hiện bất kỳ loại xác thực nào. Vì mục đích của bài viết này, chúng tôi chỉ quan tâm đến cách nó truy vấn Redis và cách nó đặt cookie cho ID phiên.

ID phiên được tạo bởi ksuid thư viện, có một số ưu điểm so với UUID thông thường và chúng tôi chỉ coi nó hoạt động trong 1 giờ. Chúng tôi sử dụng chức năng thời gian tồn tại của Redis SET lệnh tự động xóa khỏi cơ sở dữ liệu sau một giờ.

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. Bản trình diễn - Cục bộ

Phù, có rất nhiều mã.😅

Hãy làm một bản demo nhanh để đảm bảo mọi thứ hoạt động như mong đợi.

  • Đầu tiên, đặt UPSTASH_REDIS_URL biến môi trường thành URL của cơ sở dữ liệu bạn đã tạo ở phần 1 ở trên. Bạn có thể tìm thấy nó trong phần chi tiết của trang cơ sở dữ liệu của bạn (xem phần 1.1 ở trên).
export UPSTASH_REDIS_URL="<your-url-here>"
  • Sau đó, xây dựng và chạy máy chủ cục bộ:
make build-server && ./build/server

Kiểm tra trình duyệt

Bây giờ, hãy thực hiện một số thử nghiệm trong trình duyệt bằng cách truy cập http://localhost:5000/lessons/completed.

Kiến trúc phi máy chủ:AWS Lambda, Upstash Redis &Go dành cho các ứng dụng có khả năng mở rộng, tiết kiệm chi phí

Chúng tôi nhận được 403 - Forbidden , vậy hãy đăng nhập bằng cách truy cập http://localhost:5000/login?userId=lambros.

Kiến trúc phi máy chủ:AWS Lambda, Upstash Redis &Go dành cho các ứng dụng có khả năng mở rộng, tiết kiệm chi phí

Chúng tôi đã đăng nhập ngay bây giờ và chúng tôi tự động được chuyển hướng đến /lessons/completed , nhưng chúng trống rỗng. Vì vậy, hãy đánh dấu một bài học là đã hoàn thành. Trong console tab bên trong devtools của trình duyệt của bạn chạy như sau:

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'}

Truy cập http://localhost:5000/lessons/completed sẽ hiển thị bài học này như được đánh dấu ngay bây giờ:

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

Và thì đấy. Mọi thứ đều hoạt động tốt!

Nhìn vào chính cơ sở dữ liệu Redis bằng Trình duyệt dữ liệu trực tuyến mới ra mắt gần đây cũng chứng minh rằng dữ liệu dự kiến ​​có ở đó.

Kiến trúc phi máy chủ:AWS Lambda, Upstash Redis &Go dành cho các ứng dụng có khả năng mở rộng, tiết kiệm chi phí

4. AWS Lambda

Để thử nghiệm và triển khai lên AWS Lambda, chúng tôi sẽ sử dụng sam cli.

  • Trước tiên, hãy thiết lập SAM cli và đảm bảo người dùng/vai trò của bạn có quyền phù hợp.

  • sam cli cần mẫu Cloudformation để hoạt động, vì vậy hãy sao chép nội dung sau vào 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
  • Xây dựng gói xử lý cho AWS Lambda:
make build-lambda
  • Thêm phần sau vào makefile để dễ dàng triển khai sau khi chúng tôi thay đổi mã:
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
  • Triển khai đến khu vực được chỉ định (xem lệnh trước).
make sam-deploy
  • Bạn sẽ nhận được một số kết quả như bên dưới:
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
  • URL của AWS Lambda đã triển khai hiển thị trong kết quả được in ra, trong trường hợp này là https://6pmmwqmg5vec3bcsldabckaf5i0nlgje.lambda-url.eu-west-1.on.aws/ . Vì vậy, vui lòng lặp lại các bước demo mà chúng tôi đã thực hiện trong trình duyệt trước khi sử dụng localhost với miền thực tế ngay bây giờ.
    • Ngoài ra, bạn cũng có thể tìm thấy URL của hàm mới được tạo trong kết quả đầu ra của ngăn xếp CloudFormation UpstashRedisGoArticleStackDemo trong bảng điều khiển Cloudformation.
    • Lưu ý: Đảm bảo đặt UPSTASH_REDIS_URL biến môi trường trên cấu hình AWS Lambda của bạn, nếu không nó sẽ bị lỗi. Truy cập bảng điều khiển AWS Lambda, sau đó nhấp vào Lambda mới được triển khai của bạn, nhấp vào Cấu hình rồi trên menu bên trái, nhấp vào Biến môi trường . Nhập UPSTASH_REDIS_URL làm khóa và URL Upstash Redis của bạn làm giá trị. Nhấp vào Lưu , và bây giờ Lambda của bạn đã sẵn sàng.

4.1 Kiểm tra cục bộ SAM

Chúng tôi có thể kiểm tra Lambda cục bộ bằng cách cung cấp sample-event.json với đường dẫn/cookie/tham số truy vấn/vv phù hợp. Ví dụ về JSON như vậy có thể được tìm thấy trong aws-lambda-upstash-redis-article/sample-event.json .

  • Sau đó, khi bạn có tệp sự kiện JSON hợp lệ, hãy chạy lệnh sau để gọi logic máy chủ giống như khi nó chạy trên AWS Lambda:
sam local invoke -t aws-iac/sam-template.yml -e sample-event.json

4.2 Bảo mật của URL Upstash Redis

Trong bài viết này, để đơn giản, chúng tôi đã cung cấp URL Upstash Redis, chứa mật khẩu, thông qua các biến môi trường. Chúng tôi không muốn mã hóa cứng phần này vào mẫu SAM Cloudformation được phiên bản cùng với mã của chúng tôi, đó là lý do tại sao chúng tôi phải định cấu hình thủ công thông qua bảng điều khiển AWS Lambda.

Có một cách tốt hơn để thực hiện việc này một cách tự động mà không cần sửa đổi cấu hình Lambda mỗi lần và tránh để bất kỳ ai có quyền truy cập vào bảng điều khiển đều thấy được thông tin xác thực/URL Redis.

Chúng tôi có thể sử dụng Kho lưu trữ thông số của Trình quản lý hệ thống AWS và tài nguyên Cloudformation tương ứng AWS::SSM::Parameter để giữ URL (chúng ta có thể đặt URL một lần và giữ lại trong quá trình triển khai) đồng thời thay đổi mã Lambda để tìm nạp giá trị của tham số khi chạy. Chúng ta cũng có thể tự động đưa nó vào dưới dạng biến env bên trong sam-template.yml , mặc dù điều này vẫn có ở dạng văn bản thuần túy trong bảng điều khiển.

Việc thay đổi mã để tìm nạp từ Kho tham số SSM thật dễ dàng do chúng tôi phân tách các điểm vào, vì vậy, chúng tôi chỉ có thể tìm nạp tham số khi chạy bên trong AWS Lambda (~/dev/aws-lambda-upstash-redis/cmd/lambda/main.go ) và chuyển nó tới NewClient() chức năng tạo ứng dụng khách Redis.

5. Nó nhanh đến mức nào?

Ngoài lệnh khởi động nguội đầu tiên mất khoảng 100-120 ms , mọi lệnh gọi sau đó đều nhanh như chớp và luôn ở mức 4 ms .

Dưới đây là một ví dụ về lời gọi hấp dẫn dành cho /login?userId=lambros điểm cuối như đã triển khai ở trên:

Kiến trúc phi máy chủ:AWS Lambda, Upstash Redis &Go dành cho các ứng dụng có khả năng mở rộng, tiết kiệm chi phí

Như bạn có thể thấy tổng thời lượng yêu cầu của chúng tôi là 2.06 ms . Có, đó là hai mili giây , để tạo ID phiên, hãy ghi ID phiên đó vào Upstash Redis từ xa và trả về phản hồi chuyển hướng.

Xem xét kỹ hơn trong Đầu ra nhật ký phần này, chúng ta có thể thấy rằng yêu cầu đã kéo dài 789.435μs , ít nhất là từ quan điểm mã của chúng tôi. Điều này có nghĩa là logic của chúng tôi đã hoàn thành tốt theo 1 ms (khoảng 0.790 ms ). Thật ngạc nhiên khi chúng ta đang sử dụng cơ sở dữ liệu từ xa.🤯

Kết luận

Tôi thực sự ngạc nhiên trước hiệu suất hoạt động của Upstash Redis, đặc biệt là vì thật khó để tìm được hiệu suất như vậy đối với cơ sở dữ liệu không có máy chủ phù hợp với các nền tảng như AWS Lambda.

API Redis thực sự tiện lợi, Upstash Redis có mô hình định giá hàng đầu và trải nghiệm tuyệt vời dành cho nhà phát triển, đồng thời nó rất nhanh. Tôi thích sự kết hợp này!

AWS Lambda + Upstash Redis + Go =🚀❤️