Определение: Каждый запрос обрабатывается независимо, сервер не хранит данные между запросами
// Типичное stateless приложение
app.post('/login', (req, res) => {
const { username, password } = req.body;
const isValid = checkCredentials(username, password); // Чистая функция
res.json({ authenticated: isValid });
});
Определение: Сервер сохраняет данные между запросами (сессии, кэш в памяти)
// Stateful пример с сессией
const sessions = new Map();
app.post('/login', (req, res) => {
const { username, password } = req.body;
if (checkCredentials(username, password)) {
const sessionId = uuidv4();
sessions.set(sessionId, { username, lastActive: Date.now() }); // Сохраняем состояние
res.cookie('sessionId', sessionId);
}
});
Характеристика | Cookies | localStorage | sessionStorage |
---|---|---|---|
Объем | 4KB на куку | 5-10MB | 5-10MB |
Срок хранения | Задается явно | Постоянно | Только на время сессии |
Доступ | Сервер + клиент | Только клиент | Только клиент |
Автопересылка | С каждым HTTP-запросом | Нет | Нет |
API | Строковый (document.cookie) | Простой (key-value) | Простой (key-value) |
Безопасность | Уязвимы к CSRF/XSS | Уязвимы к XSS | Уязвимы к XSS |
// Сервис аутентификации
app.post('/verify-token', (req, res) => {
const isValid = jwt.verify(req.body.token, SECRET); // Не требует состояния
res.json({ valid: isValid });
});
const clients = new Map();
wss.on('connection', (ws) => {
const clientId = uuidv4();
clients.set(clientId, ws); // Сохраняем состояние подключения
ws.on('close', () => {
clients.delete(clientId); // Удаляем при отключении
});
});
// Использование Redis для сессий
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: 'keyboard cat'
}));
app.get('/profile', (req, res) => {
// Состояние хранится во внешнем хранилище
res.json(req.session.user);
});
const cache = new NodeCache({ stdTTL: 60 });
app.get('/heavy-route', (req, res) => {
const cached = cache.get(req.url);
if (cached) return res.json(cached);
const data = computeExpensiveData();
cache.set(req.url, data);
res.json(data);
});
// Пример шардирования
const INSTANCE_ID = parseInt(process.env.NODE_APP_INSTANCE) || 0;
app.post('/user-data', (req, res) => {
if (hash(req.user.id) % TOTAL_INSTANCES === INSTANCE_ID) {
// Обрабатываем только "наши" запросы
handleUserData(req.user.id, req.data);
}
});
Stateless - стандартный выбор для большинства Node.js приложений, особенно:
Stateful - специализированное решение для:
Современные практики: