در سیستمهای پیچیده و بزرگ، نیاز به تجمیع دادهها از منابع مختلف یا APIهای متفاوت، یک چالش اساسی است. پروژه Data Aggregation Layer به شما کمک میکند تا دادهها را از چندین API مختلف جمعآوری کنید، آنها را کش کنید، و مدیریت خطاهای سیستم را بهبود دهید. این پروژه با استفاده از Node.js، راهکارهایی برای مقیاسپذیری، امنیت، کشگذاری، و مانیتورینگ ارائه میدهد.
نکته:در تهیه این مقاله از هوش مصنوعی استفاده شده است
اهداف پروژه
- جمعآوری و تجمیع داده از چندین API خارجی
- پیادهسازی مدیریت خطاها و جلوگیری از مشکلات ناشی از درخواستهای مکرر به سرویسهای معیوب (Circuit Breaker)
- کشگذاری دادهها برای بهبود عملکرد و کاهش تعداد درخواستها
- استفاده از JWT برای امنیت و احراز هویت
- مانیتورینگ و جمعآوری متریکهای عملکردی با استفاده از Prometheus
1. تنظیمات پروژه
ابتدا فایل `config.js` برای تنظیمات APIها، کشگذاری، و کلیدهای JWT ایجاد میشود:
// config/config.js
module.exports = {
apis: {
api1: {
url: 'https://your-api1.com/data',
token: 'API1_TOKEN',
},
api2: {
url: 'https://your-api2.com/data',
token: 'API2_TOKEN',
},
},
cache: {
enabled: true,
ttl: 60 5, // 5 minutes caching
},
jwtSecret: 'YOUR_SECRET_KEY', // کلید رمزنگاری JWT
};
توضیحات:
- apis: شامل URL و توکن هر API برای احراز هویت است.
- cache: تنظیمات کش، شامل زمان انقضا.
- jwtSecret: کلید رمزنگاری JWT برای احراز هویت کاربران.
2. سرویسهای API
در این بخش، از کتابخانه axios برای ارسال درخواستها به APIهای مختلف و از opossum برای پیادهسازی Circuit Breaker استفاده میشود:
// services/apiService.js
const axios = require('axios');
const config = require('../config/config');
const opossum = require('opossum');
const breakerOptions = {
timeout: 3000, // زمان انتظار برای هر درخواست
errorThresholdPercentage: 50, // درصد خطاهایی که باعث فعال شدن Circuit میشود
resetTimeout: 10000, // زمان تا بازنشانی مجدد
};
// پیادهسازی یک Circuit Breaker برای هر API
async function fetchFromAPI(apiName) {
const apiConfig = config.apis[apiName];
const circuitBreaker = new opossum(() => {
return axios.get(apiConfig.url, {
headers: { Authorization: `Bearer ${apiConfig.token}` },
});
}, breakerOptions);
try {
const response = await circuitBreaker.fire();
return response.data;
} catch (error) {
console.error(`Error fetching data from ${apiName}`, error);
throw new Error(`Service ${apiName} is temporarily unavailable`);
}
}
module.exports = { fetchFromAPI };
توضیحات:
- axios
برای ارسال درخواستهای HTTP استفاده میشود.
- Circuit Breaker
مانع از درخواستهای مکرر به APIهایی میشود که دچار مشکل شدهاند.
3. مدیریت کشگذاری با Redis
برای بهبود عملکرد و جلوگیری از تکرار درخواستها، دادهها در کش (Redis) ذخیره میشوند.
// services/cacheService.js
const redis = require('redis');
const config = require('../config/config');
const client = redis.createClient();
client.on('error', (err) => console.error('Redis Error:', err));
async function getFromCache(key) {
return new Promise((resolve, reject) => {
client.get(key, (err, data) => {
if (err) return reject(err);
if (data) return resolve(JSON.parse(data));
resolve(null);
});
});
}
async function setToCache(key, value, ttl = config.cache.ttl) {
client.setex(key, ttl, JSON.stringify(value));
}
async function invalidateCache(key) {
client.del(key);
}
module.exports = { getFromCache, setToCache, invalidateCache };
توضیحات:
- Redis
برای ذخیرهسازی دادهها و کشگذاری به کار گرفته میشود.
- TTL
تعیین میکند که هر داده تا چه مدت در کش باقی بماند.
4. احراز هویت با JWT
برای امنیت پروژه، از JWT استفاده میشود که کاربران را احراز هویت میکند.
// middleware/authMiddleware.js
const jwt = require('jsonwebtoken');
const config = require('../config/config');
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) return res.sendStatus(401);
jwt.verify(token, config.jwtSecret, (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
}
module.exports = { authenticateToken };
توضیحات:
- authenticateToken
به عنوان یک middleware استفاده میشود تا قبل از پردازش درخواستها، توکن JWT را بررسی کند.
5. تجمیع دادهها
دادهها از APIها جمعآوری و در یک پاسخ واحد به فرانتاند ارسال میشوند:
// aggregator.js
const { fetchFromAPI } = require('./services/apiService');
const { getFromCache, setToCache } = require('./services/cacheService');
async function aggregateData() {
const cacheKey = 'aggregatedData';
const cachedData = await getFromCache(cacheKey);
if (cachedData) {
return cachedData;
}
const [data1, data2] = await Promise.all([
fetchFromAPI('api1'),
fetchFromAPI('api2'),
]);
const aggregatedData = {
source1: data1,
source2: data2,
};
await setToCache(cacheKey, aggregatedData);
return aggregatedData;
}
module.exports = { aggregateData };
توضیحات:
- دادههای APIها از کش بررسی میشوند و در صورت نیاز دوباره درخواست داده ارسال میشود.
6. سرور و مانیتورینگ
برای راهاندازی سرور، از Express و Prometheus برای مانیتورینگ استفاده میکنیم:
// server.js
const express = require('express');
const { getAggregatedData } = require('./controllers/aggregationController');
// اضافه کردن مانیتورینگ Prometheus
const prometheusMiddleware = require('express-prometheus-middleware');
const app = express();
app.use(prometheusMiddleware({
metricsPath: '/metrics',
collectDefaultMetrics: true,
}));
app.get('/aggregated-data', getAggregatedData);
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
توضیحات:
- Prometheus
برای جمعآوری متریکهای عملکردی سرور و APIها استفاده میشود.
- سرور در پورت 3000 اجرا میشود.
7. نصب وابستگیها و اجرای پروژه
برای اجرای این پروژه، ابتدا وابستگیها را نصب کنید:
npm install
سپس سرور را اجرا کنید:
npm start
این پروژه یک Data Aggregation Layer حرفهای با استفاده از Node.js است که قابلیتهای متنوعی مثل مدیریت کش، Circuit Breaker، احراز هویت JWT، و مانیتورینگ را ارائه میدهد. این پروژه به توسعهدهندگان امکان میدهد دادهها را بهصورت بهینه و قابل اعتماد از منابع مختلف جمعآوری کرده و با استفاده از ابزارهای مختلف مانیتورینگ و بهینهسازی، عملکرد آن را افزایش دهند.