ในบทช่วยสอนนี้ เราจะสร้างบริการย่อ URL ที่ปรับขนาดได้โดยใช้ Node.js และ Redis บริการนี้จะใช้ประโยชน์จากแคชแบบกระจายเพื่อจัดการกับการรับส่งข้อมูลสูงอย่างมีประสิทธิภาพ ลดเวลาแฝง และปรับขนาดได้อย่างราบรื่น เราจะสำรวจแนวคิดหลักๆ เช่น การแฮชที่สม่ำเสมอ กลยุทธ์การทำให้แคชใช้ไม่ได้ และการแบ่งส่วนเพื่อให้แน่ใจว่าระบบยังคงรวดเร็วและเชื่อถือได้
ในตอนท้ายของคู่มือนี้ คุณจะมีบริการย่อ URL ที่ทำงานได้อย่างสมบูรณ์ซึ่งใช้แคชแบบกระจายเพื่อเพิ่มประสิทธิภาพการทำงาน นอกจากนี้ เรายังจะสร้างการสาธิตเชิงโต้ตอบที่ผู้ใช้สามารถป้อน URL และดูตัวชี้วัดแบบเรียลไทม์ เช่น จำนวนการเข้าใช้แคชและการพลาด
สิ่งที่คุณจะได้เรียนรู้
-
วิธีสร้างบริการย่อ URL โดยใช้ Node.js และ เรดิส .
-
วิธีการใช้งาน แคชแบบกระจาย เพื่อเพิ่มประสิทธิภาพการทำงาน
-
ทำความเข้าใจกับ การแฮชที่สอดคล้องกัน และกลยุทธ์การทำให้แคชใช้ไม่ได้ .
-
การใช้ นักเทียบท่า เพื่อจำลองอินสแตนซ์ Redis หลายรายการสำหรับการแบ่งส่วนและการปรับขนาด
ข้อกำหนดเบื้องต้น
ก่อนเริ่มต้น ตรวจสอบให้แน่ใจว่าคุณได้ติดตั้งสิ่งต่อไปนี้แล้ว:
-
Node.js (v14 หรือสูงกว่า)
-
เรดดิส
-
นักเทียบท่า
-
ความรู้พื้นฐานเกี่ยวกับ JavaScript, Node.js และ Redis
สารบัญ
-
ภาพรวมโครงการ
-
ขั้นตอนที่ 1:การตั้งค่าโครงการ
-
ขั้นตอนที่ 2:การตั้งค่าอินสแตนซ์ Redis
-
ขั้นตอนที่ 3:การใช้บริการย่อ URL
-
ขั้นตอนที่ 4:การใช้การทำให้แคชใช้งานไม่ได้
-
ขั้นตอนที่ 5:การตรวจสอบการวัดแคช
-
ขั้นตอนที่ 6:ทดสอบแอปพลิเคชัน
-
สรุป:สิ่งที่คุณได้เรียนรู้
ภาพรวมโครงการ
เราจะสร้างบริการย่อ URL โดยที่:
-
ผู้ใช้สามารถย่อ URL ที่ยาวและเรียกค้น URL ดั้งเดิมได้
-
บริการนี้ใช้ แคช Redis เพื่อจัดเก็บการแมประหว่าง URL แบบสั้นและ URL ดั้งเดิม
-
แคชถูกกระจายไปยังอินสแตนซ์ Redis หลายอินสแตนซ์เพื่อรองรับการรับส่งข้อมูลจำนวนมาก
-
ระบบจะสาธิต การเข้าถึงแคช และพลาด แบบเรียลไทม์
สถาปัตยกรรมระบบ
เพื่อให้มั่นใจถึงความสามารถในการปรับขนาดและประสิทธิภาพ เราจะแบ่งบริการของเราออกเป็นองค์ประกอบต่อไปนี้:
-
เซิร์ฟเวอร์ API :จัดการคำขอให้สั้นลงและดึง URL
-
เลเยอร์แคช Redis :ใช้อินสแตนซ์ Redis หลายรายการสำหรับแคชแบบกระจาย
-
นักเทียบท่า :จำลองสภาพแวดล้อมแบบกระจายด้วยคอนเทนเนอร์ Redis หลายตัว
ขั้นตอนที่ 1:การตั้งค่าโครงการ
มาตั้งค่าโครงการของเราโดยการเริ่มต้นแอปพลิเคชัน Node.js:
mkdir scalable-url-shortener
cd scalable-url-shortener
npm init -y
ตอนนี้ ให้ติดตั้งการขึ้นต่อกันที่จำเป็น:
npm install express redis shortid dotenv
-
04รหัส> :เฟรมเวิร์กเว็บเซิร์ฟเวอร์น้ำหนักเบา -
18รหัส> :เพื่อจัดการแคช -
21รหัส> :สำหรับการสร้าง ID แบบสั้นและไม่ซ้ำใคร -
33รหัส> :สำหรับการจัดการตัวแปรสภาพแวดล้อม
สร้าง .env ไฟล์ในรูทของโปรเจ็กต์ของคุณ:
PORT=3000
REDIS_HOST_1=localhost
REDIS_PORT_1=6379
REDIS_HOST_2=localhost
REDIS_PORT_2=6380
REDIS_HOST_3=localhost
REDIS_PORT_3=6381
ตัวแปรเหล่านี้กำหนดโฮสต์และพอร์ต Redis ที่เราจะใช้
ขั้นตอนที่ 2:การตั้งค่าอินสแตนซ์ Redis
เราจะใช้ Docker เพื่อจำลองสภาพแวดล้อมแบบกระจายด้วยอินสแตนซ์ Redis หลายรายการ
เรียกใช้คำสั่งต่อไปนี้เพื่อเริ่มคอนเทนเนอร์ Redis สามคอนเทนเนอร์:
docker run -p 6379:6379 --name redis1 -d redis
docker run -p 6380:6379 --name redis2 -d redis
docker run -p 6381:6379 --name redis3 -d redis
การดำเนินการนี้จะตั้งค่าอินสแตนซ์ Redis สามอินสแตนซ์ที่ทำงานบนพอร์ตที่ต่างกัน เราจะใช้อินสแตนซ์เหล่านี้เพื่อใช้งานการแฮชที่สอดคล้องกัน และการแบ่งส่วน
ขั้นตอนที่ 3:การใช้บริการย่อ URL
มาสร้างไฟล์แอปพลิเคชันหลักของเรา index.js :
require('dotenv').config();
const express = require('express');
const redis = require('redis');
const shortid = require('shortid');
const app = express();
app.use(express.json());
const redisClients = [
redis.createClient({ host: process.env.REDIS_HOST_1, port: process.env.REDIS_PORT_1 }),
redis.createClient({ host: process.env.REDIS_HOST_2, port: process.env.REDIS_PORT_2 }),
redis.createClient({ host: process.env.REDIS_HOST_3, port: process.env.REDIS_PORT_3 })
];
// Hash function to distribute keys among Redis clients
function getRedisClient(key) {
const hash = key.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0);
return redisClients[hash % redisClients.length];
}
// Endpoint to shorten a URL
app.post('/shorten', async (req, res) => {
const { url } = req.body;
if (!url) return res.status(400).send('URL is required');
const shortId = shortid.generate();
const redisClient = getRedisClient(shortId);
await redisClient.set(shortId, url);
res.json({ shortUrl: `http://localhost:${process.env.PORT}/${shortId}` });
});
// Endpoint to retrieve the original URL
app.get('/:shortId', async (req, res) => {
const { shortId } = req.params;
const redisClient = getRedisClient(shortId);
redisClient.get(shortId, (err, url) => {
if (err || !url) {
return res.status(404).send('URL not found');
}
res.redirect(url);
});
});
app.listen(process.env.PORT, () => {
console.log(`Server running on port ${process.env.PORT}`);
});
ดังที่คุณเห็นในโค้ดนี้ เรามี:
-
การแฮชที่สม่ำเสมอ :
-
เราแจกจ่ายคีย์ (URL แบบสั้น) ไปยังไคลเอนต์ Redis หลายเครื่องโดยใช้ฟังก์ชันแฮชแบบง่าย
-
ฟังก์ชันแฮชช่วยให้แน่ใจว่า URL มีการกระจายเท่าๆ กันในอินสแตนซ์ Redis
-
-
การย่อ URL :
-
/ย่อ จุดสิ้นสุดยอมรับ URL แบบยาวและสร้าง ID แบบสั้นโดยใช้ shortid ห้องสมุด
-
URL แบบสั้นจะถูกจัดเก็บไว้ในอินสแตนซ์ Redis ตัวใดตัวหนึ่งโดยใช้ฟังก์ชันแฮชของเรา
-
-
การเปลี่ยนเส้นทาง URL :
-
/:shortId จุดสิ้นสุดดึง URL ดั้งเดิมจากแคชและเปลี่ยนเส้นทางผู้ใช้
-
หากไม่พบ URL ในแคช จะเป็น 404 การตอบสนองถูกส่งกลับ
-
ขั้นตอนที่ 4:การใช้งานการทำให้แคชใช้งานไม่ได้
ในแอปพลิเคชันในโลกแห่งความเป็นจริง URL อาจหมดอายุหรือเปลี่ยนแปลงเมื่อเวลาผ่านไป เพื่อจัดการกับสิ่งนี้ เราจำเป็นต้องดำเนินการ การทำให้แคชใช้ไม่ได้ .
การเพิ่มการหมดอายุให้กับ URL ที่แคชไว้
มาแก้ไข index.js ของเรากันดีกว่า ไฟล์เพื่อตั้งเวลาหมดอายุสำหรับแต่ละรายการที่แคชไว้:
// Endpoint to shorten a URL with expiration
app.post('/shorten', async (req, res) => {
const { url, ttl } = req.body; // ttl (time-to-live) is optional
if (!url) return res.status(400).send('URL is required');
const shortId = shortid.generate();
const redisClient = getRedisClient(shortId);
await redisClient.set(shortId, url, 'EX', ttl || 3600); // Default TTL of 1 hour
res.json({ shortUrl: `http://localhost:${process.env.PORT}/${shortId}` });
});
-
TTL (ระยะเวลาใช้งานจริง) :เราตั้งเวลาหมดอายุเริ่มต้นไว้ที่ 1 ชั่วโมง สำหรับ URL แบบสั้นแต่ละรายการ คุณสามารถปรับแต่ง TTL สำหรับแต่ละ URL ได้หากต้องการ
-
แคชใช้ไม่ได้ :เมื่อ TTL หมดอายุ รายการจะถูกลบออกจากแคชโดยอัตโนมัติ
ขั้นตอนที่ 5:การตรวจสอบการวัดแคช
เพื่อตรวจสอบ การเข้าถึงแคช และพลาด เราจะเพิ่มการบันทึกลงในจุดสิ้นสุดของเราใน index.js :
app.get('/:shortId', async (req, res) => {
const { shortId } = req.params;
const redisClient = getRedisClient(shortId);
redisClient.get(shortId, (err, url) => {
if (err || !url) {
console.log(`Cache miss for key: ${shortId}`);
return res.status(404).send('URL not found');
}
console.log(`Cache hit for key: ${shortId}`);
res.redirect(url);
});
});
ต่อไปนี้คือสิ่งที่เกิดขึ้นในโค้ดนี้:
-
การเข้าถึงแคช :หากพบ URL ในแคช แสดงว่าเป็นการเข้าใช้แคช
-
แคชหายไป :หากไม่พบ URL แสดงว่าแคชหายไป
-
การบันทึกนี้จะช่วยคุณตรวจสอบประสิทธิภาพของแคชแบบกระจายของคุณ
ขั้นตอนที่ 6:ทดสอบแอปพลิเคชัน
- เริ่มต้นอินสแตนซ์ Redis ของคุณ :
docker start redis1 redis2 redis3
- เรียกใช้เซิร์ฟเวอร์ Node.js :
node index.js
-
ทดสอบปลายทาง ใช้
40หรือบุรุษไปรษณีย์:-
ย่อ URL:
POST http://localhost:3000/shorten Body: { "url": "https://example.com" } -
เข้าถึง URL แบบสั้น:
GET http://localhost:3000/{shortId}
-
บทสรุป:สิ่งที่คุณได้เรียนรู้
ขอแสดงความยินดี! คุณได้สร้างบริการย่อ URL ที่ปรับขนาดได้สำเร็จแล้ว ด้วย แคชแบบกระจาย โดยใช้ Node.js และ Redis ตลอดบทแนะนำนี้ คุณได้เรียนรู้วิธี:
-
ใช้การแฮชที่สอดคล้องกัน เพื่อกระจายรายการแคชไปยังอินสแตนซ์ Redis หลายรายการ
-
เพิ่มประสิทธิภาพแอปพลิเคชันของคุณด้วยกลยุทธ์การทำให้แคชใช้ไม่ได้ เพื่อให้ข้อมูลอัปเดตอยู่เสมอ
-
ใช้ นักเทียบท่า เพื่อจำลองสภาพแวดล้อมแบบกระจายด้วยโหนด Redis หลายโหนด
-
ตรวจสอบการเข้าถึงแคชและการพลาด เพื่อเพิ่มประสิทธิภาพการทำงาน
ขั้นตอนถัดไป:
-
เพิ่มฐานข้อมูล :จัดเก็บ URL ในฐานข้อมูลเพื่อความคงอยู่นอกเหนือจากแคช
-
ใช้งานการวิเคราะห์ :ติดตามจำนวนคลิกและการวิเคราะห์สำหรับ URL แบบสั้น
-
ปรับใช้กับระบบคลาวด์ :ปรับใช้แอปพลิเคชันของคุณโดยใช้ Kubernetes เพื่อการปรับขนาดอัตโนมัติและความยืดหยุ่น
ขอให้สนุกกับการเขียนโค้ด!
เรียนรู้การเขียนโค้ดฟรี หลักสูตรโอเพ่นซอร์สของ freeCodeCamp ช่วยให้ผู้คนมากกว่า 40,000 คนได้งานในตำแหน่งนักพัฒนา เริ่มต้น