微服务架构已成为现代后端开发的主流选择。但真正做好微服务并非易事——过度拆分会导致分布式噩梦,拆分不足又失去微服务的价值。本文将基于实战经验,分享微服务架构的完整实践指南。
何时需要微服务#
微服务不是银弹,先判断是否真的需要:
单体架构的优势场景#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| // 小团队、简单业务 - 单体架构更合适
class MonolithApp {
// 所有功能在一个进程内
// 简单的函数调用
// 统一的事务管理
// 易于开发和测试
handleOrder(order: Order) {
this.inventory.check(order);
this.payment.process(order);
this.shipping.arrange(order);
// 简单的事务保证一致性
}
}
|
适合单体的条件:
- 团队 < 10人
- 业务领域简单
- 部署频率要求不高
- 预期流量可控
微服务的优势场景#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| // 大团队、复杂业务 - 微服务更合适
// 订单服务
class OrderService {
@MessagePattern('order.created')
async handleOrder(data: OrderDTO) {
// 发布事件,其他服务订阅
this.eventBus.emit('order.created', data);
}
}
// 库存服务
class InventoryService {
@EventPattern('order.created')
async reserveStock(data: OrderDTO) {
// 独立的库存管理逻辑
}
}
|
需要微服务的信号:
- 单个服务部署影响全系统
- 不同模块需要独立扩展
- 团队规模持续增长
- 技术栈需要差异化
服务拆分策略#
按业务能力拆分(推荐)#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| // 领域驱动设计(DDD)指导服务边界
// 用户服务 - 身份与认证
interface UserService {
register(dto: RegisterDTO): Promise<User>;
authenticate(credentials: Credentials): Promise<Token>;
getProfile(userId: string): Promise<Profile>;
}
// 商品服务 - 商品目录管理
interface ProductService {
list(filters: ProductFilter): Promise<Product[]>;
create(dto: ProductDTO): Promise<Product>;
updateStock(productId: string, quantity: number): Promise<void>;
}
// 订单服务 - 交易流程
interface OrderService {
create(dto: OrderDTO): Promise<Order>;
cancel(orderId: string): Promise<void>;
getStatus(orderId: string): Promise<OrderStatus>;
}
|
避免的拆分陷阱#
1
2
3
4
5
6
7
8
9
10
| // ❌ 按技术层拆分 - 错误示例
// 服务A: 处理所有Controller
// 服务B: 处理所有Service
// 服务C: 处理所有DAO
// 这样只是分布式单体
// ✅ 按业务域拆分 - 正确示例
// 用户服务: 完整的用户管理功能
// 订单服务: 完整的订单处理功能
// 每个服务都有完整的层次结构
|
核心基础设施#
API网关#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| // 使用NestJS实现API网关
import { Controller, Get, Proxy } from '@nestjs/common';
@Controller()
export class GatewayController {
// 路由到用户服务
@Get('api/users/:id')
@Proxy({ service: 'user-service' })
getUser() {}
// 路由到订单服务
@Get('api/orders/:id')
@Proxy({ service: 'order-service' })
getOrder() {}
// 聚合多个服务的结果
@Get('api/user-orders/:userId')
async getUserOrders(@Param('userId') userId: string) {
const [user, orders] = await Promise.all([
this.userService.getOne(userId),
this.orderService.getUserOrders(userId)
]);
return { user, orders };
}
}
|
服务注册与发现#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| // Consul服务注册
import { Client } from 'consul';
const consul = new Client();
// 服务启动时注册
async function registerService() {
await consul.agent.service.register({
name: 'order-service',
address: process.env.SERVICE_HOST,
port: parseInt(process.env.SERVICE_PORT),
check: {
http: `http://${process.env.SERVICE_HOST}:${process.env.SERVICE_PORT}/health`,
interval: '10s'
},
tags: ['v1', 'orders']
});
}
// 服务发现
async function discoverService(serviceName: string) {
const services = await consul.agent.service.list();
const instances = Object.values(services)
.filter(s => s.Service === serviceName);
// 负载均衡:随机选择
return instances[Math.floor(Math.random() * instances.length)];
}
|
配置中心#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| // 集中式配置管理
import { ConfigService } from '@nestjs/config';
// 配置优先级:环境变量 > 远程配置 > 本地文件
async function loadConfig() {
const config = new ConfigService();
return {
database: {
host: config.get('DB_HOST', 'localhost'),
port: config.get('DB_PORT', 5432),
username: config.get('DB_USER'),
password: config.get('DB_PASS')
},
redis: {
host: config.get('REDIS_HOST'),
port: config.get('REDIS_PORT', 6379)
},
features: {
enableCache: config.get('ENABLE_CACHE', true),
enableRateLimit: config.get('ENABLE_RATELIMIT', true)
}
};
}
|
服务间通信#
同步通信:REST/gRPC#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| // REST API - 简单场景
import axios from 'axios';
class UserServiceClient {
private baseURL = 'http://user-service';
async getUser(userId: string): Promise<User> {
const { data } = await axios.get(
`${this.baseURL}/users/${userId}`
);
return data;
}
}
// gRPC - 高性能场景
// user.proto
syntax = "proto3";
service UserService {
rpc GetUser(GetUserRequest) returns (UserResponse);
}
// 生成的TypeScript客户端
const client = new UserServiceClient('user-service:50051');
const user = await client.getUser({ userId: '123' });
|
异步通信:消息队列#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| // 使用RabbitMQ事件驱动
import { AmqpConnection } from '@nestjs-plus/rabbitmq';
class OrderService {
constructor(private amqp: AmqpConnection) {}
async createOrder(dto: OrderDTO): Promise<Order> {
const order = await this.saveOrder(dto);
// 发布订单创建事件
await this.amqp.publish('order.exchange', 'order.created', {
orderId: order.id,
userId: order.userId,
items: order.items,
total: order.total
});
return order;
}
}
// 库存服务订阅事件
class InventoryService {
@RabbitSubscribe({
exchange: 'order.exchange',
routingKey: 'order.created',
queue: 'inventory.order.created'
})
async handleOrderCreated(event: OrderCreatedEvent) {
await this.reserveStock(event.items);
}
}
|
数据一致性#
Saga模式:分布式事务#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| // 订单处理Saga
class OrderSaga {
private steps = [
'validateOrder',
'reserveInventory',
'processPayment',
'confirmOrder'
];
async execute(orderId: string): Promise<void> {
const saga = new SagaLog(orderId);
for (const step of this.steps) {
try {
await this.executeStep(step, orderId);
saga.markCompleted(step);
} catch (error) {
// 执行补偿操作
await this.compensate(saga);
throw error;
}
}
}
private async compensate(saga: SagaLog): Promise<void> {
const completedSteps = saga.getCompletedSteps();
// 逆序执行补偿
for (const step of completedSteps.reverse()) {
await this.executeCompensation(step, saga.orderId);
}
}
}
|
最终一致性方案#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| // 事件溯源 + CQRS
class OrderEventStore {
async append(event: OrderEvent): Promise<void> {
// 追加事件到事件流
await this.db.events.insert({
aggregateId: event.orderId,
type: event.type,
data: JSON.stringify(event.data),
timestamp: Date.now(),
version: event.version
});
}
async getEvents(orderId: string): Promise<OrderEvent[]> {
return await this.db.events
.where('aggregateId', orderId)
.orderBy('timestamp', 'asc');
}
// 从事件重建状态
async rebuild(orderId: string): Promise<Order> {
const events = await this.getEvents(orderId);
return events.reduce((order, event) => {
return this.applyEvent(order, event);
}, new Order());
}
}
|
可观测性#
分布式追踪#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| // OpenTelemetry集成
import { trace } from '@opentelemetry/api';
const tracer = trace.getTracer('order-service');
async function processOrder(orderId: string) {
const span = tracer.startSpan('processOrder');
try {
span.setAttribute('order.id', orderId);
// 自动传播追踪上下文
const user = await this.userService.getUser(userId);
const inventory = await this.inventoryService.check(items);
span.setStatus({ code: SpanStatusCode.OK });
} catch (error) {
span.recordException(error);
throw error;
} finally {
span.end();
}
}
|
指标监控#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| // Prometheus指标
import { Counter, Histogram } from 'prom-client';
export const orderCreatedCounter = new Counter({
name: 'orders_created_total',
help: 'Total orders created',
labelNames: ['status']
});
export const orderProcessingTime = new Histogram({
name: 'order_processing_seconds',
help: 'Order processing time',
buckets: [0.1, 0.5, 1, 2, 5]
});
async function createOrder(dto: OrderDTO) {
const start = Date.now();
try {
const order = await this.service.create(dto);
orderCreatedCounter.labels('success').inc();
return order;
} catch (error) {
orderCreatedCounter.labels('failed').inc();
throw error;
} finally {
orderProcessingTime.observe((Date.now() - start) / 1000);
}
}
|
部署策略#
容器化部署#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # Dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/main.js"]
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| # docker-compose.yml
version: '3.8'
services:
order-service:
build: ./services/order
environment:
- DB_HOST=postgres
- REDIS_HOST=redis
depends_on:
- postgres
- redis
postgres:
image: postgres:16
environment:
- POSTGRES_DB=orders
redis:
image: redis:7-alpine
|
Kubernetes部署#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
| # deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
replicas: 3
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
spec:
containers:
- name: order-service
image: order-service:v1.0.0
ports:
- containerPort: 3000
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: db.host
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: order-service
spec:
selector:
app: order-service
ports:
- port: 80
targetPort: 3000
type: ClusterIP
|
常见陷阱与解决方案#
陷阱1:过度拆分#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| // ❌ 错误:每个功能一个服务
class UserEmailService {}
class UserProfileService {}
class UserPreferenceService {}
class UserAuthService {}
// ✅ 正确:相关的功能在一个服务
class UserService {
// 统一的用户域
handleEmail() {}
handleProfile() {}
handlePreference() {}
handleAuth() {}
}
|
陷阱2:分布式事务滥用#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| // ❌ 2PC/3PC - 性能差、复杂度高
async function createOrder() {
await transaction.begin();
await orderService.create();
await inventoryService.reserve(); // 2PC
await paymentService.charge(); // 2PC
await transaction.commit();
}
// ✅ Saga模式 - 最终一致
async function createOrder() {
const order = await orderService.create();
await inventoryService.reserve(order);
await paymentService.charge(order);
// 失败时通过补偿操作回滚
}
|
微服务架构是一把双刃剑:
收益:
代价:
关键决策点:
- 是否真的需要微服务?
- 如何合理划分服务边界?
- 如何处理分布式事务?
- 如何保证系统可观测性?
记住:从简单开始,在需要时进化。不要为了微服务而微服务。