이 튜토리얼에서는 Node.js와 Redis를 사용하여 확장 가능한 URL 단축 서비스를 구축합니다. 이 서비스는 분산 캐싱을 활용하여 높은 트래픽을 효율적으로 처리하고 대기 시간을 줄이며 원활하게 확장합니다. 일관된 해싱, 캐시 무효화 전략, 시스템의 빠르고 안정적인 유지를 위한 샤딩과 같은 주요 개념을 살펴보겠습니다.
이 가이드가 끝나면 분산 캐싱을 사용하여 성능을 최적화하는 완전한 기능의 URL 단축 서비스를 갖게 됩니다. 또한 사용자가 URL을 입력하고 캐시 적중 및 누락과 같은 실시간 측정항목을 확인할 수 있는 대화형 데모도 만들 예정입니다.
배우게 될 내용
-
Node.js를 사용하여 URL 단축 서비스를 구축하는 방법 및 Redis .
-
분산 캐싱 구현 방법 성능을 최적화합니다.
-
일관적 해싱 이해 및 캐시 무효화 전략 .
-
Docker 사용 샤딩 및 확장을 위해 여러 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
-
express:경량 웹 서버 프레임워크입니다. -
redis:캐싱을 처리합니다. -
shortid:짧고 고유한 ID를 생성하기 위한 것입니다. -
dotenv:환경변수를 관리하기 위한 것입니다.
.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}`);
});
이 코드에서 볼 수 있듯이 다음이 포함됩니다.
-
일관된 해싱 :
-
우리는 간단한 해시 함수를 사용하여 여러 Redis 클라이언트에 키(단축 URL)를 배포합니다.
-
해시 기능은 URL이 Redis 인스턴스 전체에 균등하게 분산되도록 보장합니다.
-
-
URL 단축 :
-
/단축 엔드포인트는 긴 URL을 허용하고 shortid를 사용하여 짧은 ID를 생성합니다. 도서관.
-
단축 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(Time-To-Live) :기본 만료 시간은 1시간으로 설정되어 있습니다. 각 단축 URL에 대해 필요한 경우 각 URL의 TTL을 맞춤설정할 수 있습니다.
-
캐시 무효화 :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
-
엔드포인트 테스트
curl사용 또는 우편 배달부:-
URL 단축:
POST http://localhost:3000/shorten Body: { "url": "https://example.com" } -
단축 URL에 접속하세요:
GET http://localhost:3000/{shortId}
-
결론:배운 내용
축하합니다! 확장 가능한 URL 단축 서비스를 성공적으로 구축했습니다. 분산 캐싱 사용 Node.js와 Redis를 사용합니다. 이 튜토리얼 전체에서 다음 방법을 배웠습니다:
-
일관된 해싱 구현 여러 Redis 인스턴스에 캐시 항목을 배포합니다.
-
캐시 무효화 전략으로 애플리케이션을 최적화하세요. 데이터를 최신 상태로 유지합니다.
-
Docker 사용 여러 Redis 노드가 있는 분산 환경을 시뮬레이션합니다.
-
캐시 적중 및 누락 모니터링 성능을 최적화합니다.
다음 단계:
-
데이터베이스 추가 :캐시 이상의 지속성을 위해 데이터베이스에 URL을 저장합니다.
-
분석 구현 :단축 URL에 대한 클릭수 및 분석을 추적합니다.
-
클라우드에 배포 :자동 확장 및 복원력을 위해 Kubernetes를 사용하여 애플리케이션을 배포하세요.
즐거운 코딩 되세요!
무료로 코딩을 배우세요. freeCodeCamp의 오픈 소스 커리큘럼은 40,000명 이상의 사람들이 개발자로 취업하는 데 도움을 주었습니다. 시작하세요