ในบทความนี้ ฉันสำรวจบทบาทสำคัญของ Upstash ในการพัฒนา PlanTripAI ซึ่งเป็นการเริ่มต้นการวางแผนการเดินทางที่ขับเคลื่อนด้วย AI การใช้ Upstash Redis มีความสำคัญอย่างยิ่งต่อการจัดการด้านที่สำคัญ เช่น การจัดเก็บใบอนุญาตที่สำคัญสำหรับการเข้าถึงของผู้ใช้ และการบันทึกและแคชเนื้อหาการเดินทางอย่างมีประสิทธิภาพ นอกจากนี้ คุณลักษณะการจำกัดอัตราของ Upstash ยังมีบทบาทสำคัญในการปกป้องระบบของเรา จัดการความถี่คำขอได้อย่างมีประสิทธิภาพ โดยเสนอการป้องกันที่แข็งแกร่งต่อภัยคุกคามความปลอดภัยที่อาจเกิดขึ้น และรับประกันบริการที่ราบรื่นและไม่สะดุดสำหรับผู้ใช้ของเรา
plantripai.com คือเครื่องมือวางแผนการเดินทางที่ใช้ AI ซึ่งสร้างแผนการเดินทางส่วนบุคคลได้อย่างรวดเร็วโดยอิงตามความต้องการของผู้ใช้ เช่น จุดหมายปลายทาง ระยะเวลาการเข้าพัก รูปแบบการเดินทาง และงบประมาณ โดยนำเสนอแผนการเดินทางไม่จำกัดและรูปแบบการดาวน์โหลดที่หลากหลาย
- @upstash/redis
- @upstash/ratelimit
- next.js
มันทำงานอย่างไร
บริษัท AI มักเสนอหลายวิธีให้ผู้ใช้ลองใช้ผลิตภัณฑ์ของตน ที่ PlanTripAI เราให้บริการทั้งแบบฟรีเมียมและแบบชำระเงิน
ในแผนฟรีเมียมและเป็นที่นิยมมากที่สุดของเรา:ทุกครั้งที่ผู้ใช้สร้างการเดินทางโดยไม่มีใบอนุญาตที่ถูกต้อง รหัสสุ่มใหม่จะถูกสร้างขึ้นและเก็บไว้ในแฮช Redis (redis.hset(trip:${key}, data)) พร้อมด้วยเนื้อหาการเดินทาง คีย์นี้ให้สิทธิ์การเข้าถึงหน้ารายละเอียดการเดินทางชั่วคราว เมื่อการเข้าถึงนี้สิ้นสุดลง ผู้ใช้สามารถตัดสินใจว่าจะคงการเข้าถึงการเดินทางอย่างถาวรไว้หรือไม่
นอกจากนี้ ผู้ใช้ freemium จะต้องถูกจำกัดอัตรา (fixedWindow ) ของ 3 คำขอต่อ 10 วินาที ซึ่งช่วยป้องกันการโจมตีที่อาจเกิดขึ้นกับแอปพลิเคชัน

สำหรับแผนการชำระเงิน ผู้ใช้สามารถซื้อผลิตภัณฑ์ผ่านเกตเวย์การชำระเงินได้ เมื่อทำธุรกรรมสำเร็จ webhook ของเกตเวย์การชำระเงินจะปล่อยเหตุการณ์ความสำเร็จ และคีย์จะถูกเก็บไว้ใน Redis เป็นคีย์ที่ถูกต้อง (redis.set(${licenseKey}, true)) .
เมื่อผู้ใช้ที่มีใบอนุญาตที่ถูกต้องสร้างการเดินทาง รหัสแบบสุ่มจะยังคงสร้างและจัดเก็บไว้ใน Redis นอกจากนี้ การเดินทางใหม่จะถูกจัดเก็บไว้ในออบเจ็กต์ผู้ใช้และเชื่อมโยงกับรหัสใบอนุญาต
ผู้ใช้แบบชำระเงินจะได้รับอัตราจำกัดที่มากกว่าผู้ใช้แบบฟรีเมียม คุณลักษณะที่ได้รับการปรับปรุงนี้มีให้แบบไดนามิกโดยการตรวจสอบคีย์ที่ถูกต้องใน Redis

การจัดเก็บข้อมูลการเดินทาง
PlanTripAI ใช้ประโยชน์จาก Redis เพื่อจัดเก็บการเดินทางที่ผู้ใช้สร้างขึ้น Redis เป็นตัวเลือกในอุดมคติสำหรับเราเนื่องจากมีประสิทธิภาพในการเก็บคีย์-ค่าที่รวดเร็ว เนื่องจากการเดินทางเมื่อสร้างขึ้นแล้วจะไม่เปลี่ยนรูป และการใช้แฮชช่วยให้เราสามารถจัดเก็บข้อมูลเมตาควบคู่ไปกับข้อมูลสำคัญได้
ข้อมูลการเดินทางมีโครงสร้างเป็นแฮช Redis ดังนี้:
{
"itinerary": [
{ "day": "Day 1", "data": [...] }
],
"info": "This itinerary is designed for a city explorer visiting Paris, France for 2 days.",
"inputs": {
"city": "Paris, France",
"days": 2,
"accommodation": "Paris France Hotel",
"kind": "city explorer",
"currency": "USD",
"budget": 3000,
"transportation": "bus"
},
"createdAt": ...,
"shareable": false
} เมื่อใช้ Upstash Redis API บน HTTP ข้อมูลจะถูกจัดเก็บไว้ในฐานข้อมูล Redis ฟรี ซึ่งเสนอคำขอ 10,000 คำขอต่อวันฟรี ซึ่งมากเกินพอสำหรับความต้องการของเรา
import { Redis } from "@upstash/redis";
const redis = new Redis({
url: "..." // UPSTASH_REDIS_REST_URL
token: "..." // UPSTASH_REDIS_REST_TOKEN
});
redis.hset(`trip:${id}`, data); การจัดเก็บรหัสใบอนุญาตที่ถูกต้อง
ตามที่กล่าวไว้ก่อนหน้านี้ วิธีหนึ่งในการเข้าถึงคุณสมบัติทั้งหมดของ PlanTripAI คือผ่านการสมัครสมาชิกแบบชำระเงิน โดยผู้ใช้ที่ชำระเงินแต่ละรายจะได้รับรหัสใบอนุญาตที่ถูกต้องซึ่งจัดเก็บไว้ใน Redis การตั้งค่านี้เหมาะอย่างยิ่งสำหรับการตรวจสอบความถูกต้องอย่างรวดเร็ว โดยพิจารณาจากประสิทธิภาพของ Redis ในฐานะฐานข้อมูลคีย์-ค่า
เพื่อทำเครื่องหมายผู้ใช้ว่าถูกต้อง เราจะดำเนินการคำสั่งต่อไปนี้:
import { Redis } from "@upstash/redis";
const redis = new Redis({
url: "..." // UPSTASH_REDIS_REST_URL
token: "..." // UPSTASH_REDIS_REST_TOKEN
});
await redis.set(licenseKey, true); เพื่อตรวจสอบความถูกต้องของผู้ใช้ เราใช้คำสั่งนี้:
import { Redis } from "@upstash/redis";
const redis = new Redis({
url: "..." // UPSTASH_REDIS_REST_URL
token: "..." // UPSTASH_REDIS_REST_TOKEN
});
const redisLicenseKey = await redis.get(licenseKey);
const valid = Boolean(redisLicenseKey);
if (!valid) {
return new Response(
JSON.stringify({ message: "The license key is invalid!" }),
{
status: 401,
}
);
}
// successful code here...
การใช้ขีดจำกัดอัตรา
คุณลักษณะสำคัญในการปกป้องแอปพลิเคชันของเราคือตรรกะการจำกัดอัตรา ซึ่งสนับสนุนโดย Upstash Rate Limit สามารถดูข้อมูลเพิ่มเติมได้ที่นี่ บริการนี้มีความสำคัญอย่างยิ่งต่อการรักษาประสบการณ์ที่ราบรื่นสำหรับผู้ใช้ทั้งแบบฟรีและมีค่าใช้จ่าย โดยสามารถป้องกันการโจมตีจากผู้ใช้ที่เป็นอันตรายได้สำเร็จโดยไม่ส่งผลกระทบต่อแอปพลิเคชันโดยรวม
ด้านล่างนี้คือข้อมูลโค้ดที่ใช้ next.js เป็นมิดเดิลแวร์ รหัสนี้ช่วยจัดการการตรวจสอบ IP ของผู้ใช้และตัดสินใจว่าจะดำเนินการตามคำขอที่ตามมาหรือไม่
import {
NextResponse,
type NextFetchEvent,
type NextRequest,
} from "next/server";
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
const cache = new Map();
const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.fixedWindow(3, "10s"),
ephemeralCache: cache,
analytics: true,
});
export default async function middleware(
request: NextRequest,
event: NextFetchEvent
): Promise<Response | undefined> {
const id = request.ip ?? "anonymous";
// optional hard coded IPs
const blockeds = [];
if (blockeds.includes(id.trim())) {
new NextResponse(
JSON.stringify({
message: "Blocked :)",
}),
{ status: 429, headers: { "Content-Type": "application/json" } }
);
}
const { success, pending, limit, reset, remaining } = await ratelimit.limit(
id
);
event.waitUntil(pending);
request.headers.set("X-RateLimit-Limit", limit.toString());
request.headers.set("X-RateLimit-Remaining", remaining.toString());
request.headers.set("X-RateLimit-Reset", reset.toString());
return success
? NextResponse.next()
: new NextResponse(
JSON.stringify({
message:
"Request cannot be processed! You sent too many requests in a given amount of time.",
}),
{ status: 429, headers: { "Content-Type": "application/json" } }
);
}
export const config = {
matcher: ["/api/generate-trip", "/api/get-license/(.*)"],
}; คำพูดสุดท้าย
ขอบคุณที่สละเวลาอ่าน! PlanTripAI เริ่มต้นเป็นโปรเจ็กต์เสริม ซึ่งเกิดจากความอยากรู้อยากเห็นของฉันเกี่ยวกับการผสานรวม Upstash Redis เข้ากับ Next.js ในเฟรมเวิร์ก SaaS
ฉันหวังเป็นอย่างยิ่งว่าคุณจะพบข้อมูลและข้อมูลเชิงลึกนี้ คำถามหรือข้อเสนอแนะของคุณได้รับการชื่นชมอย่างมาก อย่าลังเลที่จะเชื่อมต่อกับฉันบน Twitter หากมีข้อสงสัยหรือแสดงความคิดเห็น