现代软件开发有多种架构模式,每种都有其特定的工作原理、机制和核心技术。下面我将详细论述几种主要的应用程序架构,并给出实例说明。
一、单体架构(Monolithic Architecture)
工作原理和机制
单体架构将所有功能模块(如用户界面、业务逻辑、数据访问等)打包在一个单一的应用程序中,通常作为一个进程运行。
核心特征:
单一代码库:所有功能在同一代码库中
单一部署单元:整个应用作为一个单元部署
集中式数据库:通常使用一个或多个共享数据库
进程内通信:模块间通过函数调用直接通信
运行机制:
text
客户端请求 → Web服务器 → 单体应用(所有模块) → 数据库
核心技术
后端框架:Spring Boot、ASP.NET、Django、Ruby on Rails
前端技术:HTML/CSS/JavaScript,可能包含模板引擎
数据库:MySQL、PostgreSQL、Oracle等
部署方式:将整个应用打包为WAR、JAR或可执行文件
实例:传统电商系统
java
// 典型的单体Spring Boot应用结构
com.example.ecommerce
├── controller # 控制器层
│ ├── UserController.java
│ ├── ProductController.java
│ └── OrderController.java
├── service # 业务逻辑层
│ ├── UserService.java
│ ├── ProductService.java
│ └── OrderService.java
├── repository # 数据访问层
│ ├── UserRepository.java
│ ├── ProductRepository.java
│ └── OrderRepository.java
└── model # 数据模型
├── User.java
├── Product.java
└── Order.java
优缺点
优点:
开发简单,初期生产力高
测试和部署简单
性能较好(进程内调用)
事务管理简单(ACID保证)
缺点:
代码库庞大,维护困难
技术栈单一,无法针对不同模块优化
扩展性差(只能整体扩展)
可靠性差(一个模块故障影响整个系统)
二、分层架构(Layered Architecture)
工作原理和机制
分层架构将系统划分为多个水平层,每层有特定职责,只能与直接相邻的层通信。
典型四层结构:
表示层(Presentation Layer):处理用户界面和用户交互
业务逻辑层(Business Logic Layer):实现业务规则和流程
数据访问层(Data Access Layer):负责数据持久化操作
数据库层(Database Layer):实际的数据存储
通信机制:
text
表示层 → 业务逻辑层 → 数据访问层 → 数据库
↑ ↑ ↑
└─────────┴──────────┘(通常只允许上层调用下层)
核心技术
表示层:React、Angular、Vue.js、Thymeleaf、JSP
业务逻辑层:Spring、.NET Core、EJB
数据访问层:Hibernate、Entity Framework、MyBatis
数据库:各种关系型和非关系型数据库
实例:企业ERP系统
csharp
// C# .NET Core分层示例
// Presentation Layer (Web API)
[ApiController]
[Route(“api/[controller]”)]
public class EmployeeController : ControllerBase
{
private readonly IEmployeeService _employeeService;
public EmployeeController(IEmployeeService employeeService)
{
_employeeService = employeeService; // 依赖注入
}
[HttpGet("{id}")]
public async Task<IActionResult> GetEmployee(int id)
{
var employee = await _employeeService.GetEmployeeByIdAsync(id);
return Ok(employee);
}
}
// Business Logic Layer
public class EmployeeService : IEmployeeService
{
private readonly IEmployeeRepository _employeeRepository;
public EmployeeService(IEmployeeRepository employeeRepository)
{
_employeeRepository = employeeRepository;
}
public async Task<EmployeeDto> GetEmployeeByIdAsync(int id)
{
var employee = await _employeeRepository.GetByIdAsync(id);
// 业务逻辑处理
if (employee.Status == EmployeeStatus.Inactive)
throw new BusinessException("员工已离职");
return MapToDto(employee);
}
}
// Data Access Layer
public class EmployeeRepository : IEmployeeRepository
{
private readonly ApplicationDbContext _context;
public EmployeeRepository(ApplicationDbContext context)
{
_context = context;
}
public async Task<Employee> GetByIdAsync(int id)
{
return await _context.Employees.FindAsync(id);
}
}
// Database Layer (Entity Framework Core)
public class ApplicationDbContext : DbContext
{
public DbSet Employees { get; set; }
}
优缺点
优点:
关注点分离,职责清晰
易于维护和测试(可分层测试)
技术栈可分层选择
团队可分层分工
缺点:
可能产生过度分层,增加复杂性
层间调用可能导致性能问题
修改可能涉及多个层
三、客户端-服务器架构(Client-Server Architecture)
工作原理和机制
客户端-服务器架构将系统分为两个主要部分:客户端(请求服务)和服务器(提供服务)。
核心特征:
服务分离:客户端处理UI和用户交互,服务器处理业务逻辑和数据存储
网络通信:通过标准协议(HTTP、TCP/IP)通信
集中式管理:服务器集中管理数据和业务规则
多客户端支持:同一服务器可服务多个客户端
通信模式:
text
客户端(请求) → 网络 → 服务器(处理) → 数据库
↑ ↓
└────────────(响应)───────────────┘
变体:
两层架构:客户端直接连接数据库服务器
三层架构:客户端 → 应用服务器 → 数据库服务器
N层架构:更细粒度的分层
核心技术
客户端:Web浏览器、桌面应用、移动应用
服务器:Node.js、Java EE、.NET Core、Python Django
通信协议:HTTP/HTTPS、WebSocket、gRPC
数据格式:JSON、XML、Protocol Buffers
实例:在线银行系统
typescript
// 客户端(React + TypeScript)
class BankClient {
async transferMoney(fromAccount: string, toAccount: string, amount: number) {
const response = await fetch(‘https://api.bank.com/transfer’, {
method: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’,
‘Authorization’: Bearer ${this.token}
},
body: JSON.stringify({
fromAccount,
toAccount,
amount,
currency: ‘USD’
})
});
if (!response.ok) {
throw new Error('转账失败');
}
return await response.json();
}
}
// 服务器端(Node.js + Express)
const express = require(‘express’);
const app = express();
const db = require(‘./database’);
app.post(‘/transfer’, authenticateToken, async (req, res) => {
const { fromAccount, toAccount, amount, currency } = req.body;
// 开始数据库事务
const transaction = await db.beginTransaction();
try {
// 检查余额
const balance = await db.query(
'SELECT balance FROM accounts WHERE account_number = ?',
[fromAccount]
);
if (balance < amount) {
throw new Error('余额不足');
}
// 执行转账
await db.query(
'UPDATE accounts SET balance = balance - ? WHERE account_number = ?',
[amount, fromAccount]
);
await db.query(
'UPDATE accounts SET balance = balance + ? WHERE account_number = ?',
[amount, toAccount]
);
// 记录交易
await db.query(
'INSERT INTO transactions (from_account, to_account, amount, currency) VALUES (?, ?, ?, ?)',
[fromAccount, toAccount, amount, currency]
);
// 提交事务
await transaction.commit();
res.json({ success: true, message: '转账成功' });
} catch (error) {
// 回滚事务
await transaction.rollback();
res.status(400).json({ success: false, error: error.message });
}
});
优缺点
优点:
集中式数据管理,安全性高
客户端可轻量化
便于维护和更新(服务器端更新)
支持多用户并发访问
缺点:
服务器单点故障风险
网络依赖性高
服务器可能成为性能瓶颈
客户端功能受限
四、微服务架构(Microservices Architecture)
工作原理和机制
微服务架构将单体应用拆分为一组小型、独立的服务,每个服务运行在自己的进程中,通过轻量级机制通信。
核心原则:
单一职责:每个微服务负责一个特定的业务能力
独立部署:每个服务可独立开发、测试、部署和扩展
去中心化治理:各服务可选择适合的技术栈
智能端点与哑管道:服务包含业务逻辑,通信尽量简单
通信模式:
text
客户端 → API网关 → 服务A → 服务B
↓ ↑
服务C → 服务D
核心技术
服务框架:Spring Cloud、.NET Core with Dapr、Go Micro
API网关:Kong、Zuul、Apigee
服务发现:Consul、Eureka、Zookeeper
通信协议:REST、gRPC、消息队列(RabbitMQ、Kafka)
容器化:Docker、Kubernetes
监控:Prometheus、Grafana、ELK Stack
实例:电商微服务系统
java
// 商品服务(Product Service)
@RestController
@RequestMapping(“/products”)
public class ProductController {
@GetMapping(“/{id}”)
public Product getProduct(@PathVariable String id) {
return productService.getProductById(id);
}
@PostMapping("/{id}/stock")
public void updateStock(@PathVariable String id,
@RequestBody StockUpdateRequest request) {
productService.updateStock(id, request.getQuantity());
// 发布库存更新事件
eventPublisher.publish(new StockUpdatedEvent(id, request.getQuantity()));
}
}
// 订单服务(Order Service)
@Service
public class OrderService {
@Autowired
private ProductClient productClient; // Feign客户端调用商品服务
@Transactional
public Order createOrder(CreateOrderRequest request) {
// 1. 验证商品库存(调用商品服务)
for (OrderItem item : request.getItems()) {
Product product = productClient.getProduct(item.getProductId());
if (product.getStock() < item.getQuantity()) {
throw new InsufficientStockException(product.getId());
}
}
// 2. 创建订单
Order order = new Order(request.getCustomerId(), request.getItems());
orderRepository.save(order);
// 3. 扣减库存(调用商品服务)
for (OrderItem item : request.getItems()) {
productClient.updateStock(item.getProductId(), -item.getQuantity());
}
// 4. 发布订单创建事件
eventPublisher.publish(new OrderCreatedEvent(order));
return order;
}
}
// API网关配置(Spring Cloud Gateway)
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route(“product-service”, r -> r
.path(“/api/products/“)
.uri(“lb://product-service”))
.route(“order-service”, r -> r
.path(”/api/orders/”)
.uri(“lb://order-service”))
.route(“user-service”, r -> r
.path(“/api/users/**”)
.uri(“lb://user-service”))
.build();
}
}
微服务间的通信方式
-
同步通信(REST/gRPC)
java
// 使用Feign客户端声明式REST调用
@FeignClient(name = “product-service”)
public interface ProductClient {
@GetMapping(“/products/{id}”)
Product getProduct(@PathVariable(“id”) String id);@PostMapping(“/products/{id}/stock”)
void updateStock(@PathVariable(“id”) String id,
@RequestParam(“delta”) int delta);
} -
异步通信(消息队列)
java
// 使用Spring Cloud Stream发布事件
@Service
public class EventPublisher {
@Autowired
private StreamBridge streamBridge;public void publishOrderCreatedEvent(Order order) {
OrderCreatedEvent event = new OrderCreatedEvent(
order.getId(),
order.getCustomerId(),
order.getTotalAmount()
);streamBridge.send("orderCreated-out-0", event);}
}
// 其他服务订阅事件
@Component
public class InventoryService {
@StreamListener(“orderCreated-in-0”)
public void handleOrderCreated(OrderCreatedEvent event) {
// 处理订单创建事件,更新库存等
log.info(“处理订单创建事件: {}”, event.getOrderId());
}
}
优缺点
优点:
独立开发部署,提高开发速度
技术栈灵活,可针对服务选择最佳技术
容错性好,单个服务故障不影响整体
易于扩展,可按服务需求独立扩展
缺点:
分布式系统复杂性高
网络延迟和通信故障处理复杂
数据一致性挑战(最终一致性)
运维复杂度高(需要容器编排、服务网格等)
五、事件驱动架构(Event-Driven Architecture)
工作原理和机制
事件驱动架构基于事件的产生、检测、消费和反应,组件之间通过事件进行松耦合通信。
核心概念:
事件生产者(Event Producer):产生事件
事件消费者(Event Consumer):消费并处理事件
事件通道(Event Channel):传输事件的机制
事件处理器(Event Processor):处理事件的逻辑
架构模式:
text
生产者 → 事件总线/消息代理 → 消费者
↑ ↓ ↓
└───────────┴──────────────┘(可能产生新事件)
关键技术
消息代理:Apache Kafka、RabbitMQ、ActiveMQ、AWS SNS/SQS
事件存储:EventStore、Apache Pulsar
流处理:Apache Flink、Apache Storm、Kafka Streams
CQRS/事件溯源:将命令和查询分离,使用事件作为状态变更记录
实例:实时交易系统
java
// 事件定义
public class OrderPlacedEvent {
private String orderId;
private String customerId;
private BigDecimal amount;
private LocalDateTime timestamp;
// getters/setters
}
public class PaymentProcessedEvent {
private String paymentId;
private String orderId;
private PaymentStatus status;
private LocalDateTime timestamp;
// getters/setters
}
// 事件生产者(订单服务)
@Service
public class OrderService {
@Autowired
private KafkaTemplate<String, Object> kafkaTemplate;
public Order placeOrder(CreateOrderRequest request) {
// 创建订单
Order order = createOrder(request);
// 发布订单创建事件
OrderPlacedEvent event = new OrderPlacedEvent();
event.setOrderId(order.getId());
event.setCustomerId(order.getCustomerId());
event.setAmount(order.getTotalAmount());
event.setTimestamp(LocalDateTime.now());
kafkaTemplate.send("order-events", event);
return order;
}
}
// 事件消费者(支付服务)
@Component
public class PaymentService {
@KafkaListener(topics = “order-events”, groupId = “payment-service”)
public void handleOrderPlaced(OrderPlacedEvent event) {
// 处理订单创建事件,发起支付
Payment payment = processPayment(event);
// 发布支付处理事件
PaymentProcessedEvent paymentEvent = new PaymentProcessedEvent();
paymentEvent.setPaymentId(payment.getId());
paymentEvent.setOrderId(event.getOrderId());
paymentEvent.setStatus(payment.getStatus());
paymentEvent.setTimestamp(LocalDateTime.now());
kafkaTemplate.send("payment-events", paymentEvent);
}
}
// 事件消费者(库存服务)
@Component
public class InventoryService {
@KafkaListener(topics = “payment-events”, groupId = “inventory-service”)
public void handlePaymentProcessed(PaymentProcessedEvent event) {
if (event.getStatus() == PaymentStatus.COMPLETED) {
// 支付成功,扣减库存
reduceInventoryForOrder(event.getOrderId());
// 发布库存更新事件
InventoryUpdatedEvent inventoryEvent = new InventoryUpdatedEvent();
// ... 设置事件属性
kafkaTemplate.send("inventory-events", inventoryEvent);
}
}
}
事件溯源(Event Sourcing)示例
java
// 聚合根,使用事件溯源
public class BankAccount {
private String accountId;
private BigDecimal balance;
private List changes = new ArrayList<>();
public BankAccount(String accountId) {
this.accountId = accountId;
this.balance = BigDecimal.ZERO;
}
// 从事件流重建聚合
public BankAccount(String accountId, List<DomainEvent> history) {
this.accountId = accountId;
this.balance = BigDecimal.ZERO;
for (DomainEvent event : history) {
apply(event);
}
}
public void deposit(BigDecimal amount) {
if (amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException("存款金额必须大于0");
}
AccountDepositedEvent event = new AccountDepositedEvent(
accountId, amount, LocalDateTime.now()
);
apply(event);
changes.add(event);
}
private void apply(AccountDepositedEvent event) {
this.balance = this.balance.add(event.getAmount());
}
public List<DomainEvent> getChanges() {
return new ArrayList<>(changes);
}
public void markChangesAsCommitted() {
changes.clear();
}
}
// 事件存储库
@Repository
public class EventStore {
private final Map<String, List> store = new HashMap<>();
public void save(String aggregateId, List<DomainEvent> events) {
store.computeIfAbsent(aggregateId, k -> new ArrayList<>())
.addAll(events);
}
public List<DomainEvent> load(String aggregateId) {
return store.getOrDefault(aggregateId, new ArrayList<>());
}
}
优缺点
优点:
高度解耦,组件独立
高扩展性和响应性
更好的故障隔离
支持异步处理和最终一致性
提供完整的审计日志(事件溯源)
缺点:
系统复杂性高
事件顺序和重复处理挑战
调试和测试困难
需要处理事件丢失和重复
六、六边形架构(Hexagonal Architecture)/端口适配器架构
工作原理和机制
六边形架构的核心思想是将业务逻辑放在中心,通过端口和适配器与外部世界交互。
核心概念:
领域核心(Domain Core):包含业务逻辑和规则,不依赖外部
端口(Ports):定义应用程序与外部世界的接口
适配器(Adapters):实现端口,处理与外部系统的具体交互
架构层次:
text
外部世界
↗ ↖
驱动适配器 driven适配器
(HTTP、CLI等) (数据库、消息等)
↘ ↙
端口(接口)
↓
领域核心
业务逻辑
核心技术
依赖倒置:高层模块不依赖低层模块,都依赖抽象
依赖注入:通过外部注入依赖
领域驱动设计(DDD):与六边形架构天然契合
整洁架构(Clean Architecture):类似理念的不同实现
实例:支付处理系统
java
// 领域核心(不依赖任何外部框架)
// 1. 领域实体
public class Payment {
private PaymentId id;
private Money amount;
private PaymentStatus status;
private LocalDateTime createdAt;
public Payment(PaymentId id, Money amount) {
this.id = id;
this.amount = amount;
this.status = PaymentStatus.PENDING;
this.createdAt = LocalDateTime.now();
}
public void process() {
if (this.status != PaymentStatus.PENDING) {
throw new IllegalStateException("支付状态异常");
}
this.status = PaymentStatus.PROCESSING;
}
public void complete() {
if (this.status != PaymentStatus.PROCESSING) {
throw new IllegalStateException("支付状态异常");
}
this.status = PaymentStatus.COMPLETED;
}
public void fail(String reason) {
this.status = PaymentStatus.FAILED;
// ... 记录失败原因
}
}
// 2. 领域服务接口(端口)
public interface PaymentProcessor {
PaymentResult process(PaymentRequest request);
}
public interface PaymentRepository {
void save(Payment payment);
Payment findById(PaymentId id);
List findByStatus(PaymentStatus status);
}
// 3. 应用服务(用例)
@Service
public class ProcessPaymentUseCase {
private final PaymentProcessor paymentProcessor;
private final PaymentRepository paymentRepository;
private final NotificationService notificationService;
public ProcessPaymentUseCase(PaymentProcessor paymentProcessor,
PaymentRepository paymentRepository,
NotificationService notificationService) {
this.paymentProcessor = paymentProcessor;
this.paymentRepository = paymentRepository;
this.notificationService = notificationService;
}
public PaymentResult execute(PaymentRequest request) {
// 领域逻辑
Payment payment = new Payment(
PaymentId.generate(),
new Money(request.getAmount(), request.getCurrency())
);
payment.process();
paymentRepository.save(payment);
// 调用外部支付网关(通过端口)
PaymentResult result = paymentProcessor.process(request);
if (result.isSuccess()) {
payment.complete();
notificationService.sendPaymentSuccess(payment.getId());
} else {
payment.fail(result.getErrorMessage());
notificationService.sendPaymentFailure(payment.getId(), result.getErrorMessage());
}
paymentRepository.save(payment);
return result;
}
}
// 驱动适配器(HTTP控制器)
@RestController
@RequestMapping(“/payments”)
public class PaymentController {
private final ProcessPaymentUseCase processPaymentUseCase;
public PaymentController(ProcessPaymentUseCase processPaymentUseCase) {
this.processPaymentUseCase = processPaymentUseCase;
}
@PostMapping
public ResponseEntity<PaymentResponse> createPayment(@RequestBody PaymentRequest request) {
PaymentResult result = processPaymentUseCase.execute(request);
if (result.isSuccess()) {
return ResponseEntity.ok(new PaymentResponse(result.getPaymentId(), "SUCCESS"));
} else {
return ResponseEntity.badRequest()
.body(new PaymentResponse(null, result.getErrorMessage()));
}
}
}
// driven适配器(数据库实现)
@Repository
public class JpaPaymentRepository implements PaymentRepository {
private final PaymentJpaRepository jpaRepository;
public JpaPaymentRepository(PaymentJpaRepository jpaRepository) {
this.jpaRepository = jpaRepository;
}
@Override
public void save(Payment payment) {
PaymentEntity entity = PaymentMapper.toEntity(payment);
jpaRepository.save(entity);
}
@Override
public Payment findById(PaymentId id) {
return jpaRepository.findById(id.getValue())
.map(PaymentMapper::toDomain)
.orElse(null);
}
}
// 外部服务适配器(支付网关)
@Component
public class StripePaymentProcessor implements PaymentProcessor {
private final StripeClient stripeClient;
public StripePaymentProcessor(StripeClient stripeClient) {
this.stripeClient = stripeClient;
}
@Override
public PaymentResult process(PaymentRequest request) {
try {
StripeResponse response = stripeClient.charge(
request.getAmount(),
request.getCurrency(),
request.getCardToken()
);
return PaymentResult.success(response.getTransactionId());
} catch (StripeException e) {
return PaymentResult.failure(e.getMessage());
}
}
}
优缺点
优点:
业务逻辑与框架解耦,可测试性强
技术框架更换成本低
清晰的架构边界
支持领域驱动设计
缺点:
初期开发成本较高
需要严格的架构纪律
可能产生过度设计
学习曲线较陡
七、云原生架构(Cloud-Native Architecture)
工作原理和机制
云原生架构充分利用云计算的优势,构建可扩展、弹性和高可用的应用程序。
核心原则(CNCF定义):
容器化:应用打包为容器
动态管理:通过编排系统管理容器
微服务:应用分解为松散耦合的微服务
DevOps:开发与运维协作自动化流程
持续交付:快速、可靠的软件发布
关键技术栈:
text
应用层:微服务、无服务器函数
编排层:Kubernetes、Service Mesh(Istio)
运行时:容器(Docker)、容器运行时(containerd)
基础设施:云平台(AWS、Azure、GCP)、虚拟化
核心技术
容器:Docker、Podman
编排:Kubernetes、Docker Swarm
服务网格:Istio、Linkerd、Consul Connect
CI/CD:Jenkins、GitLab CI、GitHub Actions
监控:Prometheus、Grafana、Jaeger
无服务器:AWS Lambda、Azure Functions、Knative
实例:云原生电商平台
yaml
Kubernetes部署文件
1. 商品服务部署
apiVersion: apps/v1
kind: Deployment
metadata:
name: product-service
spec:
replicas: 3
selector:
matchLabels:
app: product-service
template:
metadata:
labels:
app: product-service
spec:
containers:
- name: product-service
image: myregistry/product-service:1.0.0
ports:
- containerPort: 8080
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: db.host
- name: REDIS_HOST
valueFrom:
secretKeyRef:
name: redis-secret
key: host
resources:
requests:
memory: “256Mi”
cpu: “250m”
limits:
memory: “512Mi”
cpu: “500m”
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
2. 商品服务Service
apiVersion: v1
kind: Service
metadata:
name: product-service
spec:
selector:
app: product-service
ports:
- port: 80
targetPort: 8080
3. 水平自动扩展(HPA)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: product-service-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: product-service
minReplicas: 2
maxReplicas: 10
metrics:
-
type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
java
// 商品服务Spring Boot应用(云原生特性)
@SpringBootApplication
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}@Bean
public MeterRegistryCustomizer metricsCommonTags() {
return registry -> registry.config().commonTags(
“application”, “product-service”,
“region”, System.getenv(“REGION”)
);
}
}
// 健康检查端点
@RestController
public class HealthController {
@GetMapping(“/health”)
public ResponseEntity health() {
Health health = new Health.Builder()
.withDetail(“status”, “UP”)
.withDetail(“timestamp”, Instant.now())
.build();
return ResponseEntity.ok(health);
}
@GetMapping("/readiness")
public ResponseEntity<Health> readiness() {
// 检查外部依赖(数据库、缓存等)
boolean dbReady = checkDatabase();
boolean cacheReady = checkCache();
Health health;
if (dbReady && cacheReady) {
health = new Health.Builder()
.withDetail("status", "READY")
.withDetail("database", "connected")
.withDetail("cache", "connected")
.build();
return ResponseEntity.ok(health);
} else {
health = new Health.Builder()
.withDetail("status", "NOT_READY")
.withDetail("database", dbReady ? "connected" : "disconnected")
.withDetail("cache", cacheReady ? "connected" : "disconnected")
.build();
return ResponseEntity.status(503).body(health);
}
}
}
// 配置管理(使用ConfigMap/Secret)
@Configuration
@RefreshScope // 支持配置热更新
public class AppConfig {
@Value(“${database.url}”)
private String databaseUrl;
@Value("${redis.host}")
private String redisHost;
@Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(databaseUrl);
config.setUsername(System.getenv("DB_USERNAME"));
config.setPassword(System.getenv("DB_PASSWORD"));
return new HikariDataSource(config);
}
}
服务网格示例(Istio)
yaml
Istio VirtualService - 流量管理
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: product-service
spec:
hosts:
- product-service
http: - match:
- headers:
version:
exact: v2
route: - destination:
host: product-service
subset: v2
weight: 100
- headers:
- route:
- destination:
host: product-service
subset: v1
weight: 90 - destination:
host: product-service
subset: v2
weight: 10
- destination:
DestinationRule - 定义子集
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: product-service
spec:
host: product-service
subsets:
- name: v1
labels:
version: v1.0.0 - name: v2
labels:
version: v2.0.0
trafficPolicy:
loadBalancer:
simple: RANDOM
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 10
maxRequestsPerConnection: 10
优缺点
优点:
高弹性,自动扩展和恢复
资源利用率高
部署灵活,多云/混合云支持
服务治理能力强(通过服务网格)
缺点:
技术栈复杂,学习成本高
运维复杂度高
云厂商锁定风险
安全挑战(多租户、网络策略)
八、无服务器架构(Serverless Architecture)
工作原理和机制
无服务器架构中,开发者无需管理服务器基础设施,云提供商动态管理资源的分配和扩展。
核心概念:
函数即服务(FaaS):事件驱动的计算服务
后端即服务(BaaS):云提供的后端服务(数据库、认证等)
按需计费:按实际使用量计费
零管理:无需服务器管理
工作流程:
text
事件触发(HTTP、消息、定时) → 云平台自动扩展函数实例 → 执行代码 → 返回结果
核心技术
FaaS平台:AWS Lambda、Azure Functions、Google Cloud Functions
事件源:API Gateway、消息队列、存储事件、数据库变更
BaaS服务:Firebase、AWS Amplify、Supabase
部署工具:Serverless Framework、AWS SAM、Terraform
实例:图片处理管道
python
AWS Lambda函数 - 图片缩略图生成
import boto3
from PIL import Image
import io
s3 = boto3.client(‘s3’)
def lambda_handler(event, context):
# 从S3事件获取图片信息
bucket = event[‘Records’][0][‘s3’][‘bucket’][‘name’]
key = event[‘Records’][0][‘s3’][‘object’][‘key’]
# 只处理上传到uploads/目录的图片
if not key.startswith('uploads/'):
return {'statusCode': 200, 'body': 'Not an upload'}
# 下载图片
response = s3.get_object(Bucket=bucket, Key=key)
image_data = response['Body'].read()
# 生成缩略图
image = Image.open(io.BytesIO(image_data))
thumbnail_size = (200, 200)
image.thumbnail(thumbnail_size)
# 保存缩略图到内存
buffer = io.BytesIO()
image.save(buffer, format='JPEG')
buffer.seek(0)
# 上传缩略图到S3
thumbnail_key = key.replace('uploads/', 'thumbnails/')
s3.put_object(
Bucket=bucket,
Key=thumbnail_key,
Body=buffer,
ContentType='image/jpeg'
)
# 触发下一个Lambda(图片分析)
lambda_client = boto3.client('lambda')
lambda_client.invoke(
FunctionName='image-analysis-function',
InvocationType='Event', # 异步调用
Payload=json.dumps({
'bucket': bucket,
'key': thumbnail_key
})
)
return {
'statusCode': 200,
'body': json.dumps({
'original': key,
'thumbnail': thumbnail_key
})
}
javascript
// Azure Functions - HTTP触发函数
module.exports = async function (context, req) {
context.log(‘HTTP触发函数处理请求’);
// 从请求中获取数据
const { operation, num1, num2 } = req.body;
let result;
switch (operation) {
case 'add':
result = num1 + num2;
break;
case 'subtract':
result = num1 - num2;
break;
case 'multiply':
result = num1 * num2;
break;
case 'divide':
result = num2 !== 0 ? num1 / num2 : 'Error: 除零错误';
break;
default:
result = 'Error: 未知操作';
}
// 发送响应
context.res = {
status: 200,
body: {
operation,
num1,
num2,
result,
timestamp: new Date().toISOString()
}
};
// 发送事件到事件网格
context.bindings.outputEvent = {
id: uuid.v4(),
eventType: 'calculation.completed',
subject: `/calculations/${operation}`,
eventTime: new Date().toISOString(),
data: {
operation,
num1,
num2,
result
},
dataVersion: '1.0'
};
};
优缺点
优点:
无需管理基础设施
按需计费,成本优化
自动扩展,高可用性
快速部署和迭代
缺点:
冷启动延迟
执行时间和资源限制
调试和监控困难
供应商锁定风险
不适合长时间运行任务
架构选择指南
考虑因素
团队规模与技能:
小团队:单体或分层架构
大团队:微服务或云原生
业务复杂度:
简单业务:单体架构
复杂领域:六边形/整洁架构+DDD
可扩展性需求:
低扩展需求:单体架构
高扩展需求:微服务、云原生
部署和运维能力:
有限运维:单体、无服务器
强大运维:微服务、云原生
开发速度要求:
快速上线:单体、无服务器
长期维护:微服务、整洁架构
架构演进
大多数系统会随着业务发展而演进架构:
text
单体架构 → 分层架构 → 微服务架构 → 云原生架构
↓ ↓ ↓ ↓
快速启动 业务增长 规模扩大 全面云化
混合架构
在实际项目中,经常使用混合架构:
整体微服务:核心业务用微服务,边缘功能用单体
无服务器+容器:事件处理用无服务器,常驻服务用容器
事件驱动+微服务:微服务间通过事件通信
最佳实践建议
从简单开始:不要过度设计,从单体开始验证业务
渐进式演进:随着业务增长逐步重构架构
保持选项开放:使用抽象和接口,降低未来迁移成本
自动化一切:特别是测试、部署和监控
关注业务价值:架构服务于业务,而不是反之
总结
现代软件架构多种多样,每种都有其适用场景。选择架构时需要考虑:
业务需求:复杂度、规模、变化频率
技术约束:团队技能、基础设施、预算
质量属性:性能、可用性、安全性、可维护性
没有"最好"的架构,只有"最适合"的架构。随着业务和技术的发展,架构也需要不断演进和调整。关键是要保持架构的灵活性和可演进性,以应对未来的变化和挑战。
应用程序架构深度解析:从经典到现代
我将系统性地论述各种应用程序架构,涵盖它们的工作原理、核心机制、技术栈,并通过具体实例深入说明。
一、架构分类体系
按架构演进层次:
1. 基础架构模式
├── 单体架构 (Monolithic)
├── 分层架构 (Layered)
├── 客户端-服务器架构 (Client-Server)
└── 插件化架构 (Plugin-based)
2. 分布式架构模式
├── 微服务架构 (Microservices)
├── 服务导向架构 (SOA)
├── 事件驱动架构 (Event-Driven)
└── 无服务器架构 (Serverless)
3. 现代云原生架构
├── 容器化架构 (Container-based)
├── 服务网格架构 (Service Mesh)
├── 函数计算架构 (Function as a Service)
└── 边缘计算架构 (Edge Computing)
4. 高级架构模式
├── 六边形架构 (Hexagonal / Ports & Adapters)
├── 整洁架构 (Clean Architecture)
├── CQRS (Command Query Responsibility Segregation)
└── 事件溯源 (Event Sourcing)
二、详细架构解析
1. 单体架构 (Monolithic Architecture)
工作原理和机制:
┌─────────────────────────────────────┐
│ 单体应用程序 │
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ UI │ │业务 │ │数据 │ │工具 │ │
│ │层 │ │逻辑 │ │访问 │ │模块 │ │
│ └─────┘ └─────┘ └─────┘ └─────┘ │
│ 进程内调用(函数调用) │
└─────────────────┬───────────────────┘
│
┌──────┴──────┐
│ 单一数据库 │
└─────────────┘
核心机制:
- 编译时耦合:所有模块在编译时链接
- 运行时共享:共享内存空间和线程池
- 数据集中:单一数据库或有限几个数据库
- 部署单元:单个可执行文件或包
关键技术栈:
// Spring Boot 单体应用示例
@SpringBootApplication
public class MonolithicApp {
public static void main(String[] args) {
SpringApplication.run(MonolithicApp.class, args);
}
}
// 典型项目结构
src/main/java/com/example/app
├── controller/ # HTTP控制器
│ ├── UserController.java
│ └── ProductController.java
├── service/ # 业务逻辑
│ ├── UserService.java
│ └── ProductService.java
├── repository/ # 数据访问
│ ├── UserRepository.java
│ └── ProductRepository.java
├── model/ # 数据模型
│ ├── User.java
│ └── Product.java
└── config/ # 配置类
实例:小型电商网站
// 单体电商应用的核心组件
@Entity
public class Order {
@Id @GeneratedValue
private Long id;
@ManyToOne
private User user;
@OneToMany(cascade = CascadeType.ALL)
private List<OrderItem> items;
@Embedded
private PaymentInfo paymentInfo;
// 业务逻辑内聚在实体中
public BigDecimal calculateTotal() {
return items.stream()
.map(item -> item.getPrice().multiply(
BigDecimal.valueOf(item.getQuantity())))
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
public void addItem(Product product, int quantity) {
// 业务规则:库存检查
if (product.getStock() < quantity) {
throw new BusinessException("库存不足");
}
items.add(new OrderItem(product, quantity));
product.reduceStock(quantity);
}
}
@Service
@Transactional
public class OrderService {
// 所有功能集中在一个服务中
public Order createOrder(Long userId, List<CartItem> cartItems) {
User user = userRepository.findById(userId).orElseThrow();
Order order = new Order(user);
for (CartItem cartItem : cartItems) {
Product product = productRepository.findById(
cartItem.getProductId()).orElseThrow();
order.addItem(product, cartItem.getQuantity());
}
// 库存扣减、订单创建、支付记录都在同一事务中
orderRepository.save(order);
inventoryService.updateStock(order);
paymentService.processPayment(order);
notificationService.sendOrderConfirmation(order);
return order;
}
}
优点:
- 开发简单,调试方便
- 性能优秀(进程内调用)
- 事务管理简单(ACID保证)
- 部署运维简单
缺点:
- 代码库膨胀,维护困难
- 技术栈锁定,升级困难
- 扩展性差(只能垂直扩展)
- 单点故障风险
2. 分层架构 (Layered Architecture / N-Tier)
工作原理和机制:
┌─────────────────────────────────────────┐
│ 表示层 (Presentation) │
│ Web界面 / API接口 / 移动端 │
├─────────────────────────────────────────┤
│ 业务逻辑层 (Business Logic) │
│ 领域服务 / 应用服务 / 工作流 │
├─────────────────────────────────────────┤
│ 数据访问层 (Data Access) │
│ ORM / DAO / Repository │
├─────────────────────────────────────────┤
│ 持久化层 (Persistence) │
│ 数据库 / 缓存 / 文件系统 │
└─────────────────────────────────────────┘
↓ 严格的分层调用关系 ↓
核心机制:
- 依赖方向:上层依赖下层,下层不感知上层
- 关注点分离:每层有明确职责
- 接口抽象:层间通过接口通信
- 数据转换:DTO在不同层间传递
关键技术栈:
// ASP.NET Core 分层架构示例
// 1. 表现层 (Web API)
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService; // 依赖注入
}
[HttpGet("{id}")]
public async Task<ActionResult<ProductDto>> GetProduct(int id)
{
var product = await _productService.GetProductAsync(id);
return Ok(product);
}
}
// 2. 业务逻辑层
public class ProductService : IProductService
{
private readonly IProductRepository _repository;
private readonly IInventoryService _inventoryService;
public ProductService(
IProductRepository repository,
IInventoryService inventoryService)
{
_repository = repository;
_inventoryService = inventoryService;
}
public async Task<ProductDto> GetProductAsync(int id)
{
var product = await _repository.GetByIdAsync(id);
// 业务规则:检查库存状态
var inventory = await _inventoryService.GetInventoryAsync(id);
product.InStock = inventory.Quantity > 0;
return MapToDto(product); // 转换为DTO
}
}
// 3. 数据访问层
public class ProductRepository : IProductRepository
{
private readonly ApplicationDbContext _context;
public ProductRepository(ApplicationDbContext context)
{
_context = context;
}
public async Task<Product> GetByIdAsync(int id)
{
return await _context.Products
.Include(p => p.Category)
.FirstOrDefaultAsync(p => p.Id == id);
}
}
实例:企业CRM系统
# Python Django 分层CRM系统
# models.py - 数据模型层
class Customer(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
company = models.ForeignKey('Company', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'customers'
ordering = ['-created_at']
# repositories.py - 数据访问层
class CustomerRepository:
def __init__(self, db_session):
self.session = db_session
def find_by_id(self, customer_id):
return self.session.query(Customer).get(customer_id)
def find_by_email(self, email):
return self.session.query(Customer).filter_by(email=email).first()
def save(self, customer):
self.session.add(customer)
self.session.commit()
return customer
# services.py - 业务逻辑层
class CustomerService:
def __init__(self, customer_repo, email_service, validation_service):
self.repo = customer_repo
self.email_service = email_service
self.validator = validation_service
def register_customer(self, customer_data):
# 验证业务规则
self.validator.validate_customer_data(customer_data)
# 检查邮箱是否已存在
existing = self.repo.find_by_email(customer_data['email'])
if existing:
raise BusinessException('邮箱已注册')
# 创建客户
customer = Customer(**customer_data)
saved_customer = self.repo.save(customer)
# 发送欢迎邮件
self.email_service.send_welcome_email(saved_customer.email)
# 记录审计日志
self.audit_service.log_customer_registration(saved_customer)
return saved_customer
# views.py - 表示层
class CustomerViewSet(viewsets.ModelViewSet):
serializer_class = CustomerSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
return Customer.objects.filter(
company=self.request.user.company
)
@action(detail=False, methods=['post'])
def register(self, request):
serializer = CustomerRegistrationSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
# 调用业务逻辑层
customer = customer_service.register_customer(
serializer.validated_data
)
return Response(
CustomerSerializer(customer).data,
status=status.HTTP_201_CREATED
)
优点:
- 清晰的关注点分离
- 易于维护和测试
- 支持团队并行开发
- 技术栈可分层演进
缺点:
- 可能产生过度分层
- 层间调用开销
- 修改可能涉及多层
- 数据转换冗余
3. 微服务架构 (Microservices Architecture)
工作原理和机制:
┌─────────────────────────────────────────────────────┐
│ API Gateway │
│ 路由 / 聚合 / 认证 / 限流 / 监控 │
├───────┬───────┬───────┬───────┬───────┬───────┐
│用户服务│商品服务│订单服务│支付服务│库存服务│物流服务│
│───────│───────│───────│───────│───────│───────│
│独立进程│独立进程│独立进程│独立进程│独立进程│独立进程│
├───────┴───────┴───────┴───────┴───────┴───────┤
│ 网络通信 (REST/gRPC/消息) │
├───────┬───────┬───────┬───────┬───────┬───────┤
│用户数据库│商品数据库│订单数据库│支付数据库│... │
└───────┴───────┴───────┴───────┴───────┴───────┘
核心机制:
- 服务自治:每个服务独立开发部署
- 边界上下文:基于领域驱动设计(DDD)划分
- 去中心化数据:每个服务拥有自己的数据库
- 容错设计:熔断、降级、重试机制
- 服务发现:动态发现和注册服务实例
关键技术栈:
# Docker Compose 微服务编排
version: '3.8'
services:
api-gateway:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- user-service
- product-service
user-service:
build: ./services/user
ports:
- "8081:8080"
environment:
- DB_HOST=user-db
- REDIS_HOST=redis
depends_on:
- user-db
- redis
product-service:
build: ./services/product
ports:
- "8082:8080"
environment:
- DB_HOST=product-db
- KAFKA_HOST=kafka
user-db:
image: postgres:13
environment:
- POSTGRES_DB=userdb
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
redis:
image: redis:6-alpine
kafka:
image: confluentinc/cp-kafka:latest
实例:电商微服务系统
// 订单服务 (Order Service)
@Service
@Slf4j
public class OrderService {
// 使用FeignClient调用其他服务
@FeignClient(name = "product-service")
public interface ProductClient {
@GetMapping("/products/{productId}")
Product getProduct(@PathVariable String productId);
@PostMapping("/products/{productId}/stock")
void reduceStock(@PathVariable String productId,
@RequestParam int quantity);
}
@Autowired
private ProductClient productClient;
@Autowired
private PaymentClient paymentClient;
@Autowired
private OrderRepository orderRepository;
@Autowired
private KafkaTemplate<String, Object> kafkaTemplate;
@Transactional
public Order createOrder(CreateOrderRequest request) {
// 1. 验证商品库存
for (OrderItemRequest item : request.getItems()) {
Product product = productClient.getProduct(item.getProductId());
if (product.getStock() < item.getQuantity()) {
throw new InsufficientStockException(
"商品 " + product.getName() + " 库存不足"
);
}
}
// 2. 创建订单(本地事务)
Order order = Order.builder()
.userId(request.getUserId())
.items(request.getItems().stream()
.map(this::convertToOrderItem)
.collect(Collectors.toList()))
.status(OrderStatus.CREATED)
.build();
orderRepository.save(order);
// 3. 发布订单创建事件(最终一致性)
OrderCreatedEvent event = OrderCreatedEvent.builder()
.orderId(order.getId())
.userId(order.getUserId())
.items(order.getItems())
.timestamp(Instant.now())
.build();
kafkaTemplate.send("order-events", event);
// 4. 异步调用支付服务
CompletableFuture.runAsync(() -> {
try {
paymentClient.initiatePayment(
PaymentRequest.fromOrder(order)
);
} catch (Exception e) {
log.error("支付初始化失败", e);
// 补偿机制:取消订单
cancelOrder(order.getId(), "支付初始化失败");
}
});
return order;
}
// 事件消费者:处理库存扣减
@KafkaListener(topics = "payment-events", groupId = "order-service")
public void handlePaymentCompleted(PaymentCompletedEvent event) {
if (event.getStatus() == PaymentStatus.COMPLETED) {
Order order = orderRepository.findById(event.getOrderId())
.orElseThrow();
// 扣减库存
for (OrderItem item : order.getItems()) {
productClient.reduceStock(
item.getProductId(),
item.getQuantity()
);
}
// 更新订单状态
order.setStatus(OrderStatus.PAID);
orderRepository.save(order);
// 触发发货流程
kafkaTemplate.send("order-events",
new OrderPaidEvent(order.getId()));
}
}
}
服务通信模式:
1. 同步通信 (REST)
// 使用Spring Cloud OpenFeign
@FeignClient(name = "inventory-service")
public interface InventoryClient {
@GetMapping("/inventory/{productId}")
Inventory getInventory(@PathVariable String productId);
@PostMapping("/inventory/{productId}/deduct")
ResponseEntity<Void> deductStock(
@PathVariable String productId,
@RequestBody DeductRequest request
);
}
// 使用RestTemplate
@Service
public class ProductService {
@Autowired
private RestTemplate restTemplate;
public Inventory getInventory(String productId) {
// 服务发现:通过服务名调用
String url = "http://inventory-service/inventory/" + productId;
return restTemplate.getForObject(url, Inventory.class);
}
}
2. 异步通信 (消息队列)
// 使用Spring Cloud Stream (Kafka)
@EnableBinding(OrderEventSource.class)
public class OrderEventPublisher {
public interface OrderEventSource {
String OUTPUT = "orderEventOutput";
@Output(OUTPUT)
MessageChannel output();
}
@Autowired
private OrderEventSource source;
public void publishOrderCreated(Order order) {
OrderCreatedEvent event = new OrderCreatedEvent(
order.getId(),
order.getUserId(),
order.getTotalAmount()
);
source.output().send(MessageBuilder
.withPayload(event)
.setHeader("event-type", "ORDER_CREATED")
.build()
);
}
}
// 事件消费者
@Service
public class InventoryService {
@StreamListener("orderEventInput")
public void handleOrderEvent(OrderCreatedEvent event) {
// 处理订单创建事件,准备发货
prepareShipment(event.getOrderId());
}
}
服务治理组件:
1. 服务发现 (Eureka)
// 服务提供者
@SpringBootApplication
@EnableEurekaClient
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
// 服务消费者
@Service
public class OrderService {
@Autowired
private DiscoveryClient discoveryClient;
public String callProductService() {
List<ServiceInstance> instances =
discoveryClient.getInstances("product-service");
if (instances.isEmpty()) {
throw new ServiceUnavailableException("Product service unavailable");
}
ServiceInstance instance = instances.get(0);
String url = "http://" + instance.getHost() + ":" + instance.getPort();
// 使用负载均衡
return restTemplate.getForObject(url + "/products", String.class);
}
}
2. 配置中心 (Spring Cloud Config)
# config-server 配置
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri: https://github.com/config-repo
search-paths: '{application}'
# 客户端配置
spring:
application:
name: order-service
cloud:
config:
uri: http://localhost:8888
fail-fast: true
# bootstrap.yml
order-service:
database:
url: jdbc:mysql://localhost:3306/orderdb
inventory-service:
url: http://inventory-service
retry:
max-attempts: 3
backoff-delay: 1000
优点:
- 独立开发部署,迭代速度快
- 技术栈灵活,按服务选择最佳技术
- 容错性好,故障隔离
- 可独立扩展,资源利用率高
缺点:
- 分布式系统复杂性
- 网络延迟和通信故障
- 数据一致性挑战
- 运维复杂度高
- 测试和调试困难
4. 事件驱动架构 (Event-Driven Architecture)
工作原理和机制:
┌─────────────────────────────────────────────────┐
│ 事件生产者 (Producers) │
│ 用户服务 │ 订单服务 │ 支付服务 │ ... │
└───────────┴──────────┴──────────┴─────────────┘
↓ 发布事件 ↓
┌─────────────────────────────────────────────────┐
│ 事件总线/消息代理 (Event Bus) │
│ Apache Kafka │ RabbitMQ │ AWS SNS/SQS │
└─────────────────────────────────────────────────┘
↓ 订阅事件 ↓
┌─────────────────────────────────────────────────┐
│ 事件消费者 (Consumers) │
│ 库存服务 │ 物流服务 │ 通知服务 │ 分析服务 │
└─────────────────────────────────────────────────┘
核心机制:
- 事件溯源:状态变更通过事件序列记录
- 事件通知:状态变化时发布事件
- 事件处理:消费者异步处理事件
- 最终一致性:通过事件实现数据一致性
- CQRS模式:命令和查询分离
关键技术栈:
// 事件溯源 (Event Sourcing) 实现
public class BankAccount {
private String accountId;
private BigDecimal balance;
private List<DomainEvent> changes = new ArrayList<>();
// 从事件流重建
public BankAccount(String accountId, List<DomainEvent> history) {
this.accountId = accountId;
this.balance = BigDecimal.ZERO;
replayEvents(history);
}
private void replayEvents(List<DomainEvent> history) {
for (DomainEvent event : history) {
apply(event);
}
}
public void deposit(BigDecimal amount) {
if (amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException("存款金额必须大于0");
}
AccountDepositedEvent event = new AccountDepositedEvent(
accountId, amount, Instant.now()
);
apply(event);
changes.add(event);
}
private void apply(AccountDepositedEvent event) {
this.balance = this.balance.add(event.getAmount());
}
public List<DomainEvent> getUncommittedChanges() {
return new ArrayList<>(changes);
}
public void markChangesAsCommitted() {
changes.clear();
}
}
// 事件存储
@Repository
public class EventStore {
private final Map<String, List<DomainEvent>> store =
new ConcurrentHashMap<>();
public void saveEvents(String aggregateId,
List<DomainEvent> events,
long expectedVersion) {
List<DomainEvent> currentEvents =
store.getOrDefault(aggregateId, new ArrayList<>());
// 乐观锁检查
if (currentEvents.size() != expectedVersion) {
throw new ConcurrencyException("版本冲突");
}
currentEvents.addAll(events);
store.put(aggregateId, currentEvents);
}
public List<DomainEvent> getEvents(String aggregateId) {
return store.getOrDefault(aggregateId, new ArrayList<>());
}
}
实例:库存管理系统
// 事件定义
public abstract class DomainEvent {
private final String aggregateId;
private final Instant occurredOn;
private final int version;
protected DomainEvent(String aggregateId, int version) {
this.aggregateId = aggregateId;
this.version = version;
this.occurredOn = Instant.now();
}
}
public class InventoryItemCreated extends DomainEvent {
private final String sku;
private final String name;
private final int initialQuantity;
// constructor, getters...
}
public class InventoryStockAdjusted extends DomainEvent {
private final String sku;
private final int adjustment;
private final String reason;
// constructor, getters...
}
public class InventoryReserved extends DomainEvent {
private final String sku;
private final int quantity;
private final String orderId;
// constructor, getters...
}
// 聚合根
public class InventoryItem {
private String sku;
private String name;
private int quantityOnHand;
private int quantityReserved;
private List<DomainEvent> changes = new ArrayList<>();
private int version = 0;
// 从事件重建
public InventoryItem(List<DomainEvent> history) {
replayEvents(history);
this.version = history.size();
}
private void replayEvents(List<DomainEvent> history) {
for (DomainEvent event : history) {
applyEvent(event);
}
}
// 创建新商品
public static InventoryItem create(String sku, String name, int initialQuantity) {
InventoryItem item = new InventoryItem();
item.applyChange(new InventoryItemCreated(sku, name, initialQuantity));
return item;
}
// 调整库存
public void adjustStock(int adjustment, String reason) {
if (quantityOnHand + adjustment < 0) {
throw new IllegalStateException("库存不足");
}
applyChange(new InventoryStockAdjusted(
sku, adjustment, reason
));
}
// 预留库存
public void reserveStock(int quantity, String orderId) {
if (quantityOnHand - quantityReserved < quantity) {
throw new IllegalStateException("可用库存不足");
}
applyChange(new InventoryReserved(
sku, quantity, orderId
));
}
private void applyChange(DomainEvent event) {
applyEvent(event);
changes.add(event);
version++;
}
private void applyEvent(DomainEvent event) {
if (event instanceof InventoryItemCreated) {
apply((InventoryItemCreated) event);
} else if (event instanceof InventoryStockAdjusted) {
apply((InventoryStockAdjusted) event);
} else if (event instanceof InventoryReserved) {
apply((InventoryReserved) event);
}
}
private void apply(InventoryItemCreated event) {
this.sku = event.getSku();
this.name = event.getName();
this.quantityOnHand = event.getInitialQuantity();
this.quantityReserved = 0;
}
private void apply(InventoryStockAdjusted event) {
this.quantityOnHand += event.getAdjustment();
}
private void apply(InventoryReserved event) {
this.quantityReserved += event.getQuantity();
}
public List<DomainEvent> getUncommittedChanges() {
return new ArrayList<>(changes);
}
public void markChangesAsCommitted() {
changes.clear();
}
}
CQRS实现:
// 命令端 (写模型)
@Service
@Transactional
public class InventoryCommandService {
@Autowired
private EventStore eventStore;
@Autowired
private EventPublisher eventPublisher;
public void createItem(CreateItemCommand command) {
// 验证业务规则
validateCommand(command);
// 创建事件
InventoryItemCreated event = new InventoryItemCreated(
UUID.randomUUID().toString(),
command.getSku(),
command.getName(),
command.getInitialQuantity()
);
// 保存事件
eventStore.saveEvents(event.getAggregateId(),
Collections.singletonList(event), 0);
// 发布事件
eventPublisher.publish(event);
}
public void adjustStock(AdjustStockCommand command) {
// 获取当前事件流
List<DomainEvent> events = eventStore.getEvents(
command.getSku());
// 重建聚合
InventoryItem item = new InventoryItem(events);
// 执行业务操作
item.adjustStock(command.getAdjustment(), command.getReason());
// 保存新事件
eventStore.saveEvents(
command.getSku(),
item.getUncommittedChanges(),
events.size()
);
// 发布事件
for (DomainEvent event : item.getUncommittedChanges()) {
eventPublisher.publish(event);
}
item.markChangesAsCommitted();
}
}
// 查询端 (读模型)
@Service
public class InventoryQueryService {
@Autowired
private InventoryReadRepository readRepository;
public InventoryItemDTO getItem(String sku) {
return readRepository.findBySku(sku)
.orElseThrow(() -> new NotFoundException("商品不存在"));
}
public List<InventoryItemDTO> searchItems(String keyword) {
return readRepository.search(keyword);
}
public InventorySummaryDTO getSummary() {
return readRepository.getSummary();
}
}
// 事件处理器 (更新读模型)
@Component
public class InventoryReadModelUpdater {
@Autowired
private InventoryReadRepository readRepository;
@EventListener
public void handle(InventoryItemCreated event) {
InventoryItemDTO dto = new InventoryItemDTO();
dto.setSku(event.getSku());
dto.setName(event.getName());
dto.setQuantityOnHand(event.getInitialQuantity());
dto.setQuantityReserved(0);
dto.setVersion(1);
readRepository.save(dto);
}
@EventListener
public void handle(InventoryStockAdjusted event) {
InventoryItemDTO dto = readRepository.findBySku(event.getSku())
.orElseThrow();
dto.setQuantityOnHand(
dto.getQuantityOnHand() + event.getAdjustment()
);
dto.setVersion(dto.getVersion() + 1);
readRepository.save(dto);
}
@EventListener
public void handle(InventoryReserved event) {
InventoryItemDTO dto = readRepository.findBySku(event.getSku())
.orElseThrow();
dto.setQuantityReserved(
dto.getQuantityReserved() + event.getQuantity()
);
dto.setVersion(dto.getVersion() + 1);
readRepository.save(dto);
}
}
优点:
- 高度解耦,服务独立演化
- 高扩展性和响应性
- 完整的审计日志
- 支持复杂业务工作流
- 更好的故障隔离
缺点:
- 事件顺序和重复处理挑战
- 最终一致性带来的复杂性
- 调试和测试困难
- 需要处理事件丢失和重复
- 学习曲线陡峭
5. 六边形架构 (Hexagonal Architecture / Ports & Adapters)
工作原理和机制:
外部世界
↗ ↖
┌─────────────────────────────────────────┐
│ 驱动适配器 (Driving Adapters) │
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │HTTP │ │CLI │ │消息 │ │Web │ │
│ │控制器│ │命令 │ │队列 │ │Socket│ │
│ └─────┘ └─────┘ └─────┘ └─────┘ │
├─────────────────────────────────────────┤
│ 应用程序核心 │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 领域模型 │ │ 应用服务 │ │
│ │ (Entities) │ │ (Use Cases) │ │
│ └─────────────┘ └─────────────┘ │
├─────────────────────────────────────────┤
│ 被驱动适配器 (Driven Adapters) │
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │数据 │ │外部 │ │邮件 │ │推送 │ │
│ │库 │ │API │ │服务 │ │服务 │ │
│ └─────┘ └─────┘ └─────┘ └─────┘ │
└─────────────────────────────────────────┘
↘ ↙
基础设施
核心机制:
- 依赖倒置:核心不依赖外部,外部依赖核心
- 端口定义:核心定义接口(端口)
- 适配器实现:外部实现端口接口
- 测试友好:核心可独立测试
关键技术栈:
// 六边形架构完整示例:支付处理系统
// 1. 领域模型 (Domain Model)
// ----- 值对象 -----
public class Money {
private final BigDecimal amount;
private final Currency currency;
public Money(BigDecimal amount, Currency currency) {
this.amount = amount.setScale(2, RoundingMode.HALF_EVEN);
this.currency = currency;
}
public Money add(Money other) {
if (!this.currency.equals(other.currency)) {
throw new IllegalArgumentException("货币类型不匹配");
}
return new Money(this.amount.add(other.amount), this.currency);
}
// 不可变对象,只有getter
public BigDecimal getAmount() { return amount; }
public Currency getCurrency() { return currency; }
}
// ----- 实体 -----
public class Payment {
private PaymentId id;
private Money amount;
private PaymentStatus status;
private CustomerId customerId;
private Instant createdAt;
private Instant updatedAt;
private Payment() {} // 供ORM使用
public Payment(PaymentId id, Money amount, CustomerId customerId) {
this.id = id;
this.amount = amount;
this.customerId = customerId;
this.status = PaymentStatus.PENDING;
this.createdAt = Instant.now();
this.updatedAt = this.createdAt;
}
// 领域行为
public void process() {
if (this.status != PaymentStatus.PENDING) {
throw new IllegalStateException("支付状态异常");
}
this.status = PaymentStatus.PROCESSING;
this.updatedAt = Instant.now();
}
public void complete() {
if (this.status != PaymentStatus.PROCESSING) {
throw new IllegalStateException("支付状态异常");
}
this.status = PaymentStatus.COMPLETED;
this.updatedAt = Instant.now();
}
public void fail(String reason) {
this.status = PaymentStatus.FAILED;
this.updatedAt = Instant.now();
// 可添加失败原因字段
}
// 只有getter,通过领域方法修改状态
public PaymentId getId() { return id; }
public Money getAmount() { return amount; }
public PaymentStatus getStatus() { return status; }
}
// 2. 端口定义 (Ports - Interfaces)
// ----- 输入端口 (由外部调用) -----
public interface ProcessPaymentUseCase {
PaymentResult processPayment(ProcessPaymentCommand command);
}
public interface GetPaymentStatusUseCase {
PaymentStatus getPaymentStatus(PaymentId paymentId);
}
// ----- 输出端口 (由核心调用) -----
public interface PaymentGateway {
GatewayResponse charge(Money amount, PaymentMethod paymentMethod);
GatewayResponse refund(PaymentId paymentId, Money amount);
}
public interface PaymentRepository {
void save(Payment payment);
Payment findById(PaymentId id);
List<Payment> findByCustomerId(CustomerId customerId);
}
public interface NotificationService {
void sendPaymentSuccess(Payment payment);
void sendPaymentFailure(Payment payment, String reason);
}
// 3. 应用服务 (Application Services - Use Cases)
@Service
@Transactional
public class ProcessPaymentService implements ProcessPaymentUseCase {
private final PaymentGateway paymentGateway;
private final PaymentRepository paymentRepository;
private final NotificationService notificationService;
private final FraudDetectionService fraudDetectionService;
// 依赖注入(通过构造函数)
public ProcessPaymentService(
PaymentGateway paymentGateway,
PaymentRepository paymentRepository,
NotificationService notificationService,
FraudDetectionService fraudDetectionService) {
this.paymentGateway = paymentGateway;
this.paymentRepository = paymentRepository;
this.notificationService = notificationService;
this.fraudDetectionService = fraudDetectionService;
}
@Override
public PaymentResult processPayment(ProcessPaymentCommand command) {
// 1. 验证命令
validateCommand(command);
// 2. 创建支付实体
Payment payment = new Payment(
PaymentId.generate(),
new Money(command.getAmount(), command.getCurrency()),
command.getCustomerId()
);
// 3. 欺诈检测
FraudCheckResult fraudResult = fraudDetectionService.check(
command.getCustomerId(),
command.getAmount(),
command.getPaymentMethod()
);
if (fraudResult.isSuspicious()) {
payment.fail("欺诈检测失败: " + fraudResult.getReason());
paymentRepository.save(payment);
return PaymentResult.failed("支付被拒绝: 欺诈检测失败");
}
// 4. 处理支付
payment.process();
paymentRepository.save(payment);
try {
// 5. 调用支付网关
GatewayResponse response = paymentGateway.charge(
payment.getAmount(),
command.getPaymentMethod()
);
if (response.isSuccess()) {
payment.complete();
paymentRepository.save(payment);
notificationService.sendPaymentSuccess(payment);
return PaymentResult.success(
payment.getId(),
response.getTransactionId()
);
} else {
payment.fail(response.getErrorMessage());
paymentRepository.save(payment);
notificationService.sendPaymentFailure(
payment, response.getErrorMessage()
);
return PaymentResult.failed(response.getErrorMessage());
}
} catch (Exception e) {
payment.fail("支付网关异常: " + e.getMessage());
paymentRepository.save(payment);
return PaymentResult.failed("支付处理异常: " + e.getMessage());
}
}
private void validateCommand(ProcessPaymentCommand command) {
if (command.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException("支付金额必须大于0");
}
if (command.getCustomerId() == null) {
throw new IllegalArgumentException("客户ID不能为空");
}
if (command.getPaymentMethod() == null) {
throw new IllegalArgumentException("支付方式不能为空");
}
}
}
// 4. 驱动适配器 (Driving Adapters - HTTP Controllers)
@RestController
@RequestMapping("/api/payments")
public class PaymentController {
private final ProcessPaymentUseCase processPaymentUseCase;
private final GetPaymentStatusUseCase getPaymentStatusUseCase;
public PaymentController(
ProcessPaymentUseCase processPaymentUseCase,
GetPaymentStatusUseCase getPaymentStatusUseCase) {
this.processPaymentUseCase = processPaymentUseCase;
this.getPaymentStatusUseCase = getPaymentStatusUseCase;
}
@PostMapping
public ResponseEntity<PaymentResponse> createPayment(
@RequestBody @Valid CreatePaymentRequest request) {
ProcessPaymentCommand command = ProcessPaymentCommand.builder()
.customerId(new CustomerId(request.getCustomerId()))
.amount(request.getAmount())
.currency(Currency.getInstance(request.getCurrency()))
.paymentMethod(request.getPaymentMethod())
.build();
PaymentResult result = processPaymentUseCase.processPayment(command);
if (result.isSuccess()) {
PaymentResponse response = PaymentResponse.builder()
.paymentId(result.getPaymentId().getValue())
.transactionId(result.getTransactionId())
.status("SUCCESS")
.message("支付成功")
.build();
return ResponseEntity.ok(response);
} else {
PaymentResponse response = PaymentResponse.builder()
.status("FAILED")
.message(result.getErrorMessage())
.build();
return ResponseEntity.badRequest().body(response);
}
}
@GetMapping("/{paymentId}/status")
public ResponseEntity<PaymentStatusResponse> getPaymentStatus(
@PathVariable String paymentId) {
PaymentStatus status = getPaymentStatusUseCase.getPaymentStatus(
new PaymentId(paymentId)
);
PaymentStatusResponse response = PaymentStatusResponse.builder()
.paymentId(paymentId)
.status(status.toString())
.build();
return ResponseEntity.ok(response);
}
}
// 5. 被驱动适配器 (Driven Adapters)
// ----- 支付网关适配器 -----
@Component
public class StripePaymentGateway implements PaymentGateway {
private final StripeClient stripeClient;
private final CircuitBreaker circuitBreaker;
public StripePaymentGateway(StripeClient stripeClient) {
this.stripeClient = stripeClient;
this.circuitBreaker = CircuitBreaker.ofDefaults("stripe");
}
@Override
public GatewayResponse charge(Money amount, PaymentMethod paymentMethod) {
return circuitBreaker.executeSupplier(() -> {
try {
StripeChargeRequest request = StripeChargeRequest.builder()
.amount(amount.getAmount().multiply(BigDecimal.valueOf(100)).longValue()) // 转换为分
.currency(amount.getCurrency().getCurrencyCode())
.source(paymentMethod.getToken())
.description("Payment from customer")
.build();
StripeChargeResponse response = stripeClient.charge(request);
return GatewayResponse.success(
response.getTransactionId(),
response.getReceiptUrl()
);
} catch (StripeException e) {
return GatewayResponse.failed(
"Stripe支付失败: " + e.getMessage()
);
}
});
}
@Override
public GatewayResponse refund(PaymentId paymentId, Money amount) {
// 实现退款逻辑
return circuitBreaker.executeSupplier(() -> {
try {
StripeRefundResponse response = stripeClient.refund(
paymentId.getValue(),
amount.getAmount().multiply(BigDecimal.valueOf(100)).longValue()
);
return GatewayResponse.success(
response.getRefundId(),
"退款成功"
);
} catch (StripeException e) {
return GatewayResponse.failed(
"Stripe退款失败: " + e.getMessage()
);
}
});
}
}
// ----- 数据库适配器 -----
@Repository
public class JpaPaymentRepository implements PaymentRepository {
private final PaymentJpaRepository jpaRepository;
private final PaymentMapper mapper;
public JpaPaymentRepository(PaymentJpaRepository jpaRepository,
PaymentMapper mapper) {
this.jpaRepository = jpaRepository;
this.mapper = mapper;
}
@Override
public void save(Payment payment) {
PaymentEntity entity = mapper.toEntity(payment);
jpaRepository.save(entity);
}
@Override
public Payment findById(PaymentId id) {
return jpaRepository.findById(id.getValue())
.map(mapper::toDomain)
.orElse(null);
}
@Override
public List<Payment> findByCustomerId(CustomerId customerId) {
return jpaRepository.findByCustomerId(customerId.getValue())
.stream()
.map(mapper::toDomain)
.collect(Collectors.toList());
}
}
// 6. 依赖配置
@Configuration
public class PaymentConfig {
@Bean
public ProcessPaymentUseCase processPaymentUseCase(
PaymentGateway paymentGateway,
PaymentRepository paymentRepository,
NotificationService notificationService,
FraudDetectionService fraudDetectionService) {
return new ProcessPaymentService(
paymentGateway,
paymentRepository,
notificationService,
fraudDetectionService
);
}
@Bean
public PaymentGateway paymentGateway(StripeClient stripeClient) {
return new StripePaymentGateway(stripeClient);
}
@Bean
public PaymentRepository paymentRepository(
PaymentJpaRepository jpaRepository,
PaymentMapper mapper) {
return new JpaPaymentRepository(jpaRepository, mapper);
}
}
// 7. 测试(核心逻辑可独立测试)
@ExtendWith(MockitoExtension.class)
class ProcessPaymentServiceTest {
@Mock
private PaymentGateway paymentGateway;
@Mock
private PaymentRepository paymentRepository;
@Mock
private NotificationService notificationService;
@Mock
private FraudDetectionService fraudDetectionService;
@InjectMocks
private ProcessPaymentService processPaymentService;
@Test
void shouldProcessPaymentSuccessfully() {
// Given
ProcessPaymentCommand command = ProcessPaymentCommand.builder()
.customerId(new CustomerId("cust-123"))
.amount(new BigDecimal("100.00"))
.currency(Currency.getInstance("USD"))
.paymentMethod(PaymentMethod.creditCard("tok_visa"))
.build();
when(fraudDetectionService.check(any(), any(), any()))
.thenReturn(FraudCheckResult.ok());
when(paymentGateway.charge(any(), any()))
.thenReturn(GatewayResponse.success("txn_123", "receipt-url"));
// When
PaymentResult result = processPaymentService.processPayment(command);
// Then
assertTrue(result.isSuccess());
assertNotNull(result.getPaymentId());
assertEquals("txn_123", result.getTransactionId());
verify(paymentRepository, times(2)).save(any(Payment.class));
verify(notificationService).sendPaymentSuccess(any(Payment.class));
}
@Test
void shouldFailWhenFraudDetected() {
// Given
ProcessPaymentCommand command = ProcessPaymentCommand.builder()
.customerId(new CustomerId("cust-123"))
.amount(new BigDecimal("10000.00"))
.currency(Currency.getInstance("USD"))
.paymentMethod(PaymentMethod.creditCard("tok_visa"))
.build();
when(fraudDetectionService.check(any(), any(), any()))
.thenReturn(FraudCheckResult.suspicious("异常大额交易"));
// When
PaymentResult result = processPaymentService.processPayment(command);
// Then
assertFalse(result.isSuccess());
assertTrue(result.getErrorMessage().contains("欺诈检测失败"));
verify(paymentRepository, times(1)).save(any(Payment.class));
verify(paymentGateway, never()).charge(any(), any());
}
}
优点:
- 业务逻辑与框架完全解耦
- 极高的可测试性
- 框架更换成本低
- 清晰的架构边界
- 支持领域驱动设计
缺点:
- 初期开发成本较高
- 需要严格的架构纪律
- 可能产生过度设计
- 学习曲线陡峭
- 需要更多接口和映射代码
6. 云原生架构 (Cloud-Native Architecture)
工作原理和机制:
┌─────────────────────────────────────────────────┐
│ 应用层 (Applications) │
│ 微服务 │ 无服务器函数 │ 事件处理 │
├─────────────────────────────────────────────────┤
│ 服务网格层 (Service Mesh) │
│ 流量管理 │ 安全 │ 可观测性 │ 故障恢复 │
├─────────────────────────────────────────────────┤
│ 容器编排层 (Orchestration) │
│ Kubernetes │ Docker Swarm │ 自动扩展 │
├─────────────────────────────────────────────────┤
│ 容器运行时层 (Container Runtime) │
│ Docker │ containerd │ CRI-O │
├─────────────────────────────────────────────────┤
│ 基础设施层 (Infrastructure) │
│ 虚拟机 │ 物理机 │ 云服务 (AWS/Azure/GCP) │
└─────────────────────────────────────────────────┘
核心机制:
- 不可变基础设施:通过容器镜像部署
- 声明式配置:使用YAML/JSON定义期望状态
- 自动化运维:自动化部署、扩展、修复
- 可观测性:日志、指标、追踪三位一体
- 混沌工程:主动注入故障测试系统韧性
关键技术栈:
# Kubernetes部署清单示例
# 1. Deployment - 定义应用部署
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
namespace: production
labels:
app: user-service
version: v1.2.0
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
version: v1.2.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
prometheus.io/path: "/metrics"
spec:
containers:
- name: user-service
image: registry.example.com/user-service:v1.2.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: http
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: database.host
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
startupProbe:
httpGet:
path: /health/startup
port: 8080
failureThreshold: 30
periodSeconds: 10
securityContext:
runAsNonRoot: true
runAsUser: 1000
readOnlyRootFilesystem: true
volumeMounts:
- name: config-volume
mountPath: /app/config
readOnly: true
volumes:
- name: config-volume
configMap:
name: app-config
nodeSelector:
node-type: application
tolerations:
- key: "dedicated"
operator: "Equal"
value: "app"
effect: "NoSchedule"
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- user-service
topologyKey: kubernetes.io/hostname
---
# 2. Service - 定义网络访问
apiVersion: v1
kind: Service
metadata:
name: user-service
spec:
selector:
app: user-service
ports:
- port: 80
targetPort: 8080
name: http
- port: 443
targetPort: 8443
name: https
type: ClusterIP
---
# 3. HorizontalPodAutoscaler - 自动扩展
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: user-service-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: user-service
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: 100
behavior:
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Pods
value: 4
periodSeconds: 60
- type: Percent
value: 100
periodSeconds: 60
selectPolicy: Max
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Pods
value: 1
periodSeconds: 60
selectPolicy: Max
---
# 4. ConfigMap - 配置管理
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
database.host: "postgres-primary.db.svc.cluster.local"
database.port: "5432"
redis.host: "redis-master.cache.svc.cluster.local"
kafka.bootstrap.servers: "kafka-broker-0.kafka.svc.cluster.local:9092"
logging.level: "INFO"
---
# 5. Secret - 敏感信息
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
username: YWRtaW4= # base64编码的admin
password: cGFzc3dvcmQxMjM= # base64编码的password123
服务网格 (Service Mesh) 示例:
# Istio配置示例
# 1. VirtualService - 流量路由
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: user-service
spec:
hosts:
- user-service
http:
- match:
- headers:
x-version:
exact: v2
route:
- destination:
host: user-service
subset: v2
weight: 100
- route:
- destination:
host: user-service
subset: v1
weight: 90
- destination:
host: user-service
subset: v2
weight: 10
- fault:
delay:
percentage:
value: 10
fixedDelay: 2s
route:
- destination:
host: user-service
subset: v1
---
# 2. DestinationRule - 定义子集和策略
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: user-service
spec:
host: user-service
subsets:
- name: v1
labels:
version: v1.2.0
- name: v2
labels:
version: v2.0.0
trafficPolicy:
loadBalancer:
simple: LEAST_CONN
connectionPool:
tcp:
maxConnections: 100
connectTimeout: 30ms
http:
http1MaxPendingRequests: 10
http2MaxRequests: 100
maxRequestsPerConnection: 10
maxRetries: 3
outlierDetection:
consecutive5xxErrors: 5
interval: 30s
baseEjectionTime: 30s
maxEjectionPercent: 50
---
# 3. Gateway - 入口网关
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: public-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*.example.com"
tls:
httpsRedirect: true
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- "*.example.com"
tls:
mode: SIMPLE
credentialName: example-cert
云原生应用代码示例:
// Spring Boot云原生应用
@SpringBootApplication
@EnableCircuitBreaker
@EnableDiscoveryClient
@EnableConfigurationProperties(AppProperties.class)
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
@Bean
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
return registry -> registry.config().commonTags(
"application", "user-service",
"region", System.getenv("REGION"),
"environment", System.getenv("ENVIRONMENT")
);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.user"))
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo())
.enableUrlTemplating(false);
}
}
// 配置类
@ConfigurationProperties(prefix = "app")
@Data
public class AppProperties {
private DatabaseProperties database;
private RedisProperties redis;
private KafkaProperties kafka;
private SecurityProperties security;
@Data
public static class DatabaseProperties {
private String url;
private String username;
private String password;
private int maxPoolSize = 10;
private int connectionTimeout = 30000;
}
@Data
public static class RedisProperties {
private String host;
private int port = 6379;
private int timeout = 2000;
private String password;
}
}
// 健康检查
@RestController
@RequestMapping("/health")
public class HealthController {
private final HealthIndicator databaseHealthIndicator;
private final HealthIndicator redisHealthIndicator;
private final HealthIndicator kafkaHealthIndicator;
public HealthController(
@Qualifier("databaseHealthIndicator") HealthIndicator databaseHealthIndicator,
@Qualifier("redisHealthIndicator") HealthIndicator redisHealthIndicator,
@Qualifier("kafkaHealthIndicator") HealthIndicator kafkaHealthIndicator) {
this.databaseHealthIndicator = databaseHealthIndicator;
this.redisHealthIndicator = redisHealthIndicator;
this.kafkaHealthIndicator = kafkaHealthIndicator;
}
@GetMapping("/live")
public ResponseEntity<Map<String, String>> liveness() {
Map<String, String> response = new HashMap<>();
response.put("status", "UP");
response.put("timestamp", Instant.now().toString());
return ResponseEntity.ok(response);
}
@GetMapping("/ready")
public ResponseEntity<Map<String, Object>> readiness() {
Map<String, Object> response = new HashMap<>();
Map<String, Object> components = new HashMap<>();
// 检查关键依赖
Health databaseHealth = databaseHealthIndicator.health();
Health redisHealth = redisHealthIndicator.health();
Health kafkaHealth = kafkaHealthIndicator.health();
components.put("database", databaseHealth.getStatus());
components.put("redis", redisHealth.getStatus());
components.put("kafka", kafkaHealth.getStatus());
// 判断整体状态
boolean allHealthy = databaseHealth.getStatus().equals(Status.UP) &&
redisHealth.getStatus().equals(Status.UP) &&
kafkaHealth.getStatus().equals(Status.UP);
response.put("status", allHealthy ? "READY" : "NOT_READY");
response.put("components", components);
response.put("timestamp", Instant.now().toString());
return allHealthy ?
ResponseEntity.ok(response) :
ResponseEntity.status(503).body(response);
}
@GetMapping("/startup")
public ResponseEntity<Map<String, String>> startup() {
// 启动检查,用于Kubernetes的startupProbe
Map<String, String> response = new HashMap<>();
response.put("status", "STARTED");
response.put("timestamp", Instant.now().toString());
return ResponseEntity.ok(response);
}
}
// 使用熔断器
@Service
@Slf4j
public class UserService {
@Autowired
private RestTemplate restTemplate;
@HystrixCommand(
fallbackMethod = "getUserFallback",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000")
},
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "20"),
@HystrixProperty(name = "maxQueueSize", value = "10")
}
)
public User getUserWithOrders(String userId) {
// 调用订单服务(可能失败)
String url = "http://order-service/api/orders?userId=" + userId;
List<Order> orders = restTemplate.exchange(
url, HttpMethod.GET, null,
new ParameterizedTypeReference<List<Order>>() {}
).getBody();
User user = getUserFromDatabase(userId);
user.setOrders(orders);
return user;
}
private User getUserFallback(String userId, Throwable t) {
log.warn("获取用户订单失败,使用降级数据", t);
User user = getUserFromDatabase(userId);
user.setOrders(Collections.emptyList()); // 返回空订单列表
return user;
}
}
云原生监控和可观测性:
# Prometheus监控配置
global:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
rule_files:
- "rules/*.yml"
scrape_configs:
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
target_label: __address__
- action: labelmap
regex: __meta_kubernetes_pod_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_pod_name]
action: replace
target_label: kubernetes_pod_name
- job_name: 'kubernetes-apiservers'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https
# Grafana仪表盘配置
apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-dashboards
namespace: monitoring
data:
application-dashboard.json: |
{
"dashboard": {
"title": "Application Metrics",
"panels": [
{
"title": "请求率",
"type": "graph",
"targets": [
{
"expr": "rate(http_requests_total[5m])",
"legendFormat": "{{application}}"
}
]
},
{
"title": "响应时间",
"type": "graph",
"targets": [
{
"expr": "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))",
"legendFormat": "P95"
}
]
}
]
}
}
优点:
- 高弹性,自动扩展和自愈
- 资源利用率高
- 部署灵活,多云支持
- 强大的可观测性
- 自动化运维
缺点:
- 技术栈复杂,学习成本高
- 运维复杂度高
- 云厂商锁定风险
- 安全挑战增加
- 成本控制困难
三、架构选择指南
决策矩阵:
| 考虑因素 | 单体架构 | 分层架构 | 微服务架构 | 事件驱动架构 | 六边形架构 | 云原生架构 |
|---|---|---|---|---|---|---|
| 团队规模 | 小团队(<10) | 中小团队 | 大团队(>20) | 中大型团队 | 任何规模 | 大型团队 |
| 开发速度 | 快速 | 中等 | 慢(初期) | 中等 | 慢(初期) | 慢(初期) |
| 维护成本 | 高(长期) | 中等 | 低(模块化) | 中等 | 低 | 低 |
| 扩展性 | 差 | 中等 | 优秀 | 优秀 | 中等 | 优秀 |
| 技术多样性 | 单一 | 有限 | 丰富 | 丰富 | 灵活 | 丰富 |
| 容错能力 | 差 | 中等 | 优秀 | 优秀 | 中等 | 优秀 |
| 部署复杂度 | 简单 | 中等 | 复杂 | 复杂 | 中等 | 复杂 |
| 测试难度 | 简单 | 中等 | 复杂 | 复杂 | 简单(核心) | 复杂 |
架构演进路径:
初创阶段 → 成长阶段 → 成熟阶段 → 云原生阶段
↓ ↓ ↓ ↓
单体架构 → 分层架构 → 微服务架构 → 云原生架构
↘ ↗
事件驱动架构/六边形架构
混合架构实践:
在实际项目中,经常采用混合架构:
-
整体微服务 (Modulith)
// 内部模块化,外部单体部署 @SpringBootApplication public class ModularMonolithApplication { public static void main(String[] args) { SpringApplication.run(ModularMonolithApplication.class, args); } } // 模块间使用包私有访问控制 module.order { // 只能通过OrderService接口访问 public interface OrderService { ... } class OrderServiceImpl { ... } } module.inventory { // 只能通过InventoryService接口访问 public interface InventoryService { ... } class InventoryServiceImpl { ... } } -
逐步迁移策略
阶段1: 单体应用 + 新功能作为独立服务 阶段2: 提取核心功能为微服务 阶段3: 逐步拆分剩余功能 阶段4: 引入服务网格和云原生技术
四、总结与建议
核心原则:
- 简单性优先:从最简单的可行架构开始
- 演进式设计:随着业务增长逐步演进架构
- 业务驱动:架构服务于业务需求,而不是反之
- 保持选项开放:通过抽象降低未来迁移成本
- 自动化一切:自动化测试、部署、监控
技术选型建议:
- 初创公司/新产品:单体或分层架构
- 中型企业应用:分层或模块化单体
- 大型分布式系统:微服务 + 事件驱动
- 高要求金融/电商:六边形架构 + DDD + 微服务
- 云原生转型:容器化 + Kubernetes + 服务网格
成功关键因素:
- 团队技能:架构需要匹配团队能力
- 运维能力:分布式系统需要强大运维
- 监控体系:没有监控就不要上线
- 文化支持:架构成功需要组织文化支持
- 持续改进:架构需要持续演化和改进
记住:没有"最好"的架构,只有"最适合"的架构。架构决策应该基于具体的业务需求、团队能力和技术约束,并随着业务发展不断调整和优化。
170万+

被折叠的 条评论
为什么被折叠?



