परिचय
सर्वरलेस कम्प्यूट प्लेटफ़ॉर्म शानदार हैं, लेकिन सर्वरलेस डेटाबेस के बिना वे बहुत सीमित हैं।
जब मैं अपने आगामी कोर्स "The Elements of CI/CD" के लिए प्लेटफ़ॉर्म बना रहा था, तो मुझे एक सर्वरलेस डेटाबेस चाहिए था क्योंकि मैंने कुछ चीज़ों के लिए अपने सर्वर के रूप में AWS Lambda का उपयोग करने का फ़ैसला किया था। मेरी आवश्यकताएँ थीं:
- पे-एज़-यू-गो प्राइसिंग। मैं प्रति घंटे या प्रति नोड भुगतान नहीं करना चाहता, बल्कि उपयोग (रिक्वेस्ट, स्टोरेज, आदि) के अनुसार। शुरुआत में इसका उपयोग करना बहुत सस्ता होना चाहिए और जैसे-जैसे उपयोग बढ़े, लागत आनुपातिक रूप से बढ़े।
- कम लेटेंसी। किसी को धीमी प्रतिक्रियाएँ पसंद नहीं हैं, इसलिए डेटाबेस क्वेरी AWS रीजन के अंदर से तेज़ होनी चाहिए (उदाहरण के लिए
eu-west-1)। - शानदार डेवलपर अनुभव (DevX)। एक और विशिष्ट DSL सीखे बिना या वेबसाइट के साथ घंटों बर्बाद किए बिना डेटाबेस के लिए एक अच्छा इंटरफ़ेस होना चाहिए।
Upstash Redis ऊपर की सभी आवश्यकताओं को पूरा करता है, और इसे बहुत अच्छी तरह से करता है।
- पे-एज़-यू-गो?
- ✅ शुरुआत में वास्तव में किफ़ायती, और स्केल पर भी!
- कम लेटेंसी?
- ✅ AWS Lambda के अंदर से क्वेरी करने पर
<1ms लेटेंसी!
- ✅ AWS Lambda के अंदर से क्वेरी करने पर
- शानदार DevX?
- ✅ यह स्टैंडर्ड Redis है। तो, हाँ।
इस लेख में हम देखेंगे कि AWS Lambda के अंदर से Upstash Redis का उपयोग कैसे करें, यह सुनिश्चित करें कि यह हमारी ज़रूरतों के लिए पर्याप्त तेज़ है, साथ ही हमारे कोड को मेंटेनेबल रखें ताकि हम इसे स्थानीय रूप से टेस्ट कर सकें या किसी अन्य प्लेटफ़ॉर्म पर डिप्लॉय कर सकें।
हम क्या लागू कर रहे हैं?
सरलता के लिए, हम केवल 3 API एंडपॉइंट लागू करेंगे:
GET|POST /loginएंडपॉइंट जोGETमें क्वेरी पैरामीटर के रूप में याPOSTरिक्वेस्ट के साथ सबमिट किए गए फॉर्म वैल्यू मेंuserIdस्वीकार करता है। यह एंडपॉइंट एक सेशन ID जेनरेट करता है, इसे Redis में स्टोर करता है, और बाद की विज़िट के लिए एक कुकी सेट करता है।GETकेवल टेस्टिंग को आसान बनाता है।🙃GET /lessons/completedएंडपॉइंट लॉग-इन यूज़र्स (यानी सेशन ID वाली कुकी होने) की आवश्यकता होती है और यूज़र द्वारा पूरे किए गए सभी लेसन और कब, के साथ JSON प्रतिक्रिया देता है।POST /lessons/{lessonSlug}/mark-completeएंडपॉइंट लॉग-इन यूज़र्स की आवश्यकता होती है औरlessonSlugद्वारा दर्शाए गए लेसन को वर्तमान समय के साथ पूरा हुआ मार्क करता है।
नोट: नीचे दिए गए कोड में कुछ चीज़ें गायब हैं, इसलिए यह प्रोडक्शन-रेडी कॉपी-पेस्ट करने योग्य कोड नहीं है। उदाहरण के लिए, अपडेट करने से पहले हमें जांचना चाहिए कि दिया गया lessonSlug मौजूद है या नहीं। लॉगिन एंडपॉइंट को पासवर्ड भी स्वीकार करना चाहिए और सेशन ID बनाने से पहले उचित साल्टेड/हैश्ड वेरिफिकेशन करना चाहिए, आदि।
1. सेटअप
- नीचे विस्तृत पूरा कोड मेरे
aws-playgroundरिपॉजिटरी में भी मौजूद है अगर आप देखना चाहते हैं कि सब कुछ कैसे फिट होता है।
जैसा कि आप नीचे देखेंगे, हम दो एंट्रीपॉइंट बना रहे हैं, यानी दो एक्ज़ीक्यूटेबल कमांड। एक सामान्य लोकल सर्वर के लिए होगा, और एक AWS Lambda के लिए। इस तरह, हम अपने पूरे लॉजिक को स्थानीय रूप से टेस्ट कर सकेंगे, और यदि चाहें तो स्टैंडर्ड यूनिट/इंटीग्रेशन टेस्ट के साथ।
उनके बीच एकमात्र अंतर नीचे अनुभाग 1.2 और 1.3 में दिखाया गया है।
1.1 वर्कस्पेस
कोड में गोता लगाने से पहले, आइए Go के लिए अपनी वर्किंग डायरेक्टरी सेटअप करें।
- Go डाउनलोड करें।
- अपनी पसंद के रीजन में Upstash Redis अकाउंट और डेटाबेस बनाएं। आदर्श रूप से यह वही AWS रीजन होना चाहिए जिसमें आप अपना Lambda डिप्लॉय करेंगे। इस लेख में मैं
eu-west-1(यूरोप, आयरलैंड) का उपयोग करूंगा।

