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:
Alexander Abakumov committed 2025-09-09 22:08:07 +03:00
commit 15e744da49
107 files changed
+61762

No files matched your search

@@ -0,0 +1,363 @@
# Основы производительности
## Навигация
- [🏠 Главная страница курса](../../../README.md)
- [📚 Модуль 10](../README.md)
---
## Что такое производительность
**Производительность** — это способность системы выполнять задачи за определенное время с использованием доступных ресурсов.
## Метрики производительности
### 1. Throughput (Пропускная способность)
**Определение:** Количество операций, выполняемых за единицу времени.
**Технический пример - Advanced Performance Monitoring System:**
```java
// Advanced Performance Metrics Collector
@Component
public class AdvancedPerformanceMetrics {
private final MeterRegistry meterRegistry;
private final Counter requestCounter;
private final Timer requestTimer;
private final Gauge activeConnections;
private final DistributionSummary responseSize;
private final Counter errorCounter;
public AdvancedPerformanceMetrics(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
// Request metrics
this.requestCounter = Counter.builder("requests.total")
.description("Total number of requests")
.tag("service", "user-service")
.register(meterRegistry);
this.requestTimer = Timer.builder("request.duration")
.description("Request processing time")
.publishPercentiles(0.5, 0.95, 0.99)
.publishPercentileHistogram()
.register(meterRegistry);
// Connection metrics
this.activeConnections = Gauge.builder("connections.active")
.description("Number of active connections")
.register(meterRegistry, this, AdvancedPerformanceMetrics::getActiveConnections);
// Response size metrics
this.responseSize = DistributionSummary.builder("response.size")
.description("Response size in bytes")
.publishPercentiles(0.5, 0.95, 0.99)
.register(meterRegistry);
// Error metrics
this.errorCounter = Counter.builder("errors.total")
.description("Total number of errors")
.register(meterRegistry);
}
public void recordRequest(Duration duration, int responseSizeBytes, boolean isError) {
requestCounter.increment();
requestTimer.record(duration);
this.responseSize.record(responseSizeBytes);
if (isError) {
errorCounter.increment();
}
}
public PerformanceReport generateReport() {
return PerformanceReport.builder()
.throughput(getThroughput())
.averageLatency(getAverageLatency())
.p95Latency(getP95Latency())
.p99Latency(getP99Latency())
.errorRate(getErrorRate())
.activeConnections(getActiveConnections())
.averageResponseSize(getAverageResponseSize())
.timestamp(LocalDateTime.now())
.build();
}
public double getThroughput() {
double totalTime = requestTimer.totalTime(TimeUnit.SECONDS);
return totalTime > 0 ? requestCounter.count() / totalTime : 0;
}
public double getAverageLatency() {
return requestTimer.mean(TimeUnit.MILLISECONDS);
}
public double getP95Latency() {
return requestTimer.percentile(0.95, TimeUnit.MILLISECONDS);
}
public double getP99Latency() {
return requestTimer.percentile(0.99, TimeUnit.MILLISECONDS);
}
public double getErrorRate() {
double totalRequests = requestCounter.count();
return totalRequests > 0 ? (errorCounter.count() / totalRequests) * 100 : 0;
}
private double getActiveConnections() {
return 0; // Placeholder
}
public double getAverageResponseSize() {
return responseSize.mean();
}
}
// Performance Optimization Service
@Service
public class PerformanceOptimizationService {
@Autowired
private AdvancedPerformanceMetrics metrics;
@Autowired
private DatabaseOptimizationService dbOptimizationService;
// Automatic performance optimization
@Scheduled(fixedRate = 60000) // Every minute
public void optimizePerformance() {
PerformanceReport report = metrics.generateReport();
if (needsOptimization(report)) {
log.warn("Performance optimization triggered: {}", report);
if (report.getAverageLatency() > 1000) {
optimizeLatency();
}
if (report.getErrorRate() > 5) {
optimizeErrorHandling();
}
if (report.getThroughput() < 100) {
optimizeThroughput();
}
}
}
private boolean needsOptimization(PerformanceReport report) {
return report.getAverageLatency() > 1000 ||
report.getErrorRate() > 5 ||
report.getThroughput() < 100 ||
report.getP95Latency() > 2000;
}
private void optimizeLatency() {
log.info("Optimizing latency...");
increaseConnectionPoolSize();
enableCompression();
optimizeJVMSettings();
}
private void optimizeErrorHandling() {
log.info("Optimizing error handling...");
enableCircuitBreaker();
enableRetryLogic();
improveErrorLogging();
}
private void optimizeThroughput() {
log.info("Optimizing throughput...");
increaseThreadPoolSize();
enableAsyncProcessing();
optimizeBatchProcessing();
}
private void increaseConnectionPoolSize() {
log.info("Increasing connection pool size");
}
private void enableCompression() {
log.info("Enabling compression");
}
private void optimizeJVMSettings() {
log.info("Optimizing JVM settings");
}
private void enableCircuitBreaker() {
log.info("Enabling circuit breaker");
}
private void enableRetryLogic() {
log.info("Enabling retry logic");
}
private void improveErrorLogging() {
log.info("Improving error logging");
}
private void increaseThreadPoolSize() {
log.info("Increasing thread pool size");
}
private void enableAsyncProcessing() {
log.info("Enabling async processing");
}
private void optimizeBatchProcessing() {
log.info("Optimizing batch processing");
}
}
```
### 2. Latency (Задержка)
**Определение:** Время выполнения одной операции.
```java
// Измерение latency
@Service
public class UserService {
private final Timer requestTimer;
public UserService(MeterRegistry meterRegistry) {
this.requestTimer = Timer.builder("user.service.duration")
.register(meterRegistry);
}
public User getUser(Long id) {
return requestTimer.recordCallable(() -> {
// бизнес-логика
return userRepository.findById(id);
});
}
}
```
### 3. Resource Utilization (Использование ресурсов)
**Определение:** Процент использования доступных ресурсов.
```java
// Мониторинг ресурсов
@Component
public class ResourceMonitor {
private final Gauge cpuUsage;
private final Gauge memoryUsage;
private final Gauge diskUsage;
public ResourceMonitor(MeterRegistry meterRegistry) {
this.cpuUsage = Gauge.builder("system.cpu.usage")
.register(meterRegistry, this, ResourceMonitor::getCpuUsage);
this.memoryUsage = Gauge.builder("system.memory.usage")
.register(meterRegistry, this, ResourceMonitor::getMemoryUsage);
this.diskUsage = Gauge.builder("system.disk.usage")
.register(meterRegistry, this, ResourceMonitor::getDiskUsage);
}
private double getCpuUsage() {
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
return osBean.getProcessCpuLoad();
}
private double getMemoryUsage() {
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
return (double) heapUsage.getUsed() / heapUsage.getMax();
}
private double getDiskUsage() {
File root = new File("/");
long totalSpace = root.getTotalSpace();
long freeSpace = root.getFreeSpace();
return (double) (totalSpace - freeSpace) / totalSpace;
}
}
```
## Производительность по уровням
### 1. Application Level
```java
// Оптимизация на уровне приложения
@Service
public class OptimizedUserService {
@Autowired
private UserRepository userRepository;
@Autowired
private UserCache userCache;
// Оптимизация: кэширование
@Cacheable("users")
public User getUser(Long id) {
return userRepository.findById(id);
}
// Оптимизация: batch операции
public List<User> getUsers(List<Long> ids) {
return userRepository.findByIdIn(ids);
}
// Оптимизация: асинхронная обработка
@Async
public CompletableFuture<Void> processUserAsync(User user) {
// асинхронная обработка
return CompletableFuture.completedFuture(null);
}
}
```
### 2. Database Level
```java
// Оптимизация на уровне базы данных
@Repository
public class OptimizedUserRepository {
// Оптимизация: использование индексов
@Query("SELECT u FROM User u WHERE u.email = :email")
User findByEmail(@Param("email") String email);
// Оптимизация: пагинация
@Query("SELECT u FROM User u")
Page<User> findAllUsers(Pageable pageable);
// Оптимизация: batch операции
@Modifying
@Query("UPDATE User u SET u.lastLogin = :lastLogin WHERE u.id IN :ids")
int updateLastLogin(@Param("ids") List<Long> ids, @Param("lastLogin") LocalDateTime lastLogin);
}
```
### 3. Infrastructure Level
```yaml
# Оптимизация на уровне инфраструктуры
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 3
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: user-service:latest
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
env:
- name: JAVA_OPTS
value: "-Xms512m -Xmx1g -XX:+UseG1GC"
```
@@ -0,0 +1,169 @@
# Профилирование и анализ
## Навигация
- [🏠 Главная страница курса](../../../README.md)
- [📚 Модуль 10](../README.md)
---
## Инструменты профилирования
### 1. JProfiler
```java
// Профилирование с JProfiler
@Service
public class ProfiledUserService {
@Autowired
private UserRepository userRepository;
public User getUser(Long id) {
// JProfiler покажет время выполнения этого метода
return userRepository.findById(id);
}
public List<User> searchUsers(String query) {
// Профилирование покажет узкие места
List<User> users = userRepository.findByNameContaining(query);
// Профилирование покажет время обработки
return users.stream()
.filter(user -> user.isActive())
.collect(Collectors.toList());
}
}
```
### 2. VisualVM
```java
// Мониторинг с VisualVM
@Component
public class PerformanceMonitor {
private final MemoryMXBean memoryBean;
private final ThreadMXBean threadBean;
public PerformanceMonitor() {
this.memoryBean = ManagementFactory.getMemoryMXBean();
this.threadBean = ManagementFactory.getThreadMXBean();
}
@Scheduled(fixedRate = 5000)
public void logPerformanceMetrics() {
// Мониторинг памяти
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
log.info("Heap usage: {} / {}", heapUsage.getUsed(), heapUsage.getMax());
// Мониторинг потоков
int threadCount = threadBean.getThreadCount();
log.info("Thread count: {}", threadCount);
// Мониторинг CPU
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
double cpuUsage = osBean.getProcessCpuLoad();
log.info("CPU usage: {}%", cpuUsage * 100);
}
}
```
### 3. Application Performance Monitoring (APM)
```java
// APM интеграция
@Service
public class APMUserService {
@Autowired
private NewRelic newRelic;
public User getUser(Long id) {
newRelic.addCustomParameter("user.id", id);
try {
User user = userRepository.findById(id);
newRelic.recordMetric("User/Found", 1);
return user;
} catch (Exception e) {
newRelic.recordMetric("User/Error", 1);
newRelic.recordException(e);
throw e;
}
}
public List<User> searchUsers(String query) {
newRelic.addCustomParameter("search.query", query);
List<User> users = userRepository.findByNameContaining(query);
newRelic.recordMetric("User/SearchResults", users.size());
return users;
}
}
```
## Анализ производительности
### 1. Bottleneck Analysis
```java
// Анализ узких мест
@Service
public class BottleneckAnalyzer {
private final Timer databaseTimer;
private final Timer cacheTimer;
private final Timer networkTimer;
public BottleneckAnalyzer(MeterRegistry meterRegistry) {
this.databaseTimer = Timer.builder("database.operation.duration")
.register(meterRegistry);
this.cacheTimer = Timer.builder("cache.operation.duration")
.register(meterRegistry);
this.networkTimer = Timer.builder("network.operation.duration")
.register(meterRegistry);
}
public User getUser(Long id) {
// Анализ времени выполнения каждой операции
User user = databaseTimer.recordCallable(() -> {
return userRepository.findById(id);
});
if (user != null) {
cacheTimer.recordCallable(() -> {
userCache.put(id, user);
});
}
return user;
}
}
```
### 2. Memory Analysis
```java
// Анализ памяти
@Component
public class MemoryAnalyzer {
private final MemoryMXBean memoryBean;
public MemoryAnalyzer() {
this.memoryBean = ManagementFactory.getMemoryMXBean();
}
@Scheduled(fixedRate = 10000)
public void analyzeMemory() {
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
MemoryUsage nonHeapUsage = memoryBean.getNonHeapMemoryUsage();
log.info("Heap: {} / {} ({}%)",
heapUsage.getUsed(),
heapUsage.getMax(),
(heapUsage.getUsed() * 100) / heapUsage.getMax());
log.info("Non-Heap: {} / {} ({}%)",
nonHeapUsage.getUsed(),
nonHeapUsage.getMax(),
(nonHeapUsage.getUsed() * 100) / nonHeapUsage.getMax());
// Анализ утечек памяти
if (heapUsage.getUsed() > heapUsage.getMax() * 0.8) {
log.warn("High memory usage detected!");
}
}
}
```
@@ -0,0 +1,145 @@
# Оптимизация базы данных
## Навигация
- [🏠 Главная страница курса](../../../README.md)
- [📚 Модуль 10](../README.md)
---
## Оптимизация запросов
### 1. Query Optimization
```sql
-- Оптимизация запросов
-- Плохо: медленный запрос
SELECT * FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.created_at > '2023-01-01'
AND o.status = 'COMPLETED';
-- Хорошо: оптимизированный запрос
SELECT u.id, u.name, u.email, COUNT(o.id) as order_count
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.created_at > '2023-01-01'
AND o.status = 'COMPLETED'
GROUP BY u.id, u.name, u.email;
-- Хорошо: использование индексов
CREATE INDEX idx_user_created_at ON users(created_at);
CREATE INDEX idx_order_status ON orders(status);
CREATE INDEX idx_order_user_status ON orders(user_id, status);
```
### 2. Connection Pooling
```java
// Настройка пула соединений
@Configuration
public class DatabaseConfig {
@Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:postgresql://localhost:5432/mydb");
config.setUsername("user");
config.setPassword("password");
// Оптимизация пула соединений
config.setMaximumPoolSize(20);
config.setMinimumIdle(5);
config.setConnectionTimeout(30000);
config.setIdleTimeout(600000);
config.setMaxLifetime(1800000);
config.setLeakDetectionThreshold(60000);
return new HikariDataSource(config);
}
}
```
### 3. Batch Operations
```java
// Batch операции
@Repository
public class OptimizedUserRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
// Batch вставка
public void saveUsers(List<User> users) {
String sql = "INSERT INTO users (name, email, created_at) VALUES (?, ?, ?)";
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
User user = users.get(i);
ps.setString(1, user.getName());
ps.setString(2, user.getEmail());
ps.setTimestamp(3, Timestamp.valueOf(user.getCreatedAt()));
}
@Override
public int getBatchSize() {
return users.size();
}
});
}
// Batch обновление
public void updateUsers(List<User> users) {
String sql = "UPDATE users SET name = ?, email = ? WHERE id = ?";
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
User user = users.get(i);
ps.setString(1, user.getName());
ps.setString(2, user.getEmail());
ps.setLong(3, user.getId());
}
@Override
public int getBatchSize() {
return users.size();
}
});
}
}
```
## Настройка базы данных
### 1. Index Optimization
```sql
-- Оптимизация индексов
-- Анализ использования индексов
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'user@example.com';
-- Создание составных индексов
CREATE INDEX idx_user_email_status ON users(email, status);
-- Создание частичных индексов
CREATE INDEX idx_active_users ON users(email) WHERE status = 'ACTIVE';
-- Создание функциональных индексов
CREATE INDEX idx_user_lower_email ON users(LOWER(email));
```
### 2. Query Plan Analysis
```sql
-- Анализ планов выполнения
EXPLAIN (ANALYZE, BUFFERS)
SELECT u.name, COUNT(o.id) as order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.created_at > '2023-01-01'
GROUP BY u.id, u.name;
-- Анализ статистики
ANALYZE users;
ANALYZE orders;
-- Обновление статистики
UPDATE pg_stat_user_tables
SET n_tup_ins = 0, n_tup_upd = 0, n_tup_del = 0
WHERE relname = 'users';
```
+310
View File
@@ -0,0 +1,310 @@
# Кэширование
## Навигация
- [🏠 Главная страница курса](../../../README.md)
- [📚 Модуль 10](../README.md)
---
## Стратегии кэширования
### 1. Cache-Aside Pattern
**Технический пример - Advanced Multi-Level Caching System:**
```java
// Advanced Cache Management Service
@Service
public class AdvancedCacheService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private CacheMetricsService cacheMetricsService;
// Multi-level caching
private final Map<String, Object> localCache = new ConcurrentHashMap<>();
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
public <T> T get(String cacheKey, Class<T> type, Supplier<T> dataLoader) {
// Level 1: Local cache
T value = getFromLocalCache(cacheKey, type);
if (value != null) {
cacheMetricsService.recordCacheHit(cacheKey, CacheLevel.LOCAL);
return value;
}
// Level 2: Redis cache
value = getFromRedisCache(cacheKey, type);
if (value != null) {
putToLocalCache(cacheKey, value, Duration.ofMinutes(5));
cacheMetricsService.recordCacheHit(cacheKey, CacheLevel.REDIS);
return value;
}
// Level 3: Data source
cacheMetricsService.recordCacheMiss(cacheKey);
value = dataLoader.get();
if (value != null) {
putToLocalCache(cacheKey, value, Duration.ofMinutes(5));
putToRedisCache(cacheKey, value, Duration.ofMinutes(30));
}
return value;
}
public <T> CompletableFuture<T> getAsync(String cacheKey, Class<T> type, Supplier<T> dataLoader) {
return CompletableFuture.supplyAsync(() -> get(cacheKey, type, dataLoader), scheduler);
}
public <T> List<T> getBatch(List<String> cacheKeys, Class<T> type, Function<List<String>, List<T>> dataLoader) {
List<T> results = new ArrayList<>();
List<String> missingKeys = new ArrayList<>();
// Check local cache first
for (String key : cacheKeys) {
T value = getFromLocalCache(key, type);
if (value != null) {
results.add(value);
cacheMetricsService.recordCacheHit(key, CacheLevel.LOCAL);
} else {
missingKeys.add(key);
}
}
if (missingKeys.isEmpty()) {
return results;
}
// Check Redis cache
List<T> redisValues = getFromRedisCacheBatch(missingKeys, type);
List<String> stillMissingKeys = new ArrayList<>();
for (int i = 0; i < missingKeys.size(); i++) {
String key = missingKeys.get(i);
T value = redisValues.get(i);
if (value != null) {
results.add(value);
putToLocalCache(key, value, Duration.ofMinutes(5));
cacheMetricsService.recordCacheHit(key, CacheLevel.REDIS);
} else {
stillMissingKeys.add(key);
}
}
// Load missing data
if (!stillMissingKeys.isEmpty()) {
List<T> loadedData = dataLoader.apply(stillMissingKeys);
for (int i = 0; i < stillMissingKeys.size(); i++) {
String key = stillMissingKeys.get(i);
T value = loadedData.get(i);
if (value != null) {
results.add(value);
putToLocalCache(key, value, Duration.ofMinutes(5));
putToRedisCache(key, value, Duration.ofMinutes(30));
}
cacheMetricsService.recordCacheMiss(key);
}
}
return results;
}
public void put(String cacheKey, Object value) {
putToLocalCache(cacheKey, value, Duration.ofMinutes(5));
putToRedisCache(cacheKey, value, Duration.ofMinutes(30));
cacheMetricsService.recordCachePut(cacheKey);
}
public void evict(String cacheKey) {
localCache.remove(cacheKey);
redisTemplate.delete(cacheKey);
cacheMetricsService.recordCacheEvict(cacheKey);
}
public void evictPattern(String pattern) {
localCache.entrySet().removeIf(entry -> entry.getKey().matches(pattern));
Set<String> keys = redisTemplate.keys(pattern);
if (keys != null && !keys.isEmpty()) {
redisTemplate.delete(keys);
}
cacheMetricsService.recordCacheEvictPattern(pattern);
}
// Cache warming
public void warmCache(List<String> keys, Supplier<List<Object>> dataLoader) {
log.info("Warming cache with {} keys", keys.size());
List<Object> data = dataLoader.get();
for (int i = 0; i < keys.size() && i < data.size(); i++) {
String key = keys.get(i);
Object value = data.get(i);
if (value != null) {
putToLocalCache(key, value, Duration.ofMinutes(5));
putToRedisCache(key, value, Duration.ofMinutes(30));
}
}
log.info("Cache warming completed");
}
private <T> T getFromLocalCache(String key, Class<T> type) {
Object value = localCache.get(key);
return type.cast(value);
}
private <T> T getFromRedisCache(String key, Class<T> type) {
try {
Object value = redisTemplate.opsForValue().get(key);
return type.cast(value);
} catch (Exception e) {
log.warn("Error getting from Redis cache: {}", e.getMessage());
return null;
}
}
private <T> List<T> getFromRedisCacheBatch(List<String> keys, Class<T> type) {
try {
List<Object> values = redisTemplate.opsForValue().multiGet(keys);
return values.stream()
.map(type::cast)
.collect(Collectors.toList());
} catch (Exception e) {
log.warn("Error getting batch from Redis cache: {}", e.getMessage());
return keys.stream().map(k -> (T) null).collect(Collectors.toList());
}
}
private void putToLocalCache(String key, Object value, Duration ttl) {
localCache.put(key, value);
scheduler.schedule(() -> localCache.remove(key), ttl.toMillis(), TimeUnit.MILLISECONDS);
}
private void putToRedisCache(String key, Object value, Duration ttl) {
try {
redisTemplate.opsForValue().set(key, value, ttl);
} catch (Exception e) {
log.warn("Error putting to Redis cache: {}", e.getMessage());
}
}
}
```
### 2. Write-Through Pattern
```java
// Write-Through реализация
@Service
public class WriteThroughUserService {
@Autowired
private UserRepository userRepository;
@Autowired
private RedisTemplate<String, User> redisTemplate;
public void createUser(User user) {
// Сохраняем в БД
user = userRepository.save(user);
// Сохраняем в кэш
String cacheKey = "user:" + user.getId();
redisTemplate.opsForValue().set(cacheKey, user, Duration.ofMinutes(30));
}
public void updateUser(User user) {
// Обновляем БД
user = userRepository.save(user);
// Обновляем кэш
String cacheKey = "user:" + user.getId();
redisTemplate.opsForValue().set(cacheKey, user, Duration.ofMinutes(30));
}
}
```
### 3. Write-Behind Pattern
```java
// Write-Behind реализация
@Service
public class WriteBehindUserService {
@Autowired
private UserRepository userRepository;
@Autowired
private RedisTemplate<String, User> redisTemplate;
@Async
public void createUser(User user) {
// Сохраняем в кэш сразу
String cacheKey = "user:" + user.getId();
redisTemplate.opsForValue().set(cacheKey, user, Duration.ofMinutes(30));
// Сохраняем в БД асинхронно
CompletableFuture.runAsync(() -> {
userRepository.save(user);
});
}
}
```
## Многоуровневое кэширование
### 1. L1 Cache (Application Level)
```java
// L1 кэш (в памяти приложения)
@Service
public class L1CacheUserService {
private final Map<Long, User> localCache = new ConcurrentHashMap<>();
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
@Autowired
private UserRepository userRepository;
public User getUser(Long id) {
return localCache.computeIfAbsent(id, key -> {
User user = userRepository.findById(key);
if (user != null) {
// Автоматическое удаление через 5 минут
scheduler.schedule(() -> localCache.remove(key), 5, TimeUnit.MINUTES);
}
return user;
});
}
}
```
### 2. L2 Cache (Distributed Cache)
```java
// L2 кэш (распределенный)
@Service
public class L2CacheUserService {
@Autowired
private RedisTemplate<String, User> redisTemplate;
@Autowired
private UserRepository userRepository;
public User getUser(Long id) {
String cacheKey = "user:" + id;
User user = redisTemplate.opsForValue().get(cacheKey);
if (user == null) {
user = userRepository.findById(id);
if (user != null) {
redisTemplate.opsForValue().set(cacheKey, user, Duration.ofMinutes(30));
}
}
return user;
}
}
```
@@ -0,0 +1,357 @@
# Оптимизация кода и минификация
## Навигация
- [🏠 Главная страница курса](../../../README.md)
- [📚 Модуль 10](../README.md)
---
## Принципы оптимизации кода
### 1. Минификация JavaScript/TypeScript
**Цели минификации:**
- Уменьшение размера файлов
- Ускорение загрузки страниц
- Снижение трафика
- Улучшение производительности
**Инструменты минификации:**
```javascript
// webpack.config.js - Конфигурация минификации
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
mode: 'production',
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
drop_console: true, // Удаление console.log
drop_debugger: true, // Удаление debugger
pure_funcs: ['console.log'], // Удаление чистых функций
dead_code: true, // Удаление мертвого кода
unused: true, // Удаление неиспользуемых переменных
},
mangle: {
toplevel: true, // Обфускация глобальных переменных
properties: {
regex: /^_/ // Обфускация приватных свойств
}
},
format: {
comments: false // Удаление комментариев
}
},
extractComments: false
}),
new CssMinimizerPlugin({
minimizerOptions: {
preset: [
'default',
{
discardComments: { removeAll: true },
normalizeWhitespace: true,
colormin: true,
minifySelectors: true
}
]
}
})
],
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
common: {
name: 'common',
minChunks: 2,
chunks: 'all',
enforce: true
}
}
}
}
};
```
**Java примеры - Оптимизация сборки:**
```gradle
// build.gradle - Оптимизация Java приложения
plugins {
id 'java'
id 'org.springframework.boot' version '3.0.0'
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
tasks.withType(JavaCompile) {
options.compilerArgs += [
'-parameters', // Сохранение имен параметров
'-Xlint:unchecked', // Предупреждения о небезопасных операциях
'-Xlint:deprecation' // Предупреждения об устаревших API
]
}
// Оптимизация JAR файла
jar {
enabled = false
archiveClassifier = ''
}
bootJar {
enabled = true
archiveClassifier = ''
// Исключение ненужных файлов
exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA'
// Оптимизация манифеста
manifest {
attributes(
'Main-Class': 'com.example.Application',
'Implementation-Version': project.version,
'Built-By': System.getProperty('user.name'),
'Built-Date': new Date().toString()
)
}
}
```
**Rust примеры - Оптимизация компиляции:**
```toml
# Cargo.toml - Оптимизация Rust приложения
[package]
name = "my-app"
version = "0.1.0"
edition = "2021"
[profile.release]
# Максимальная оптимизация
opt-level = 3
# Оптимизация размера
lto = true
# Удаление отладочной информации
debug = false
# Оптимизация кода
codegen-units = 1
# Оптимизация паники
panic = "abort"
# Оптимизация размера
strip = true
[profile.release.package."*"]
# Оптимизация всех зависимостей
opt-level = 3
# Дополнительные флаги компиляции
[build]
rustflags = [
"-C", "target-cpu=native", # Оптимизация под текущий CPU
"-C", "link-arg=-s", # Удаление символов
"-C", "opt-level=3", # Максимальная оптимизация
"-C", "lto=fat", # Link Time Optimization
]
```
**Python примеры - Оптимизация:**
```python
# Оптимизация Python приложения
import sys
from typing import List, Dict, Optional
from dataclasses import dataclass
from functools import lru_cache
import asyncio
import aiohttp
# Оптимизированная структура данных
@dataclass(frozen=True, slots=True) # slots для экономии памяти
class OptimizedUser:
id: int
name: str
email: str
status: int # 1 = active, 0 = inactive
def is_active(self) -> bool:
return self.status == 1
# Кэширование для оптимизации
class OptimizedUserService:
def __init__(self):
self._users_cache: Dict[int, OptimizedUser] = {}
self._session: Optional[aiohttp.ClientSession] = None
async def __aenter__(self):
self._session = aiohttp.ClientSession(
connector=aiohttp.TCPConnector(
limit=100, # Пул соединений
limit_per_host=30,
ttl_dns_cache=300,
use_dns_cache=True,
),
timeout=aiohttp.ClientTimeout(total=30)
)
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
if self._session:
await self._session.close()
# LRU кэш для часто используемых методов
@lru_cache(maxsize=1000)
def get_user_by_id_cached(self, user_id: int) -> Optional[OptimizedUser]:
return self._users_cache.get(user_id)
# Batch операции
async def get_users_batch(self, user_ids: List[int]) -> List[OptimizedUser]:
tasks = [self._fetch_user_async(user_id) for user_id in user_ids]
results = await asyncio.gather(*tasks, return_exceptions=True)
users = []
for result in results:
if isinstance(result, OptimizedUser):
users.append(result)
return users
```
### 2. Оптимизация изображений
```javascript
// webpack.config.js - Оптимизация изображений
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024 // 8kb
}
},
generator: {
filename: 'images/[name].[hash:8][ext]'
}
}
]
},
optimization: {
minimizer: [
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
['gifsicle', { interlaced: true }],
['jpegtran', { progressive: true }],
['optipng', { optimizationLevel: 5 }],
[
'svgo',
{
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: false,
},
},
},
],
},
],
],
},
},
}),
],
},
};
```
### 3. Оптимизация CSS
```css
/* Оптимизированный CSS */
/* Удаление неиспользуемых стилей */
/* Минификация селекторов */
/* Объединение правил */
/* До оптимизации */
.header {
background-color: #ffffff;
padding: 20px;
margin: 0;
border: 1px solid #cccccc;
}
.header .title {
font-size: 24px;
font-weight: bold;
color: #333333;
}
/* После оптимизации */
.header{background:#fff;padding:20px;margin:0;border:1px solid #ccc}
.header .title{font:bold 24px/1 sans-serif;color:#333}
```
### 4. Оптимизация загрузки ресурсов
```html
<!-- Lazy loading изображений -->
<img src="placeholder.jpg"
data-src="large-image.jpg"
loading="lazy"
alt="Описание">
<!-- Preload критических ресурсов -->
<link rel="preload" href="critical.css" as="style">
<link rel="preload" href="app.js" as="script">
<!-- Prefetch для будущих ресурсов -->
<link rel="prefetch" href="next-page.js">
<link rel="prefetch" href="next-page.css">
<!-- DNS prefetch -->
<link rel="dns-prefetch" href="//fonts.googleapis.com">
<link rel="dns-prefetch" href="//cdn.example.com">
```
### 5. Оптимизация базы данных
```sql
-- Оптимизация запросов
-- Использование индексов
CREATE INDEX idx_user_email ON users(email);
CREATE INDEX idx_order_date ON orders(created_at);
-- Оптимизация JOIN
SELECT u.id, u.name, COUNT(o.id) as order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.created_at > '2023-01-01'
GROUP BY u.id, u.name;
-- Партиционирование таблиц
CREATE TABLE orders_2023 PARTITION OF orders
FOR VALUES FROM ('2023-01-01') TO ('2024-01-01');
```
@@ -0,0 +1,102 @@
# Оптимизация сети
## Навигация
- [🏠 Главная страница курса](../../../README.md)
- [📚 Модуль 10](../README.md)
---
## Оптимизация сети
### 1. Connection Pooling
```java
// Оптимизация HTTP соединений
@Configuration
public class HttpClientConfig {
@Bean
public RestTemplate restTemplate() {
HttpComponentsClientHttpRequestFactory factory =
new HttpComponentsClientHttpRequestFactory();
// Настройка пула соединений
PoolingHttpClientConnectionManager connectionManager =
new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(100);
connectionManager.setDefaultMaxPerRoute(20);
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(RequestConfig.custom()
.setConnectTimeout(5000)
.setSocketTimeout(10000)
.build())
.build();
factory.setHttpClient(httpClient);
return new RestTemplate(factory);
}
}
```
### 2. Compression
```java
// Сжатие HTTP ответов
@Configuration
public class CompressionConfig {
@Bean
public FilterRegistrationBean<CompressionFilter> compressionFilter() {
FilterRegistrationBean<CompressionFilter> registration =
new FilterRegistrationBean<>();
registration.setFilter(new CompressionFilter());
registration.addUrlPatterns("/*");
registration.setName("compressionFilter");
registration.setOrder(1);
return registration;
}
}
@Component
public class CompressionFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String acceptEncoding = httpRequest.getHeader("Accept-Encoding");
if (acceptEncoding != null && acceptEncoding.contains("gzip")) {
httpResponse.setHeader("Content-Encoding", "gzip");
GzipResponseWrapper gzipResponse = new GzipResponseWrapper(httpResponse);
chain.doFilter(request, gzipResponse);
gzipResponse.finish();
} else {
chain.doFilter(request, response);
}
}
}
```
### 3. CDN Integration
```java
// Интеграция с CDN
@Service
public class CDNService {
@Value("${cdn.base-url}")
private String cdnBaseUrl;
public String getCDNUrl(String path) {
return cdnBaseUrl + "/" + path;
}
public void uploadToCDN(String path, byte[] content) {
// Загрузка контента в CDN
// Реализация зависит от выбранного CDN провайдера
}
public void invalidateCDNCache(String path) {
// Инвалидация кэша CDN
// Реализация зависит от выбранного CDN провайдера
}
}
```
@@ -0,0 +1,116 @@
# Capacity Planning
## Навигация
- [🏠 Главная страница курса](../../../README.md)
- [📚 Модуль 10](../README.md)
---
## Процесс планирования мощности
### 1. Current Capacity Analysis
```java
// Анализ текущей производительности
@Component
public class CapacityAnalyzer {
private final MeterRegistry meterRegistry;
public CapacityAnalyzer(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
@Scheduled(fixedRate = 60000) // каждую минуту
public void analyzeCapacity() {
// Анализ CPU
double cpuUsage = getCpuUsage();
log.info("CPU usage: {}%", cpuUsage * 100);
// Анализ памяти
double memoryUsage = getMemoryUsage();
log.info("Memory usage: {}%", memoryUsage * 100);
// Анализ пропускной способности
double throughput = getThroughput();
log.info("Throughput: {} RPS", throughput);
// Анализ задержки
double latency = getLatency();
log.info("Latency: {} ms", latency);
// Предупреждения
if (cpuUsage > 0.8) {
log.warn("High CPU usage detected!");
}
if (memoryUsage > 0.8) {
log.warn("High memory usage detected!");
}
}
}
```
### 2. Load Forecasting
```java
// Прогнозирование нагрузки
@Service
public class LoadForecaster {
@Autowired
private MetricsRepository metricsRepository;
public LoadForecast forecastLoad(int days) {
// Получаем исторические данные
List<MetricData> historicalData = metricsRepository
.findByDateRange(LocalDateTime.now().minusDays(30), LocalDateTime.now());
// Анализируем тренды
double growthRate = calculateGrowthRate(historicalData);
// Прогнозируем нагрузку
double currentLoad = getCurrentLoad();
double forecastedLoad = currentLoad * Math.pow(1 + growthRate, days);
return new LoadForecast(forecastedLoad, growthRate, days);
}
private double calculateGrowthRate(List<MetricData> data) {
// Простой расчет темпа роста
if (data.size() < 2) return 0.0;
double firstValue = data.get(0).getValue();
double lastValue = data.get(data.size() - 1).getValue();
return (lastValue - firstValue) / firstValue / data.size();
}
}
```
### 3. Resource Planning
```yaml
# Планирование ресурсов
capacity_planning:
current_capacity:
cpu: "4 cores"
memory: "8 GB"
storage: "100 GB"
network: "1 Gbps"
forecasted_load:
peak_rps: 1000
average_rps: 500
growth_rate: "20% per month"
resource_requirements:
cpu:
current: "80% utilization"
target: "70% utilization"
required: "6 cores"
memory:
current: "75% utilization"
target: "65% utilization"
required: "12 GB"
storage:
current: "60% utilization"
target: "50% utilization"
required: "150 GB"
```
@@ -0,0 +1,174 @@
# Performance Testing
## Навигация
- [🏠 Главная страница курса](../../../README.md)
- [📚 Модуль 10](../README.md)
---
## Типы тестов производительности
### 1. Load Testing
```java
// Load тестирование с JMeter
@Component
public class LoadTestRunner {
public void runLoadTest() {
// Настройка JMeter теста
JMeterEngine engine = new StandardJMeterEngine();
// Загрузка тестового плана
HashTree testPlanTree = new HashTree();
TestPlan testPlan = new TestPlan();
testPlan.setName("User Service Load Test");
// Настройка потока
ThreadGroup threadGroup = new ThreadGroup();
threadGroup.setName("Users");
threadGroup.setNumThreads(100);
threadGroup.setRampUp(60);
threadGroup.setDuration(300); // 5 минут
// Настройка HTTP запроса
HTTPSamplerProxy httpSampler = new HTTPSamplerProxy();
httpSampler.setDomain("localhost");
httpSampler.setPort(8080);
httpSampler.setPath("/api/users");
httpSampler.setMethod("GET");
// Добавление элементов в тест
testPlanTree.add(testPlan);
testPlanTree.add(testPlan, threadGroup);
testPlanTree.add(threadGroup, httpSampler);
// Запуск теста
engine.configure(testPlanTree);
engine.run();
}
}
```
### 2. Stress Testing
```java
// Stress тестирование
@Service
public class StressTestService {
@Autowired
private UserService userService;
public void runStressTest() {
int numberOfThreads = 200;
int requestsPerThread = 1000;
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
CountDownLatch latch = new CountDownLatch(numberOfThreads);
for (int i = 0; i < numberOfThreads; i++) {
executor.submit(() -> {
try {
for (int j = 0; j < requestsPerThread; j++) {
// Выполняем запрос
userService.getUser((long) (Math.random() * 1000));
// Небольшая задержка
Thread.sleep(10);
}
} catch (Exception e) {
log.error("Stress test error", e);
} finally {
latch.countDown();
}
});
}
try {
latch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
executor.shutdown();
}
}
```
### 3. Endurance Testing
```java
// Endurance тестирование
@Component
public class EnduranceTestRunner {
@Autowired
private UserService userService;
@Scheduled(fixedRate = 1000) // каждую секунду
public void runEnduranceTest() {
try {
// Выполняем запрос
userService.getUser(1L);
// Логируем метрики
log.info("Endurance test - request completed");
} catch (Exception e) {
log.error("Endurance test error", e);
}
}
}
```
## Автоматизация тестов производительности
### 1. Automated Performance Tests
```java
// Автоматизированные performance тесты
@SpringBootTest
@TestPropertySource(properties = {
"spring.datasource.url=jdbc:h2:mem:testdb",
"spring.jpa.hibernate.ddl-auto=create-drop"
})
public class PerformanceTestSuite {
@Autowired
private UserService userService;
@Test
public void testUserServicePerformance() {
// Подготовка данных
List<User> users = createTestUsers(1000);
// Измерение времени выполнения
long startTime = System.currentTimeMillis();
for (User user : users) {
userService.createUser(user);
}
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
// Проверка производительности
assertThat(duration).isLessThan(5000); // менее 5 секунд
// Проверка пропускной способности
double throughput = (double) users.size() / duration * 1000;
assertThat(throughput).isGreaterThan(100); // более 100 RPS
}
@Test
public void testDatabaseQueryPerformance() {
// Подготовка данных
createTestUsers(10000);
// Измерение времени выполнения запроса
long startTime = System.currentTimeMillis();
List<User> users = userService.findUsersByName("Test");
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
// Проверка производительности
assertThat(duration).isLessThan(1000); // менее 1 секунды
}
}
```
@@ -0,0 +1,24 @@
# Практические задания
## Навигация
- [🏠 Главная страница курса](../../../README.md)
- [📚 Модуль 10](../README.md)
---
### Задание 1: Профилирование
1. Настройте профилирование приложения
2. Проведите анализ производительности
3. Выявите узкие места
### Задание 2: Оптимизация базы данных
1. Проанализируйте медленные запросы
2. Оптимизируйте индексы
3. Настройте пул соединений
### Задание 3: Performance Testing
1. Создайте load тесты
2. Проведите stress тестирование
3. Проанализируйте результаты
---
@@ -0,0 +1,42 @@
# Практические задания
## Навигация
- [🏠 Главная страница курса](../../../README.md)
- [📚 Модуль 10](../README.md)
---
## Задание 1: Профилирование
1. Настройте профилирование приложения
2. Проведите анализ производительности
3. Выявите узкие места
## Задание 2: Оптимизация базы данных
1. Проанализируйте медленные запросы
2. Оптимизируйте индексы
3. Настройте пул соединений
## Задание 3: Performance Testing
1. Создайте load тесты
2. Проведите stress тестирование
3. Проанализируйте результаты
## Дополнительные ресурсы
### Инструменты
- **Profiling**: JProfiler, VisualVM, YourKit
- **APM**: New Relic, AppDynamics, Datadog
- **Load Testing**: JMeter, Gatling, K6
- **Database**: pgAdmin, MySQL Workbench, MongoDB Compass
### Книги
- "Java Performance" by Scott Oaks
- "High Performance Browser Networking" by Ilya Grigorik
- "Web Performance in Action" by Jeremy Wagner
## Контрольные вопросы
1. Какие метрики производительности наиболее важны?
2. Как определить узкие места в приложении?
3. Какие стратегии кэширования вы знаете?
4. Как оптимизировать базу данных?
5. Что такое capacity planning?