- Added comprehensive course structure with 11 modules - Included theoretical content, practical examples, and tasks - Multi-language code examples (Java, Rust, Node.js, Python) - Detailed analysis of architectural approaches and trade-offs - Complete caching strategies documentation - Architecture examples from real-world systems (Twitter, Netflix, Uber) - Structured navigation and learning path - Ready for educational use
19 KiB
19 KiB
Cloud-Native архитектура
Навигация
Принципы Cloud-Native
1. Microservices
- Разбиение монолитных приложений на независимые сервисы
- Каждый сервис отвечает за одну бизнес-функцию
- Независимое развертывание и масштабирование
# Kubernetes Deployment для микросервиса
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
labels:
app: user-service
spec:
replicas: 3
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: user-service:v1.0.0
ports:
- containerPort: 8080
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: user-service-secrets
key: database-url
- name: REDIS_URL
valueFrom:
configMapKeyRef:
name: user-service-config
key: redis-url
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
2. Containerization
- Упаковка приложений в контейнеры
- Изоляция зависимостей
- Портабельность между средами
# Dockerfile для Node.js приложения
FROM node:18-alpine
# Установка рабочей директории
WORKDIR /app
# Копирование package.json и package-lock.json
COPY package*.json ./
# Установка зависимостей
RUN npm ci --only=production
# Копирование исходного кода
COPY . .
# Создание пользователя для безопасности
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
# Изменение владельца файлов
RUN chown -R nextjs:nodejs /app
USER nextjs
# Открытие порта
EXPOSE 3000
# Команда запуска
CMD ["npm", "start"]
3. Orchestration
- Управление контейнерами в кластере
- Автоматическое масштабирование
- Отказоустойчивость
# Kubernetes Service
apiVersion: v1
kind: Service
metadata:
name: user-service
labels:
app: user-service
spec:
selector:
app: user-service
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP
---
# Kubernetes Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: user-service-ingress
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- api.example.com
secretName: user-service-tls
rules:
- host: api.example.com
http:
paths:
- path: /users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 80
4. API-First Design
- Приоритет API в архитектуре
- Версионирование API
- Документирование через OpenAPI
# OpenAPI Specification
openapi: 3.0.0
info:
title: User Service API
version: 1.0.0
description: API for managing users
servers:
- url: https://api.example.com/v1
description: Production server
paths:
/users:
get:
summary: Get all users
operationId: getUsers
parameters:
- name: limit
in: query
schema:
type: integer
default: 10
- name: offset
in: query
schema:
type: integer
default: 0
responses:
'200':
description: List of users
content:
application/json:
schema:
type: object
properties:
users:
type: array
items:
$ref: '#/components/schemas/User'
total:
type: integer
post:
summary: Create a new user
operationId: createUser
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUserRequest'
responses:
'201':
description: User created
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
User:
type: object
properties:
id:
type: string
format: uuid
email:
type: string
format: email
name:
type: string
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
CreateUserRequest:
type: object
required:
- email
- name
properties:
email:
type: string
format: email
name:
type: string
password:
type: string
minLength: 8
Error:
type: object
properties:
code:
type: string
message:
type: string
details:
type: string
5. Event-Driven Architecture
- Асинхронная обработка событий
- Loose coupling между сервисами
- Event sourcing и CQRS
// Event-driven микросервис на Node.js
const express = require('express');
const { PubSub } = require('@google-cloud/pubsub');
const { v4: uuidv4 } = require('uuid');
const app = express();
const pubsub = new PubSub();
const topic = pubsub.topic('order-events');
app.use(express.json());
// Обработка создания заказа
app.post('/orders', async (req, res) => {
try {
const order = {
id: uuidv4(),
customerId: req.body.customerId,
items: req.body.items,
total: req.body.total,
status: 'created',
createdAt: new Date().toISOString()
};
// Сохранение заказа в базе данных
await saveOrder(order);
// Публикация события
await topic.publishMessage({
data: Buffer.from(JSON.stringify({
type: 'OrderCreated',
orderId: order.id,
customerId: order.customerId,
total: order.total,
timestamp: order.createdAt
}))
});
res.status(201).json(order);
} catch (error) {
console.error('Error creating order:', error);
res.status(500).json({ error: 'Internal server error' });
}
});
// Обработка событий
app.post('/events/order-created', async (req, res) => {
try {
const event = req.body;
if (event.type === 'OrderCreated') {
// Отправка email уведомления
await sendOrderConfirmationEmail(event.customerId, event.orderId);
// Обновление инвентаря
await updateInventory(event.items);
// Обновление статуса заказа
await updateOrderStatus(event.orderId, 'confirmed');
}
res.status(200).json({ status: 'processed' });
} catch (error) {
console.error('Error processing event:', error);
res.status(500).json({ error: 'Internal server error' });
}
});
async function saveOrder(order) {
// Логика сохранения заказа
}
async function sendOrderConfirmationEmail(customerId, orderId) {
// Логика отправки email
}
async function updateInventory(items) {
// Логика обновления инвентаря
}
async function updateOrderStatus(orderId, status) {
// Логика обновления статуса заказа
}
app.listen(3000, () => {
console.log('Order service listening on port 3000');
});
Cloud-Native Patterns
1. Circuit Breaker
- Защита от каскадных сбоев
- Автоматическое восстановление
- Fallback механизмы
// Circuit Breaker implementation
class CircuitBreaker {
constructor(service, options = {}) {
this.service = service;
this.failureThreshold = options.failureThreshold || 5;
this.timeout = options.timeout || 60000;
this.resetTimeout = options.resetTimeout || 30000;
this.state = 'CLOSED';
this.failureCount = 0;
this.lastFailureTime = null;
}
async call(...args) {
if (this.state === 'OPEN') {
if (Date.now() - this.lastFailureTime > this.resetTimeout) {
this.state = 'HALF_OPEN';
} else {
throw new Error('Circuit breaker is OPEN');
}
}
try {
const result = await this.service(...args);
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
onSuccess() {
this.failureCount = 0;
this.state = 'CLOSED';
}
onFailure() {
this.failureCount++;
this.lastFailureTime = Date.now();
if (this.failureCount >= this.failureThreshold) {
this.state = 'OPEN';
}
}
}
// Использование Circuit Breaker
const userService = async (userId) => {
// Вызов внешнего сервиса
const response = await fetch(`https://user-service/api/users/${userId}`);
if (!response.ok) {
throw new Error('User service error');
}
return response.json();
};
const circuitBreaker = new CircuitBreaker(userService, {
failureThreshold: 3,
resetTimeout: 30000
});
// Использование в API endpoint
app.get('/users/:id', async (req, res) => {
try {
const user = await circuitBreaker.call(req.params.id);
res.json(user);
} catch (error) {
res.status(500).json({ error: 'Service unavailable' });
}
});
2. Retry Pattern
- Повторные попытки при временных сбоях
- Exponential backoff
- Jitter для избежания thundering herd
// Retry pattern implementation
class RetryPolicy {
constructor(options = {}) {
this.maxAttempts = options.maxAttempts || 3;
this.baseDelay = options.baseDelay || 1000;
this.maxDelay = options.maxDelay || 10000;
this.backoffMultiplier = options.backoffMultiplier || 2;
this.jitter = options.jitter || true;
}
async execute(operation) {
let lastError;
for (let attempt = 1; attempt <= this.maxAttempts; attempt++) {
try {
return await operation();
} catch (error) {
lastError = error;
if (attempt === this.maxAttempts) {
throw error;
}
const delay = this.calculateDelay(attempt);
await this.sleep(delay);
}
}
throw lastError;
}
calculateDelay(attempt) {
let delay = this.baseDelay * Math.pow(this.backoffMultiplier, attempt - 1);
delay = Math.min(delay, this.maxDelay);
if (this.jitter) {
delay = delay * (0.5 + Math.random() * 0.5);
}
return delay;
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
// Использование Retry Policy
const retryPolicy = new RetryPolicy({
maxAttempts: 3,
baseDelay: 1000,
maxDelay: 5000,
backoffMultiplier: 2,
jitter: true
});
app.get('/external-data', async (req, res) => {
try {
const data = await retryPolicy.execute(async () => {
const response = await fetch('https://external-api.com/data');
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.json();
});
res.json(data);
} catch (error) {
res.status(500).json({ error: 'Failed to fetch external data' });
}
});
3. Bulkhead Pattern
- Изоляция ресурсов
- Предотвращение каскадных сбоев
- Независимое масштабирование
// Bulkhead pattern implementation
class BulkheadPool {
constructor(options = {}) {
this.maxConcurrency = options.maxConcurrency || 10;
this.queue = [];
this.active = 0;
}
async execute(operation) {
return new Promise((resolve, reject) => {
this.queue.push({ operation, resolve, reject });
this.process();
});
}
async process() {
if (this.active >= this.maxConcurrency || this.queue.length === 0) {
return;
}
this.active++;
const { operation, resolve, reject } = this.queue.shift();
try {
const result = await operation();
resolve(result);
} catch (error) {
reject(error);
} finally {
this.active--;
this.process();
}
}
}
// Создание отдельных пулов для разных операций
const databasePool = new BulkheadPool({ maxConcurrency: 5 });
const externalApiPool = new BulkheadPool({ maxConcurrency: 3 });
const fileProcessingPool = new BulkheadPool({ maxConcurrency: 2 });
// Использование в API endpoints
app.post('/orders', async (req, res) => {
try {
// Использование database pool
const order = await databasePool.execute(async () => {
return await saveOrder(req.body);
});
// Использование external API pool
const paymentResult = await externalApiPool.execute(async () => {
return await processPayment(order.id, order.total);
});
res.json({ order, payment: paymentResult });
} catch (error) {
res.status(500).json({ error: 'Order processing failed' });
}
});
Serverless Architecture
1. Function as a Service (FaaS)
- Выполнение кода без управления серверами
- Автоматическое масштабирование
- Pay-per-execution модель
// AWS Lambda function
exports.handler = async (event, context) => {
const { Records } = event;
for (const record of Records) {
if (record.eventSource === 'aws:s3') {
await processS3Event(record);
} else if (record.eventSource === 'aws:sqs') {
await processSQSMessage(record);
}
}
return { statusCode: 200, body: 'Processed successfully' };
};
async function processS3Event(record) {
const bucket = record.s3.bucket.name;
const key = record.s3.object.key;
// Обработка файла из S3
console.log(`Processing file: ${bucket}/${key}`);
// Логика обработки файла
// ...
}
async function processSQSMessage(record) {
const body = JSON.parse(record.body);
// Обработка сообщения из SQS
console.log('Processing message:', body);
// Логика обработки сообщения
// ...
}
2. Event-Driven Serverless
- Обработка событий через serverless функции
- Интеграция с различными источниками событий
- Асинхронная обработка
# Serverless Framework configuration
service: my-serverless-app
provider:
name: aws
runtime: nodejs18.x
region: us-east-1
environment:
DATABASE_URL: ${env:DATABASE_URL}
REDIS_URL: ${env:REDIS_URL}
functions:
processOrder:
handler: handlers/order.handler
events:
- http:
path: /orders
method: post
cors: true
- sqs:
arn: !GetAtt OrderQueue.Arn
batchSize: 10
environment:
QUEUE_URL: !Ref OrderQueue
processPayment:
handler: handlers/payment.handler
events:
- sns:
topic: order-created
filterPolicy:
status: [created]
environment:
PAYMENT_API_URL: ${env:PAYMENT_API_URL}
sendNotification:
handler: handlers/notification.handler
events:
- sns:
topic: order-processed
environment:
EMAIL_SERVICE_URL: ${env:EMAIL_SERVICE_URL}
resources:
Resources:
OrderQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: order-queue
VisibilityTimeoutSeconds: 300
MessageRetentionPeriod: 1209600
OrderTopic:
Type: AWS::SNS::Topic
Properties:
TopicName: order-created
Best Practices
1. Design for Failure
- Предполагайте, что компоненты могут выйти из строя
- Реализуйте graceful degradation
- Используйте health checks и monitoring
2. Stateless Services
- Не храните состояние в сервисах
- Используйте внешние хранилища для состояния
- Обеспечивайте горизонтальное масштабирование
3. Configuration Management
- Выносите конфигурацию в переменные окружения
- Используйте секреты для чувствительных данных
- Применяйте принцип least privilege
4. Monitoring and Observability
- Настройте comprehensive monitoring
- Используйте structured logging
- Реализуйте distributed tracing
5. Security
- Применяйте defense in depth
- Используйте service mesh для безопасности
- Регулярно обновляйте зависимости