บทนำ
แพลตฟอร์มการประมวลผลแบบไร้เซิร์ฟเวอร์นั้นยอดเยี่ยม แต่ถ้าไม่มีฐานข้อมูลแบบไร้เซิร์ฟเวอร์ แพลตฟอร์มเหล่านั้นก็มีข้อจำกัดมากเกินไป
ในขณะที่ฉันกำลังสร้างแพลตฟอร์มสำหรับหลักสูตรที่กำลังจะมาถึง The Elements of CI/CD ฉันต้องการฐานข้อมูลแบบไร้เซิร์ฟเวอร์เนื่องจากฉันตัดสินใจใช้ AWS Lambda เป็นเซิร์ฟเวอร์ของฉันสำหรับบางสิ่ง ข้อกำหนดที่ฉันมีคือ:
- จ่ายตามราคา . ฉันไม่ต้องการจ่ายต่อชั่วโมงหรือต่อโหนด แต่จ่ายตามการใช้งาน (คำขอ พื้นที่เก็บข้อมูล ฯลฯ) การเริ่มใช้งานควรมีราคาถูกมาก และเมื่อการใช้งานเพิ่มขึ้น ต้นทุนก็จะเพิ่มขึ้นตามสัดส่วน
- เวลาแฝงต่ำ . ไม่มีใครชอบการตอบสนองที่ช้า ดังนั้นการสืบค้นฐานข้อมูลควรรวดเร็วจากภายในภูมิภาค AWS (เช่น
01). - ประสบการณ์นักพัฒนาที่ยอดเยี่ยม (DevX) . การมีอินเทอร์เฟซที่ดีสำหรับฐานข้อมูลโดยไม่ต้องเรียนรู้ DSL เฉพาะกลุ่มอื่น หรือเสียเวลาหลายชั่วโมงกับการเล่นเว็บไซต์เป็นที่ต้องการ
Upstash Redis เป็นไปตามข้อกำหนดข้างต้นทั้งหมด และทำงานได้ดีมาก
- จ่ายตามการใช้งาน?
- ✅ ราคาไม่แพงจริงๆ สำหรับการเริ่มต้นและในวงกว้าง!
- เวลาแฝงต่ำ?
- ✅
14รหัส> เวลาแฝง 1 มิลลิวินาทีจากการสืบค้นจากภายใน AWS Lambda!
- ✅
- DevX เยี่ยมมาก?
- ✅เป็น Redis มาตรฐาน ใช่แล้ว
ในบทความนี้ เราจะดูวิธีใช้ Upstash Redis จากภายใน AWS Lambda เพื่อให้แน่ใจว่ารวดเร็วเพียงพอสำหรับความต้องการของเรา ขณะเดียวกันก็รักษาโค้ดของเราให้ดูแลรักษาได้เพื่อให้สามารถทดสอบภายในเครื่องหรือปรับใช้กับแพลตฟอร์มอื่น หากจำเป็น
เรากำลังดำเนินการอะไร
เพื่อความง่าย เราจะใช้ตำแหน่งข้อมูล API เพียง 3 รายการ:
- รหัส <24 จุดสิ้นสุดที่ยอมรับ
38เป็นพารามิเตอร์การค้นหาใน42หรือภายในค่าแบบฟอร์มที่ส่งด้วย57คำขอ ตำแหน่งข้อมูลนี้จะสร้าง ID เซสชัน เก็บไว้ใน Redis และตั้งค่าคุกกี้สำหรับการเข้าชมครั้งต่อไปด้วย68รหัส> แค่ช่วยให้ทดสอบได้ง่ายขึ้น🙃 - รหัส <77 ตำแหน่งข้อมูลกำหนดให้ผู้ใช้ที่เข้าสู่ระบบ (เช่น มีคุกกี้ที่มีรหัสเซสชัน) และส่งคืนการตอบสนอง JSON พร้อมบทเรียนทั้งหมดที่ผู้ใช้เสร็จสิ้นและเวลาใด
- รหัส <89 ตำแหน่งข้อมูลกำหนดให้ผู้ใช้ที่เข้าสู่ระบบ (เช่น มีคุกกี้ที่มีรหัสเซสชัน) และทำเครื่องหมายบทเรียนที่แสดงโดย
90เสร็จสมบูรณ์ตามเวลาปัจจุบัน
หมายเหตุ:ในโค้ดด้านล่างมีบางสิ่งที่ขาดหายไป ดังนั้นโค้ดนี้จึงไม่ใช่โค้ดที่พร้อมสำหรับการคัดลอกและวางได้ ตัวอย่างเช่น เราควรตรวจสอบว่า 103 ที่ให้มานั้น มีอยู่แล้วก่อนที่จะอัปเดต ตำแหน่งข้อมูลการเข้าสู่ระบบควรยอมรับรหัสผ่านและทำการตรวจสอบแบบ Salted/Hash อย่างเหมาะสมก่อนสร้างรหัสเซสชัน ฯลฯ ป>
1. ตั้งค่า
- โค้ดทั้งหมดที่มีรายละเอียดด้านล่างนี้มีอยู่ใน
117ของฉันด้วย พื้นที่เก็บข้อมูลหากคุณต้องการดูว่าทุกอย่างเข้ากันอย่างไร
ดังที่คุณจะเห็นด้านล่าง เรากำลังสร้างจุดเข้าใช้งานสองจุด นั่นคือ คำสั่งปฏิบัติการสองคำสั่ง อันหนึ่งสำหรับเซิร์ฟเวอร์ภายในเครื่องปกติ และอีกอันสำหรับ AWS Lambda ด้วยวิธีนี้ เราจะสามารถทดสอบตรรกะทั้งหมดของเราภายในเครื่อง และด้วยการทดสอบหน่วย/การรวมมาตรฐานหากเราต้องการ
ความแตกต่างเพียงอย่างเดียวแสดงอยู่ในส่วนที่ 1.2 และ 1.3 ด้านล่าง
1.1 พื้นที่ทำงาน
ก่อนที่เราจะเจาะลึกโค้ด เรามาตั้งค่าไดเร็กทอรีการทำงานสำหรับ Go กันก่อน
- ดาวน์โหลดไป
- สร้างบัญชีและฐานข้อมูล Upstash Redis ในภูมิภาคที่คุณเลือก ตามหลักการแล้ว ควรเป็นภูมิภาค AWS เดียวกันกับที่คุณจะปรับใช้ Lambda ฉันจะใช้
127(ยุโรป ไอร์แลนด์) ในบทความนี้