उपरोक्त पूरा करने के बाद, हम अब अपना वर्कस्पेस बना सकते हैं। लेख के बाकी हिस्से के लिए, मान लें कि हमारा कोड ~/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 विकल्प क्रॉस-कम्पाइल करने और AWS Lambda के लिनक्स वातावरण से मेल खाने के लिए आवश्यक हैं, यदि आप स्थानीय रूप से Mac या Windows सिस्टम का उपयोग कर रहे हैं।
इसके बाद, सभी कोड डिपेंडेंसी लाने के लिए go mod tidy चलाएं। याद रखें कि हर बार जब आप Go डिपेंडेंसी जोड़ते या हटाते हैं तो इसे चलाएं।
अंत में, कोड में गहराई से जाने से पहले सब कुछ बिल्ड करने और यह सुनिश्चित करने के लिए एक बार make चलाएं कि आपका वर्कस्पेस सेटअप है।
2. API कार्यान्वयन
इस खंड के लिए हम हमेशा ~/dev/aws-lambda-upstash-redis/core/lib.go फ़ाइल के अंदर काम करेंगे।
निम्न कुछ पंक्तियाँ पहले चर्चा किए गए API एंडपॉइंट को परिभाषित करती हैं, अद्भुत go-chi लाइब्रेरी का उपयोग करके।
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 मिडलवेयर
इस मिडलवेयर में हम निम्नलिखित लागू करना चाहते हैं:
- सेशन ID वाली कुकी निकालें, अन्यथा विफल करें।
- सेशन ID के आधार पर Redis से यूज़र डिटेल्स लाएं, और यदि प्रदान की गई सेशन ID एक्टिव नहीं है तो विफल करें।
- रिक्वेस्ट के
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 मिडलवेयर केवल लॉग-इन यूज़र्स तक पहुंच को प्रतिबंधित करता है।
// यदि वेरिफिकेशन पास हो जाता है, तो कॉन्टेक्स्ट में यूज़र 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 {
// यदि सेशन नहीं मिला तो यूज़र API एक्सेस करने से प्रतिबंधित है!
render.Status(r, http.StatusForbidden)
render.JSON(w, r, struct{}{})
return
} else if err != nil {
// Redis क्वेरी करते समय कुछ गलत हुआ!
render.Status(r, http.StatusInternalServerError)
render.JSON(w, r, struct{ Message string }{Message: "We could not validate the provided session ID"})
return
}
// डाउनस्ट्रीम मिडलवेयर और हैंडलर के लिए सेट करें।
next.ServeHTTP(w, r.WithContext(context.WithValue(ctx, CTX_USER_ID, userId)))
})
}
2.2 markLessonComplete(...)
यह एक सीधा ऑपरेशन है जहां हम Redis में स्टोर करना चाहते हैं कि lessonSlug पथ पैरामीटर द्वारा दर्शाया गया लेसन रिक्वेस्ट के वर्तमान समय पर पूरा हुआ।
Redis में हम प्रत्येक यूज़र के लिए एक मैप रखना चाहते हैं जहां मैप में प्रत्येक की-वैल्यू पेयर लेसन को कुंजी के रूप में और पूरा होने की तारीख को वैल्यू के रूप में होगा। इसलिए, हम HSET Redis कमांड का उपयोग करते हैं। हम प्रति लेसन एक अलग कुंजी भी स्टोर कर सकते थे लेकिन इससे बाद में एक यूज़र के सभी लेसन को एक साथ लाना आसान हो जाता है।
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 listLessonsCompleted(...)
पिछले खंड के समान तरीके से, यहां हम केवल लेसन पूरा होने का पूरा मैप लौटाना चाहते हैं और इसे यूज़र को 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 login(...)
अंत में, लॉगिन एंडपॉइंट। एक बार फिर, कृपया निम्न कोड को प्रोडक्शन में कॉपी न करें, क्योंकि यह किसी भी तरह का वेरिफिकेशन नहीं कर रहा है। इस लेख के उद्देश्यों के लिए हम केवल इसमें रुचि रखते हैं कि यह Redis को कैसे क्वेरी करता है और सेशन ID के लिए कुकी कैसे सेट करता है।
सेशन ID ksuid लाइब्रेरी द्वारा जेनरेट की जाती है, जिसके सामान्य UUID पर कुछ फायदे हैं, और हम इसे केवल 1 घंटे के लिए एक्टिव मानते हैं। हम Redis SET कमांड के टाइम-टू-लाइव फंक्शनलिटी का उपयोग एक घंटे के बाद डेटाबेस से स्वचालित हटाने के लिए करते हैं।
import (
// ...
"github.com/segmentio/ksuid"
)
func login(w http.ResponseWriter, r *http.Request) {
// क्रेडेंशियल जांचें और redis सेशन अपडेट करें और Set-Cookie वापस करें
// चेतावनी: प्रोडक्शन में आपको क्रेडेंशियल के लिए वास्तविक वेरिफिकेशन करना चाहिए!
// ...
// अभी के लिए हम हमेशा शुद्धता मानते हैं और स्वचालित रूप से एक सेशन टोकन बनाते हैं
// इसे Redis में सेव करके, और इसे कुकी के रूप में भी सेट करके।
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()),
// प्रोडक्शन में डिप्लॉय करते समय यह true होना चाहिए (https), लेकिन स्थानीय रूप से हमें false चाहिए (http)।
Secure: false,
})
http.Redirect(w, r, "/lessons/completed", http.StatusTemporaryRedirect)
}
3. डेमो - स्थानीय रूप से
उफ़, यह बहुत सारा कोड था।😅
आइए एक त्वरित डेमो करें ताकि यह सुनिश्चित हो सके कि सब कुछ अपेक्षानुसार काम करता है।
- सबसे पहले,
UPSTASH_REDIS_URLएनवायरनमेंट वेरिएबल को ऊपर अनुभाग 1 में बनाए गए डेटाबेस के URL पर सेट करें। आप इसे अपने डेटाबेस के पेज के डिटेल्स टैब में पा सकते हैं (ऊपर अनुभाग 1.1 देखें)।
export UPSTASH_REDIS_URL=""
- फिर, लोकल सर्वर को बिल्ड और चलाएं:
make build-server && ./build/server
ब्राउज़र टेस्टिंग
अब ब्राउज़र में https://localhost:5000/lessons/completed पर जाकर कुछ टेस्टिंग करते हैं।

हमें 403 - Forbidden मिलता है, तो आइए लॉगिन करते हैं, https://localhost:5000/login?userId=lambros पर जाकर।

हम अब लॉग-इन हैं, और हम स्वचालित रूप से /lessons/completed पर रीडायरेक्ट हो गए, लेकिन वे खाली हैं। तो, आइए एक लेसन को पूरा हुआ मार्क करें। अपने ब्राउज़र के देवटूल्स के console टैब में निम्न चलाएं:
await ( await fetch("https://localhost:5000/lessons/123/mark-complete", { method: "POST", credentials: "same-origin", }) ).json();
// कुछ इस तरह आउटपुट होना चाहिए:
// {LessonSlug: '123', LastCompleted: '2022-10-12T02:01:14+03:00'}
https://localhost:5000/lessons/completed पर जाने से अब यह लेसन मार्क हुआ दिखना चाहिए:
{
"Lessons": {
"123": "2022-10-12T02:01:14+03:00"
}
}
एट वोइला। सब कुछ ठीक काम करता है!
हाल ही में लॉन्च किए गए ऑनलाइन डेटा ब्राउज़र का उपयोग करके Redis डेटाबेस में देखने से यह भी साबित होता है कि अपेक्षित डेटा वहां है।

4. AWS Lambda
AWS Lambda पर टेस्ट और डिप्लॉय करने के लिए हम sam CLI का उपयोग करने जा रहे हैं।
सबसे पहले, SAM CLI सेटअप करें और सुनिश्चित करें कि आपके यूज़र/रोल के पास सही परमिशन हैं।
samCLI को काम करने के लिए 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::function:UpstashRedisGoArticleStackDem-GoUpstashRedis-baB8dQPkTfg0
Key GoUpstashRedisIamRole
Description Implicit IAM Role created for GoUpstashRedis
Value arn:aws:iam:::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 कंसोल में CloudFormation स्टैक
UpstashRedisGoArticleStackDemoके आउटपुट में नए बनाए गए फंक्शन का URL भी ढूंढ सकते हैं। - नोट: अपने AWS Lambda कॉन्फिगरेशन पर
UPSTASH_REDIS_URLएनवायरनमेंट वेरिएबल सेट करना सुनिश्चित करें, अन्यथा यह क्रैश हो जाएगा। AWS Lambda कंसोल पर जाएं, फिर अपने नए डिप्लॉय किए गए Lambda पर क्लिक करें, Configuration टैब पर क्लिक करें, और फिर बाएं साइड मेनू पर Environment variables पर क्लिक करें।UPSTASH_REDIS_URLको की के रूप में टाइप करें, और अपने Upstash Redis URL को वैल्यू के रूप में। Save पर क्लिक करें, और अब आपका Lambda तैयार है।
- वैकल्पिक रूप से, आप CloudFormation कंसोल में CloudFormation स्टैक
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 के अंदर एनवायरनमेंट वेरिएबल के रूप में स्वचालित रूप से इंजेक्ट भी कर सकते हैं, हालांकि यह अभी भी कंसोल में सादे टेक्स्ट में होगा।
हमारे एंट्रीपॉइंट्स के पृथक्करण के कारण SSM Parameter Store से इसे लाने के लिए कोड बदलना आसान है, इसलिए हम पैरामीटर को केवल AWS Lambda के अंदर चलने पर (~/dev/aws-lambda-upstash-redis/cmd/lambda/main.go) ला सकते हैं और इसे NewClient() फ़ंक्शन में पास कर सकते हैं जो Redis क्लाइंट बनाता है।
5. यह कितना तेज़ है?
पहले कोल्ड स्टार्ट इनवोकेशन को छोड़कर जो लगभग 100-120 ms लेता है, उसके बाद हर इनवोकेशन बिजली की तेजी से होता है और हमेशा 4 ms के अंदर होता है।
ऊपर लागू किए गए /login?userId=lambros एंडपॉइंट के लिए एक हॉट इनवोकेशन का उदाहरण नीचे है:

