Initial commit: Complete Software Architecture course with 11 modules
- 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
This commit is contained in:
commit
15e744da49
107 files changed
+61762
No files matched your search
@@ -0,0 +1,721 @@
|
||||
# Cloud-Native архитектура
|
||||
|
||||
## Навигация
|
||||
- [🏠 Главная страница курса](../../../README.md)
|
||||
- [📚 Модуль 8](../README.md)
|
||||
|
||||
---
|
||||
|
||||
## Принципы Cloud-Native
|
||||
|
||||
### 1. Microservices
|
||||
- Разбиение монолитных приложений на независимые сервисы
|
||||
- Каждый сервис отвечает за одну бизнес-функцию
|
||||
- Независимое развертывание и масштабирование
|
||||
|
||||
```yaml
|
||||
# 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
|
||||
# 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
|
||||
- Управление контейнерами в кластере
|
||||
- Автоматическое масштабирование
|
||||
- Отказоустойчивость
|
||||
|
||||
```yaml
|
||||
# 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
|
||||
|
||||
```yaml
|
||||
# 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
|
||||
|
||||
```javascript
|
||||
// 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 механизмы
|
||||
|
||||
```javascript
|
||||
// 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
|
||||
|
||||
```javascript
|
||||
// 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
|
||||
- Изоляция ресурсов
|
||||
- Предотвращение каскадных сбоев
|
||||
- Независимое масштабирование
|
||||
|
||||
```javascript
|
||||
// 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 модель
|
||||
|
||||
```javascript
|
||||
// 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 функции
|
||||
- Интеграция с различными источниками событий
|
||||
- Асинхронная обработка
|
||||
|
||||
```yaml
|
||||
# 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 для безопасности
|
||||
- Регулярно обновляйте зависимости
|
||||
Reference in new issue
Block a user