หลังจากเสร็จสิ้นขั้นตอนข้างต้นแล้ว เราก็สามารถสร้างพื้นที่ทำงานของเราได้แล้ว สำหรับบทความที่เหลือ สมมติว่าโค้ดของเราอยู่ภายใต้ 139 .
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 จุดเข้าเซิร์ฟเวอร์ท้องถิ่น
- วางโค้ดต่อไปนี้ใน
141.
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
- วางโค้ดต่อไปนี้ใน
150.
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 ตรรกะหลัก
ตรรกะหลักหลักของเราจะอยู่ใน 166 แพ็คเกจที่จะแชร์โดยจุดเข้าทั้งสองด้านบน
- วางโค้ดต่อไปนี้ใน
179.
package core
import (
"github.com/go-chi/chi/v5"
)
func NewMux() *chi.Mux {
r := chi.NewRouter()
return r
} 1.5 การสร้าง / การรวบรวม
ฉันมักจะเขียน 182 ตัวเล็ก เพื่อหลีกเลี่ยงการพิมพ์คำสั่งยาวๆ ทุกครั้งที่ต้องการคอมไพล์ ดังนั้นให้คัดลอกคำสั่งต่อไปนี้ลงใน 196 :
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 ไม่ต้องกังวลมากเกินไปในตอนนี้เกี่ยวกับรายละเอียด แต่สิ่งนี้ช่วยให้เราดำเนินการได้:
200รหัส> :สร้างไบนารีสำหรับการรันเซิร์ฟเวอร์ในเครื่อง (ปฏิบัติการได้219).227รหัส> :สร้างไบนารีสำหรับการรันเซิร์ฟเวอร์บน AWS Lambda (ปฏิบัติการได้233และ245รหัส> ).255รหัส> หรือ264รหัส> ทำทั้งสองอย่าง
275รหัส> ตัวเลือกทำให้แน่ใจว่าไบนารีที่ปฏิบัติการได้ของเรานั้นมีอยู่ในตัวเอง (เช่น คอมไพล์แบบคงที่) 282รหัส> จำเป็นต้องใช้ตัวเลือกในการคอมไพล์ข้ามและจับคู่สภาพแวดล้อม linux ของ AWS Lambda ในกรณีที่คุณใช้ระบบ Mac หรือ Windows ในเครื่อง
จากนั้นรัน 291 เพื่อดึงข้อมูลการอ้างอิงโค้ดทั้งหมด อย่าลืมเรียกใช้สิ่งนี้ทุกครั้งที่คุณเพิ่มหรือลบการขึ้นต่อกันของ Go
สุดท้ายให้รัน 303 หนึ่งครั้ง เพื่อสร้างทุกอย่างและตรวจสอบให้แน่ใจว่าพื้นที่ทำงานของคุณได้รับการตั้งค่าแล้ว ก่อนที่เราจะเจาะลึกโค้ด
2. การใช้งาน API
สำหรับส่วนนี้ เราจะทำงานภายใน 318 เสมอ ไฟล์ ป>
สองสามบรรทัดต่อไปนี้จะกำหนดตำแหน่งข้อมูล API ที่เรากล่าวถึงก่อนหน้านี้ โดยใช้ 321 ที่น่าทึ่ง ห้องสมุด
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
}
ในตัวอย่างด้านบน 331 สร้างเลเยอร์ที่ใช้ร่วมกันซึ่งเราสามารถใช้มิดเดิลแวร์ทั่วไปสำหรับเส้นทางใด ๆ ที่กำหนดไว้ภายในนั้น ในกรณีนี้ เราจะเพิ่มมิดเดิลแวร์ของเราเอง 344 ซึ่งดังที่เราจะเห็นในภายหลังรับประกันว่าคำขอมีคุกกี้ที่มีรหัสเซสชันที่ใช้งานอยู่
2.1 UsersWithSessionOnly มิดเดิลแวร์
ในมิดเดิลแวร์นี้ เราต้องการใช้สิ่งต่อไปนี้:
- แยกคุกกี้ที่มีรหัสเซสชันและล้มเหลวมิฉะนั้น
- ค้นหา Redis เพื่อดึงรายละเอียดผู้ใช้ตามรหัสเซสชัน และล้มเหลวหากรหัสเซสชันที่ระบุไม่ทำงาน
- จัดเก็บ ID ผู้ใช้ในคำขอ
354เพื่อให้พร้อมใช้งานสำหรับมิดเดิลแวร์หรือตัวจัดการดาวน์สตรีม
ขั้นแรก เราต้องการโค้ดสำเร็จรูปสำหรับการนำเข้าและคำจำกัดความบางอย่างที่ใช้ทุกที่
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(...)
นี่เป็นการดำเนินการตรงไปตรงมาซึ่งเราต้องการเก็บไว้ใน Redis ซึ่งบทเรียนแสดงด้วย 365 พารามิเตอร์เส้นทางเสร็จสมบูรณ์ในเวลาปัจจุบันของคำขอ
ใน Redis เราต้องการเก็บแผนที่สำหรับผู้ใช้แต่ละราย โดยแต่ละคู่คีย์-ค่าในแผนที่จะเป็นบทเรียนเป็นคีย์ และวันที่เสร็จสมบูรณ์เป็นมูลค่า ดังนั้นเราจึงใช้ 373 คำสั่งเรดดิส นอกจากนี้เรายังสามารถจัดเก็บคีย์แยกต่างหากต่อบทเรียนได้ แต่จะทำให้ง่ายต่อการดึงบทเรียนทั้งหมดสำหรับผู้ใช้ในคราวเดียวในภายหลัง
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 เราใช้ 388 คำสั่งสำหรับสิ่งนี้
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 เซสชัน
รหัสเซสชันถูกสร้างขึ้นโดย 391 ไลบรารี่ซึ่งมีข้อได้เปรียบเหนือ UUID ทั่วไปเล็กน้อย และเราถือว่ามันใช้งานได้เพียง 1 ชั่วโมงเท่านั้น เราใช้ฟังก์ชันการทำงานตามเวลาจริงของ Redis 400 คำสั่งสำหรับการลบออกจากฐานข้อมูลโดยอัตโนมัติหลังจากหนึ่งชั่วโมง
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. สาธิต - ภายในเครื่อง
วุ้ย นั่นเป็นโค้ดเยอะมาก😅
มาสาธิตสั้นๆ เพื่อให้แน่ใจว่าทุกอย่างทำงานได้ตามที่คาดหวัง
- ขั้นแรก ให้ตั้งค่า
417ตัวแปรสภาพแวดล้อมเป็น URL ของฐานข้อมูลที่คุณสร้างในส่วนที่ 1 ด้านบน คุณสามารถดูได้ในรายละเอียด ของหน้าฐานข้อมูลของคุณ (ดูหัวข้อ 1.1 ด้านบน)
export UPSTASH_REDIS_URL="<your-url-here>" - จากนั้น สร้างและเรียกใช้เซิร์ฟเวอร์ภายในเครื่อง:
make build-server && ./build/server การทดสอบเบราว์เซอร์
ตอนนี้เรามาทำการทดสอบในเบราว์เซอร์โดยไปที่ http://localhost:5000/lessons/completed

เราได้รับ 423 ดังนั้นมาเข้าสู่ระบบกันดีกว่า โดยไปที่ http://localhost:5000/login?userId=lambros

เราเข้าสู่ระบบแล้ว และเราจะถูกเปลี่ยนเส้นทางไปที่ 434 โดยอัตโนมัติ แต่พวกมันว่างเปล่า ดังนั้น เรามาทำเครื่องหมายบทเรียนว่าเสร็จสมบูรณ์แล้ว ใน 448 แท็บภายใน 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 โดยใช้ Data Browser ออนไลน์ที่เพิ่งเปิดตัวเมื่อเร็วๆ นี้ ยังพิสูจน์ได้ว่ามีข้อมูลที่คาดหวังอยู่ที่นั่น

4. AWS แลมบ์ดา
เพื่อทดสอบและปรับใช้กับ AWS Lambda เราจะใช้ 453 คลิก
-
ขั้นแรก ให้ตั้งค่า SAM cli และตรวจสอบให้แน่ใจว่าผู้ใช้/บทบาทของคุณมีสิทธิ์ที่ถูกต้อง
-
464รหัส> cli ต้องใช้เทมเพลต Cloudformation จึงจะทำงานได้ ดังนั้นให้คัดลอกสิ่งต่อไปนี้ลงใน477:
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 - เพิ่มสิ่งต่อไปนี้ใน
489เพื่อให้ง่ายต่อการปรับใช้หลังจากที่เราทำการเปลี่ยนแปลงโค้ด:
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 - URL ของ AWS Lambda ที่ปรับใช้จะแสดงในเอาต์พุตที่พิมพ์ ในกรณีนี้คือ
493. ดังนั้น โปรดทำซ้ำขั้นตอนการสาธิตที่เราทำในเบราว์เซอร์ของเราก่อนที่จะใช้505ด้วยโดเมนจริงตอนนี้- หรืออีกวิธีหนึ่ง คุณยังสามารถค้นหา URL ของฟังก์ชันที่สร้างขึ้นใหม่ในเอาต์พุตของสแต็ก CloudFormation
513ในคอนโซล Cloudformation - หมายเหตุ: ตรวจสอบให้แน่ใจว่าได้ตั้งค่า
520ตัวแปรสภาพแวดล้อมในการกำหนดค่า AWS Lambda ของคุณเช่นกัน ไม่เช่นนั้นก็จะพัง ไปที่คอนโซล AWS Lambda จากนั้นคลิกที่ Lambda ที่เพิ่งปรับใช้ คลิกที่ การกำหนดค่า แท็บ จากนั้นบนเมนูด้านซ้าย ให้คลิก ตัวแปรสภาพแวดล้อม . พิมพ์535เป็นคีย์และ Upstash Redis URL ของคุณเป็นค่า คลิกบันทึก และตอนนี้ Lambda ของคุณก็พร้อมแล้ว
- หรืออีกวิธีหนึ่ง คุณยังสามารถค้นหา URL ของฟังก์ชันที่สร้างขึ้นใหม่ในเอาต์พุตของสแต็ก CloudFormation
4.1 การทดสอบ SAM ในพื้นที่
เราสามารถทดสอบ Lambda ของเราภายในเครื่องได้โดยระบุ 540 ด้วยเส้นทางที่ถูกต้อง / คุกกี้ / พารามิเตอร์แบบสอบถาม / ฯลฯ ตัวอย่างของ JSON ดังกล่าวมีอยู่ใน 559 .
- จากนั้น เมื่อคุณมีไฟล์เหตุการณ์ 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 ได้
เราสามารถใช้ที่เก็บพารามิเตอร์ AWS Systems Manager และทรัพยากร Cloudformation ที่เกี่ยวข้อง 565 เพื่อเก็บ URL (เราสามารถตั้งค่าได้ครั้งเดียวและเก็บไว้ในระหว่างการปรับใช้) และเปลี่ยนโค้ด Lambda ของเราเพื่อดึงค่าของพารามิเตอร์ขณะรันไทม์ นอกจากนี้เรายังสามารถฉีดมันเป็นตัวแปร env ภายใน 571 โดยอัตโนมัติ แม้ว่าสิ่งนี้จะยังคงเป็นข้อความธรรมดาในคอนโซลก็ตาม
การเปลี่ยนโค้ดเพื่อดึงข้อมูลจากร้านค้าพารามิเตอร์ SSM เป็นเรื่องง่ายเนื่องจากเราแยกจุดเข้าใช้งาน ดังนั้นเราจึงสามารถดึงพารามิเตอร์ได้เฉพาะเมื่อทำงานภายใน AWS Lambda (585 ) และส่งผ่านไปยัง 592 ฟังก์ชั่นที่สร้างไคลเอนต์ Redis
5. มันเร็วแค่ไหน?
นอกเหนือจากการเรียกใช้ Cold Start ครั้งแรกซึ่งใช้เวลาประมาณ 603 ทุกการร้องขอหลังจากนั้นจะเร็วปานสายฟ้าและอยู่ภายใต้ 618 เสมอ .
ด้านล่างนี้เป็นตัวอย่างของการร้องขอร้อนสำหรับ 623 ปลายทางตามการใช้งานด้านบน:

