- 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
9.4 KiB
9.4 KiB
Реализация архитектуры
Навигация
Структура проекта
1. Monorepo Structure
ecommerce-platform/
├── services/
│ ├── user-service/
│ │ ├── src/
│ │ ├── Dockerfile
│ │ ├── pom.xml
│ │ └── README.md
│ ├── product-service/
│ ├── order-service/
│ ├── payment-service/
│ └── inventory-service/
├── frontend/
│ ├── customer-app/
│ ├── admin-app/
│ └── shared/
├── infrastructure/
│ ├── kubernetes/
│ ├── terraform/
│ └── docker-compose/
├── docs/
│ ├── architecture/
│ ├── api/
│ └── deployment/
└── scripts/
├── build.sh
├── deploy.sh
└── test.sh
2. Service Implementation
// Order Service Implementation
@RestController
@RequestMapping("/api/orders")
@Validated
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping
public ResponseEntity<OrderResponse> createOrder(
@Valid @RequestBody CreateOrderRequest request) {
Order order = orderService.createOrder(request);
OrderResponse response = OrderMapper.toResponse(order);
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}
@GetMapping("/{id}")
public ResponseEntity<OrderResponse> getOrder(@PathVariable Long id) {
Order order = orderService.getOrder(id);
OrderResponse response = OrderMapper.toResponse(order);
return ResponseEntity.ok(response);
}
@PutMapping("/{id}/status")
public ResponseEntity<OrderResponse> updateOrderStatus(
@PathVariable Long id,
@Valid @RequestBody UpdateOrderStatusRequest request) {
Order order = orderService.updateOrderStatus(id, request.getStatus());
OrderResponse response = OrderMapper.toResponse(order);
return ResponseEntity.ok(response);
}
}
@Service
@Transactional
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private OrderEventPublisher eventPublisher;
@Autowired
private InventoryServiceClient inventoryClient;
@Autowired
private PaymentServiceClient paymentClient;
public Order createOrder(CreateOrderRequest request) {
// Валидация заказа
validateOrderRequest(request);
// Создание заказа
Order order = new Order(request);
order = orderRepository.save(order);
// Резервирование товаров
inventoryClient.reserveItems(order.getId(), request.getItems());
// Публикация события
eventPublisher.publishOrderCreated(order);
return order;
}
public Order updateOrderStatus(Long orderId, OrderStatus status) {
Order order = orderRepository.findById(orderId)
.orElseThrow(() -> new OrderNotFoundException("Order not found: " + orderId));
order.updateStatus(status);
order = orderRepository.save(order);
// Публикация события
eventPublisher.publishOrderStatusUpdated(order);
return order;
}
private void validateOrderRequest(CreateOrderRequest request) {
if (request.getItems().isEmpty()) {
throw new ValidationException("Order must contain at least one item");
}
// Дополнительные проверки...
}
}
Проектирование API
1. REST API Specification
# OpenAPI Specification
openapi: 3.0.0
info:
title: E-commerce Platform API
version: 1.0.0
description: API for e-commerce platform
servers:
- url: https://api.ecommerce.com/v1
description: Production server
paths:
/orders:
post:
summary: Create a new order
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateOrderRequest'
responses:
'201':
description: Order created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/OrderResponse'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/orders/{id}:
get:
summary: Get order by ID
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200':
description: Order retrieved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/OrderResponse'
'404':
description: Order not found
components:
schemas:
CreateOrderRequest:
type: object
required:
- customerId
- items
properties:
customerId:
type: integer
format: int64
items:
type: array
items:
$ref: '#/components/schemas/OrderItem'
shippingAddress:
$ref: '#/components/schemas/Address'
paymentMethod:
$ref: '#/components/schemas/PaymentMethod'
OrderResponse:
type: object
properties:
id:
type: integer
format: int64
customerId:
type: integer
format: int64
status:
type: string
enum: [PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED]
totalAmount:
type: number
format: decimal
items:
type: array
items:
$ref: '#/components/schemas/OrderItem'
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
2. Event Schema
{
"orderCreated": {
"eventType": "OrderCreated",
"version": "1.0",
"timestamp": "2023-12-01T10:00:00Z",
"data": {
"orderId": "12345",
"customerId": "67890",
"items": [
{
"productId": "prod-001",
"quantity": 2,
"price": 29.99
}
],
"totalAmount": 59.98,
"status": "PENDING"
}
},
"orderStatusUpdated": {
"eventType": "OrderStatusUpdated",
"version": "1.0",
"timestamp": "2023-12-01T10:05:00Z",
"data": {
"orderId": "12345",
"oldStatus": "PENDING",
"newStatus": "CONFIRMED",
"updatedBy": "system"
}
}
}
Проектирование базы данных
1. Database Schema
-- Order Service Database Schema
CREATE TABLE orders (
id BIGSERIAL PRIMARY KEY,
customer_id BIGINT NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
total_amount DECIMAL(10,2) NOT NULL,
shipping_address JSONB,
payment_method JSONB,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE order_items (
id BIGSERIAL PRIMARY KEY,
order_id BIGINT NOT NULL REFERENCES orders(id),
product_id VARCHAR(50) NOT NULL,
quantity INTEGER NOT NULL,
unit_price DECIMAL(10,2) NOT NULL,
total_price DECIMAL(10,2) NOT NULL
);
CREATE TABLE order_events (
id BIGSERIAL PRIMARY KEY,
order_id BIGINT NOT NULL,
event_type VARCHAR(50) NOT NULL,
event_data JSONB NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Индексы для оптимизации
CREATE INDEX idx_orders_customer_id ON orders(customer_id);
CREATE INDEX idx_orders_status ON orders(status);
CREATE INDEX idx_orders_created_at ON orders(created_at);
CREATE INDEX idx_order_items_order_id ON order_items(order_id);
CREATE INDEX idx_order_events_order_id ON order_events(order_id);
2. Data Access Layer
@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
List<Order> findByCustomerId(Long customerId);
List<Order> findByStatus(OrderStatus status);
@Query("SELECT o FROM Order o WHERE o.createdAt BETWEEN :startDate AND :endDate")
List<Order> findOrdersByDateRange(
@Param("startDate") LocalDateTime startDate,
@Param("endDate") LocalDateTime endDate
);
@Query("SELECT o FROM Order o WHERE o.customerId = :customerId AND o.status = :status")
List<Order> findByCustomerIdAndStatus(
@Param("customerId") Long customerId,
@Param("status") OrderStatus status
);
}
@Repository
public class OrderEventRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
public void saveEvent(OrderEvent event) {
String sql = "INSERT INTO order_events (order_id, event_type, event_data) VALUES (?, ?, ?)";
jdbcTemplate.update(sql,
event.getOrderId(),
event.getEventType(),
event.getEventData()
);
}
public List<OrderEvent> findEventsByOrderId(Long orderId) {
String sql = "SELECT * FROM order_events WHERE order_id = ? ORDER BY created_at";
return jdbcTemplate.query(sql, new OrderEventRowMapper(), orderId);
}
}