जैसा कि आप देख सकते हैं हमारे रिक्वेस्ट की कुल अवधि 2.06 ms थी। हां, वह दो मिलीसेकंड हैं, एक सेशन ID जेनरेट करने, इसे दूरस्थ रूप से Upstash Redis में लिखने, और रीडायरेक्शन प्रतिक्रिया वापस करने के लिए।
Log output अनुभाग को अधिक ध्यान से देखने पर, हम देख सकते हैं कि रिक्वेस्ट 789.435μs तक चली, कम से कम हमारे कोड के दृष्टिकोण से। इसका मतलब है कि हमारा लॉजिक 1 ms (लगभग 0.790 ms) से अच्छी तरह से पूरा हुआ। यह सोचकर दिमाग चकरा जाता है कि हम एक रिमोट डेटाबेस का उपयोग कर रहे हैं।🤯
निष्कर्ष
मैं वास्तव में चकित हूं कि Upstash Redis कितना अच्छा प्रदर्शन करता है, खासकर जब से AWS Lambda जैसे प्लेटफ़ॉर्म के लिए उपयुक्त सर्वरलेस डेटाबेस के लिए ऐसा प्रदर्शन ढूंढना कठिन है।
Redis API वास्तव में सुविधाजनक है, Upstash Redis में टॉप-नॉच प्राइसिंग मॉडल और शानदार डेवलपर अनुभव है, और यह तेज़ है। मुझे यह संयोजन पसंद है!
AWS Lambda + Upstash Redis + Go = 🚀❤️