ดังที่คุณเห็นระยะเวลารวมของคำขอของเราคือ 635 . ใช่ นั่นคือ สองมิลลิวินาที หากต้องการสร้าง ID เซสชัน ให้เขียนลงใน Upstash Redis จากระยะไกล และส่งคืนการตอบกลับการเปลี่ยนเส้นทาง
ดูให้ละเอียดยิ่งขึ้นในเอาต์พุตบันทึก ส่วนเราจะเห็นว่าคำขอกินเวลา 644 อย่างน้อยก็จากมุมมองของโค้ดของเรา ซึ่งหมายความว่าตรรกะของเราเสร็จสมบูรณ์ได้ดีภายใต้ 657 (ประมาณ 667 ). น่าทึ่งมากเมื่อพิจารณาว่าเรากำลังใช้ฐานข้อมูลระยะไกล🤯
บทสรุป
ฉันประหลาดใจจริงๆ กับประสิทธิภาพของ Upstash Redis โดยเฉพาะอย่างยิ่งเนื่องจากเป็นการยากที่จะพบประสิทธิภาพดังกล่าวสำหรับฐานข้อมูลแบบไร้เซิร์ฟเวอร์ที่เหมาะกับแพลตฟอร์ม เช่น AWS Lambda
Redis API นั้นสะดวกมาก Upstash Redis มีรูปแบบการกำหนดราคาที่ยอดเยี่ยมและประสบการณ์ของนักพัฒนาที่ยอดเยี่ยม และมันก็รวดเร็ว ฉันชอบการผสมผสานกัน!
AWS Lambda + Upstash Redis + Go =🚀❤️