微服务架构

What — 是什么

微服务架构将单体应用拆分为多个独立部署的小服务,每个服务专注单一业务能力,通过 API/消息队列通信,独立开发/测试/部署/扩缩容。

核心概念:

  • 服务拆分:按业务领域(DDD 限界上下文)拆分,每个服务拥有独立数据库
  • 服务注册发现:服务实例动态注册地址,消费者通过注册中心查找(Consul/Nacos)
  • API 网关:统一入口,路由转发、认证、限流、协议转换
  • 配置中心:集中管理所有服务的配置,动态更新(Apollo/Nacos Config)
  • 熔断降级:下游服务不可用时快速失败,防止级联故障(Circuit Breaker)
  • 链路追踪:追踪请求在多个服务间的调用路径(Jaeger/Zipkin)

关键特性:

  • 每个服务独立数据库,避免数据耦合
  • 服务间通过 gRPC/REST/消息队列通信
  • 独立部署,故障隔离
  • 可按服务独立扩缩容

Why — 为什么

适用场景:

  • 大型团队(10+ 开发者)协作
  • 业务模块边界清晰
  • 不同模块有不同的性能/扩展需求
  • 需要独立部署和灰度发布

对比架构:

维度单体架构微服务架构
部署简单(一个包)复杂(多服务)
扩展整体扩展按需扩展
故障影响全局隔离
开发效率小项目高大项目高
运维复杂度

How — 怎么用

代码示例

// NestJS 微服务
const { NestFactory } = require('@nestjs/core');
const { MicroserviceOptions, Transport } = require('@nestjs/microservices');

const app = await NestFactory.createMicroservice(AppModule, {
    transport: Transport.TCP,
    options: { host: '0.0.0.0', port: 3001 }
});

// 消息处理
@MessagePattern('user.created')
async function handleUserCreated(data: CreateUserEvent) {
    await this.notificationService.sendWelcome(data.userId);
}

// 客户端调用
@Injectable()
class OrderService {
    constructor(@Inject('USER_SERVICE') private client: ClientProxy) {}

    async getUser(id: string) {
        return this.client.send({ cmd: 'get_user' }, { id }).toPromise();
    }
}

常见问题与踩坑

问题原因解决方案
分布式事务跨服务数据一致性Saga 模式 + 事件溯源
服务间循环依赖服务 A 调 B,B 调 A引入事件驱动解耦
调试困难请求跨多个服务链路追踪(Trace ID)
数据一致性各服务独立数据库最终一致性 + 补偿事务

最佳实践

  • 按业务领域拆分,不从技术层拆分
  • 每个服务独立数据库
  • 用 API 网关统一入口
  • 实现熔断和降级防止级联故障
  • 链路追踪串联跨服务调用

面试题

Q1: 微服务如何处理分布式事务?

两种主流方案:① Saga 模式——将长事务拆分为多个本地事务,每个步骤有补偿操作。失败时逆序执行补偿。适合业务流程明确的场景(订单→支付→库存)。② 事件溯源——所有状态变更以事件形式记录,通过重放事件重建状态。配合消息队列确保最终一致性。不推荐跨服务 2PC(性能差、耦合高)。

Q2: 微服务的服务发现如何实现?

两种模式:① 客户端发现——服务实例启动时向注册中心(Consul/Nacos)注册地址和健康状态,客户端从注册中心获取实例列表,自行选择(负载均衡)。② 服务端发现——客户端请求 API 网关/负载均衡器,由其查询注册中心并转发。客户端发现更灵活(可自定义策略),服务端发现更简单(客户端无需感知注册中心)。


相关链接: