微服务架构实战:从单体应用到分布式系统

2026-06-18

分享微服务架构的设计模式和最佳实践

作者:Elegy

微服务架构实战:从单体应用到分布式系统

微服务架构已经成为构建大规模应用的主流选择。本文将分享我在实际项目中实施微服务架构的经验和教训。

🏗️ 为什么选择微服务?

单体应用的痛点

  • 部署困难:一处改动需要整体重新部署
  • 扩展受限:无法针对性地扩展高负载模块
  • 技术栈固定:难以引入新技术
  • 团队协作:多人修改同一代码库易冲突

微服务的优势

  • ✅ 独立部署和扩展
  • ✅ 技术栈自由选择
  • ✅ 故障隔离
  • ✅ 团队独立开发

🎯 服务拆分策略

1. 按业务领域拆分(DDD方法)

电商系统示例:
├── 用户服务 (User Service)
├── 商品服务 (Product Service)
├── 订单服务 (Order Service)
├── 支付服务 (Payment Service)
└── 库存服务 (Inventory Service)

2. 拆分原则

  • 单一职责:每个服务只负责一个业务领域
  • 高内聚低耦合:服务内部紧密相关,服务间松散依赖
  • 数据独立:每个服务拥有自己的数据库

🌐 API网关设计

API网关是微服务的统一入口:

// 使用Express实现简单的API网关
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');

const app = express();

// 路由转发
app.use('/api/users', createProxyMiddleware({ 
  target: 'http://user-service:3001',
  changeOrigin: true 
}));

app.use('/api/products', createProxyMiddleware({ 
  target: 'http://product-service:3002',
  changeOrigin: true 
}));

// 统一认证中间件
app.use(authenticateToken);

app.listen(8080);

🔍 服务发现与注册

使用Consul或Eureka实现服务注册:

// 服务注册示例
const consul = require('consul')();

function registerService() {
  consul.agent.service.register({
    id: 'user-service-1',
    name: 'user-service',
    address: '192.168.1.10',
    port: 3001,
    check: {
      http: 'http://192.168.1.10:3001/health',
      interval: '10s'
    }
  });
}

📡 服务间通信

1. 同步通信 - REST API

// 订单服务调用用户服务
async function createOrder(userId, productId) {
  const user = await axios.get(`http://user-service/api/users/${userId}`);
  
  if (!user.data) {
    throw new Error('User not found');
  }
  
  // 创建订单逻辑
}

2. 异步通信 - 消息队列

// 使用RabbitMQ发送订单创建事件
const amqp = require('amqplib');

async function publishOrderCreated(order) {
  const connection = await amqp.connect('amqp://localhost');
  const channel = await connection.createChannel();
  
  await channel.assertExchange('orders', 'topic', { durable: true });
  channel.publish('orders', 'order.created', Buffer.from(JSON.stringify(order)));
  
  console.log('Order created event published');
}

🛡️ 分布式追踪

使用Jaeger或Zipkin实现请求链路追踪:

const { initTracer } = require('jaeger-client');

const tracer = initTracer({
  serviceName: 'user-service',
  sampler: { type: 'const', param: 1 }
});

app.use((req, res, next) => {
  const span = tracer.startSpan('http_request');
  span.setTag('http.method', req.method);
  span.setTag('http.url', req.url);
  
  res.on('finish', () => {
    span.setTag('http.status_code', res.statusCode);
    span.finish();
  });
  
  next();
});

⚠️ 常见挑战与解决方案

1. 分布式事务

使用Saga模式处理跨服务事务:

// 订单创建的Saga流程
async function createOrderSaga(orderData) {
  try {
    // 1. 创建订单
    const order = await orderService.create(orderData);
    
    // 2. 扣减库存
    await inventoryService.reduce(orderData.items);
    
    // 3. 处理支付
    await paymentService.process(order.id, orderData.amount);
    
    return order;
  } catch (error) {
    // 补偿操作:回滚已完成的步骤
    await orderService.cancel(order.id);
    await inventoryService.restore(orderData.items);
    throw error;
  }
}

2. 服务熔断与降级

使用Circuit Breaker模式:

const CircuitBreaker = require('opossum');

const options = {
  timeout: 3000,
  errorThresholdPercentage: 50,
  resetTimeout: 30000
};

const breaker = new CircuitBreaker(callExternalService, options);

breaker.fallback(() => '服务暂时不可用,请稍后重试');

breaker.on('open', () => console.log('熔断器打开'));
breaker.on('halfOpen', () => console.log('熔断器半开'));
breaker.on('close', () => console.log('熔断器关闭'));

🎓 总结

微服务架构带来灵活性的同时也增加了复杂度:

  • 合理拆分服务边界
  • 选择合适的通信方式
  • 实施完善的监控和追踪
  • 处理好分布式事务和容错
  • 使用容器化和编排工具(Docker + K8s)

只有在团队和业务规模达到一定程度时,微服务的优势才会体现出来。小型项目建议从单体开始!