microservices-architecture
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMicroservices Architecture
微服务架构
Overview
概述
Comprehensive guide to designing, implementing, and maintaining microservices architectures. Covers service decomposition, communication patterns, data management, deployment strategies, and observability for distributed systems.
一份关于微服务架构设计、实现与维护的全面指南,涵盖服务拆分、通信模式、数据管理、部署策略以及分布式系统的可观测性等内容。
When to Use
适用场景
- Designing new microservices architectures
- Decomposing monolithic applications
- Implementing service-to-service communication
- Setting up API gateways and service mesh
- Implementing service discovery
- Managing distributed transactions
- Designing inter-service data consistency
- Scaling independent services
- 设计全新的微服务架构
- 拆分单体应用
- 实现服务间通信
- 搭建API网关与服务网格
- 实现服务发现
- 管理分布式事务
- 设计服务间数据一致性方案
- 独立服务的扩容
Instructions
操作指南
1. Service Boundary Design
1. 服务边界设计
Domain-Driven Design (DDD) Approach
领域驱动设计(DDD)方法
Bounded Contexts:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Order Service │ │ User Service │ │ Payment Service │
│ │ │ │ │ │
│ - Create Order │ │ - User Profile │ │ - Process Pay │
│ - Order Status │ │ - Auth │ │ - Refund │
│ - Order History │ │ - Preferences │ │ - Transactions │
└─────────────────┘ └─────────────────┘ └─────────────────┘Decomposition Strategies:
- By Business Capability
E-commerce System:
- Product Catalog Service
- Shopping Cart Service
- Order Management Service
- Payment Service
- Inventory Service
- Shipping Service
- User Account Service- By Subdomain
Healthcare System:
- Patient Management (Core Domain)
- Appointment Scheduling (Core Domain)
- Billing (Supporting Domain)
- Notifications (Generic Domain)
- Reporting (Generic Domain)Bounded Contexts:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Order Service │ │ User Service │ │ Payment Service │
│ │ │ │ │ │
│ - Create Order │ │ - User Profile │ │ - Process Pay │
│ - Order Status │ │ - Auth │ │ - Refund │
│ - Order History │ │ - Preferences │ │ - Transactions │
└─────────────────┘ └─────────────────┘ └─────────────────┘拆分策略:
- 按业务能力拆分
E-commerce System:
- Product Catalog Service
- Shopping Cart Service
- Order Management Service
- Payment Service
- Inventory Service
- Shipping Service
- User Account Service- 按子域拆分
Healthcare System:
- Patient Management (Core Domain)
- Appointment Scheduling (Core Domain)
- Billing (Supporting Domain)
- Notifications (Generic Domain)
- Reporting (Generic Domain)Service Design Example
服务设计示例
typescript
// order-service/src/domain/order.ts
export class OrderService {
constructor(
private orderRepository: OrderRepository,
private eventBus: EventBus,
private paymentClient: PaymentClient,
private inventoryClient: InventoryClient
) {}
async createOrder(request: CreateOrderRequest): Promise<Order> {
// 1. Validate order
const order = Order.create(request);
// 2. Check inventory (synchronous call)
const available = await this.inventoryClient.checkAvailability(
order.items
);
if (!available) {
throw new InsufficientInventoryError();
}
// 3. Save order
await this.orderRepository.save(order);
// 4. Publish event (asynchronous)
await this.eventBus.publish(new OrderCreatedEvent(order));
return order;
}
}typescript
// order-service/src/domain/order.ts
export class OrderService {
constructor(
private orderRepository: OrderRepository,
private eventBus: EventBus,
private paymentClient: PaymentClient,
private inventoryClient: InventoryClient
) {}
async createOrder(request: CreateOrderRequest): Promise<Order> {
// 1. Validate order
const order = Order.create(request);
// 2. Check inventory (synchronous call)
const available = await this.inventoryClient.checkAvailability(
order.items
);
if (!available) {
throw new InsufficientInventoryError();
}
// 3. Save order
await this.orderRepository.save(order);
// 4. Publish event (asynchronous)
await this.eventBus.publish(new OrderCreatedEvent(order));
return order;
}
}2. Communication Patterns
2. 通信模式
Synchronous Communication (REST/gRPC)
同步通信(REST/gRPC)
REST API Example:
typescript
// user-service/src/api/user.controller.ts
import express from 'express';
const router = express.Router();
// Get user profile
router.get('/users/:id', async (req, res) => {
try {
const user = await userService.findById(req.params.id);
res.json(user);
} catch (error) {
if (error instanceof UserNotFoundError) {
res.status(404).json({ error: 'User not found' });
} else {
res.status(500).json({ error: 'Internal server error' });
}
}
});
// Service-to-service call with circuit breaker
import axios from 'axios';
import CircuitBreaker from 'opossum';
const options = {
timeout: 3000,
errorThresholdPercentage: 50,
resetTimeout: 30000
};
const breaker = new CircuitBreaker(
async (userId: string) => {
const response = await axios.get(
`http://user-service/users/${userId}`,
{ timeout: 2000 }
);
return response.data;
},
options
);
breaker.fallback(() => ({ id: userId, name: 'Unknown User' }));gRPC Example:
protobuf
// proto/user.proto
syntax = "proto3";
package user;
service UserService {
rpc GetUser (GetUserRequest) returns (UserResponse);
rpc ListUsers (ListUsersRequest) returns (stream UserResponse);
}
message GetUserRequest {
string user_id = 1;
}
message UserResponse {
string user_id = 1;
string email = 2;
string name = 3;
}typescript
// Implementation
import * as grpc from '@grpc/grpc-js';
import * as protoLoader from '@grpc/proto-loader';
const packageDefinition = protoLoader.loadSync('proto/user.proto');
const userProto = grpc.loadPackageDefinition(packageDefinition).user;
// Server
function getUser(call, callback) {
const userId = call.request.user_id;
const user = await userService.findById(userId);
callback(null, user);
}
const server = new grpc.Server();
server.addService(userProto.UserService.service, { getUser });
server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());REST API示例:
typescript
// user-service/src/api/user.controller.ts
import express from 'express';
const router = express.Router();
// Get user profile
router.get('/users/:id', async (req, res) => {
try {
const user = await userService.findById(req.params.id);
res.json(user);
} catch (error) {
if (error instanceof UserNotFoundError) {
res.status(404).json({ error: 'User not found' });
} else {
res.status(500).json({ error: 'Internal server error' });
}
}
});
// Service-to-service call with circuit breaker
import axios from 'axios';
import CircuitBreaker from 'opossum';
const options = {
timeout: 3000,
errorThresholdPercentage: 50,
resetTimeout: 30000
};
const breaker = new CircuitBreaker(
async (userId: string) => {
const response = await axios.get(
`http://user-service/users/${userId}`,
{ timeout: 2000 }
);
return response.data;
},
options
);
breaker.fallback(() => ({ id: userId, name: 'Unknown User' }));gRPC示例:
protobuf
// proto/user.proto
syntax = "proto3";
package user;
service UserService {
rpc GetUser (GetUserRequest) returns (UserResponse);
rpc ListUsers (ListUsersRequest) returns (stream UserResponse);
}
message GetUserRequest {
string user_id = 1;
}
message UserResponse {
string user_id = 1;
string email = 2;
string name = 3;
}typescript
// Implementation
import * as grpc from '@grpc/grpc-js';
import * as protoLoader from '@grpc/proto-loader';
const packageDefinition = protoLoader.loadSync('proto/user.proto');
const userProto = grpc.loadPackageDefinition(packageDefinition).user;
// Server
function getUser(call, callback) {
const userId = call.request.user_id;
const user = await userService.findById(userId);
callback(null, user);
}
const server = new grpc.Server();
server.addService(userProto.UserService.service, { getUser });
server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());Asynchronous Communication (Message Queue)
异步通信(消息队列)
Event-Driven with RabbitMQ:
typescript
// order-service/src/events/publisher.ts
import amqp from 'amqplib';
export class EventPublisher {
private connection: amqp.Connection;
private channel: amqp.Channel;
async connect() {
this.connection = await amqp.connect('amqp://localhost');
this.channel = await this.connection.createChannel();
await this.channel.assertExchange('orders', 'topic', { durable: true });
}
async publishOrderCreated(order: Order) {
const event = {
eventType: 'OrderCreated',
timestamp: new Date(),
data: order
};
this.channel.publish(
'orders',
'order.created',
Buffer.from(JSON.stringify(event)),
{ persistent: true }
);
}
}
// inventory-service/src/events/consumer.ts
export class OrderEventConsumer {
async subscribe() {
const connection = await amqp.connect('amqp://localhost');
const channel = await connection.createChannel();
await channel.assertExchange('orders', 'topic', { durable: true });
const q = await channel.assertQueue('inventory-order-events', {
durable: true
});
await channel.bindQueue(q.queue, 'orders', 'order.created');
channel.consume(q.queue, async (msg) => {
if (msg) {
const event = JSON.parse(msg.content.toString());
await this.handleOrderCreated(event.data);
channel.ack(msg);
}
});
}
private async handleOrderCreated(order: Order) {
// Reserve inventory
await inventoryService.reserveItems(order.items);
}
}Kafka Event Streaming:
typescript
// event-streaming/kafka-producer.ts
import { Kafka } from 'kafkajs';
const kafka = new Kafka({
clientId: 'order-service',
brokers: ['kafka:9092']
});
const producer = kafka.producer();
export async function publishEvent(topic: string, event: any) {
await producer.connect();
await producer.send({
topic,
messages: [
{
key: event.aggregateId,
value: JSON.stringify(event),
headers: {
'event-type': event.type,
'correlation-id': event.correlationId
}
}
]
});
}
// Consumer
const consumer = kafka.consumer({ groupId: 'inventory-service' });
await consumer.subscribe({ topic: 'order-events', fromBeginning: false });
await consumer.run({
eachMessage: async ({ topic, partition, message }) => {
const event = JSON.parse(message.value.toString());
await eventHandler.handle(event);
}
});基于RabbitMQ的事件驱动架构:
typescript
// order-service/src/events/publisher.ts
import amqp from 'amqplib';
export class EventPublisher {
private connection: amqp.Connection;
private channel: amqp.Channel;
async connect() {
this.connection = await amqp.connect('amqp://localhost');
this.channel = await this.connection.createChannel();
await this.channel.assertExchange('orders', 'topic', { durable: true });
}
async publishOrderCreated(order: Order) {
const event = {
eventType: 'OrderCreated',
timestamp: new Date(),
data: order
};
this.channel.publish(
'orders',
'order.created',
Buffer.from(JSON.stringify(event)),
{ persistent: true }
);
}
}
// inventory-service/src/events/consumer.ts
export class OrderEventConsumer {
async subscribe() {
const connection = await amqp.connect('amqp://localhost');
const channel = await connection.createChannel();
await channel.assertExchange('orders', 'topic', { durable: true });
const q = await channel.assertQueue('inventory-order-events', {
durable: true
});
await channel.bindQueue(q.queue, 'orders', 'order.created');
channel.consume(q.queue, async (msg) => {
if (msg) {
const event = JSON.parse(msg.content.toString());
await this.handleOrderCreated(event.data);
channel.ack(msg);
}
});
}
private async handleOrderCreated(order: Order) {
// Reserve inventory
await inventoryService.reserveItems(order.items);
}
}Kafka事件流:
typescript
// event-streaming/kafka-producer.ts
import { Kafka } from 'kafkajs';
const kafka = new Kafka({
clientId: 'order-service',
brokers: ['kafka:9092']
});
const producer = kafka.producer();
export async function publishEvent(topic: string, event: any) {
await producer.connect();
await producer.send({
topic,
messages: [
{
key: event.aggregateId,
value: JSON.stringify(event),
headers: {
'event-type': event.type,
'correlation-id': event.correlationId
}
}
]
});
}
// Consumer
const consumer = kafka.consumer({ groupId: 'inventory-service' });
await consumer.subscribe({ topic: 'order-events', fromBeginning: false });
await consumer.run({
eachMessage: async ({ topic, partition, message }) => {
const event = JSON.parse(message.value.toString());
await eventHandler.handle(event);
}
});3. API Gateway Pattern
3. API网关模式
typescript
// api-gateway/src/gateway.ts
import express from 'express';
import httpProxy from 'http-proxy-middleware';
import jwt from 'jsonwebtoken';
import rateLimit from 'express-rate-limit';
const app = express();
// Rate limiting
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100
});
app.use(limiter);
// Authentication middleware
const authenticateToken = (req, res, next) => {
const token = req.headers['authorization']?.split(' ')[1];
if (!token) return res.sendStatus(401);
jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
};
// Route to services
app.use('/api/users', authenticateToken, httpProxy.createProxyMiddleware({
target: 'http://user-service:3000',
changeOrigin: true,
pathRewrite: { '^/api/users': '/users' }
}));
app.use('/api/orders', authenticateToken, httpProxy.createProxyMiddleware({
target: 'http://order-service:3000',
changeOrigin: true,
pathRewrite: { '^/api/orders': '/orders' }
}));
app.use('/api/products', httpProxy.createProxyMiddleware({
target: 'http://product-service:3000',
changeOrigin: true,
pathRewrite: { '^/api/products': '/products' }
}));
// Aggregation endpoint
app.get('/api/order-details/:orderId', authenticateToken, async (req, res) => {
const orderId = req.params.orderId;
// Parallel requests to multiple services
const [order, user, products] = await Promise.all([
fetch(`http://order-service:3000/orders/${orderId}`).then(r => r.json()),
fetch(`http://user-service:3000/users/${req.user.id}`).then(r => r.json()),
fetch(`http://product-service:3000/products?ids=${order.itemIds}`).then(r => r.json())
]);
res.json({ order, user, products });
});typescript
// api-gateway/src/gateway.ts
import express from 'express';
import httpProxy from 'http-proxy-middleware';
import jwt from 'jsonwebtoken';
import rateLimit from 'express-rate-limit';
const app = express();
// Rate limiting
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100
});
app.use(limiter);
// Authentication middleware
const authenticateToken = (req, res, next) => {
const token = req.headers['authorization']?.split(' ')[1];
if (!token) return res.sendStatus(401);
jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
};
// Route to services
app.use('/api/users', authenticateToken, httpProxy.createProxyMiddleware({
target: 'http://user-service:3000',
changeOrigin: true,
pathRewrite: { '^/api/users': '/users' }
}));
app.use('/api/orders', authenticateToken, httpProxy.createProxyMiddleware({
target: 'http://order-service:3000',
changeOrigin: true,
pathRewrite: { '^/api/orders': '/orders' }
}));
app.use('/api/products', httpProxy.createProxyMiddleware({
target: 'http://product-service:3000',
changeOrigin: true,
pathRewrite: { '^/api/products': '/products' }
}));
// Aggregation endpoint
app.get('/api/order-details/:orderId', authenticateToken, async (req, res) => {
const orderId = req.params.orderId;
// Parallel requests to multiple services
const [order, user, products] = await Promise.all([
fetch(`http://order-service:3000/orders/${orderId}`).then(r => r.json()),
fetch(`http://user-service:3000/users/${req.user.id}`).then(r => r.json()),
fetch(`http://product-service:3000/products?ids=${order.itemIds}`).then(r => r.json())
]);
res.json({ order, user, products });
});4. Service Discovery
4. 服务发现
Consul Example
Consul示例
typescript
// service-registry/consul-client.ts
import Consul from 'consul';
export class ServiceRegistry {
private consul: Consul.Consul;
constructor() {
this.consul = new Consul({
host: 'consul',
port: 8500
});
}
// Register service
async register(serviceName: string, servicePort: number) {
await this.consul.agent.service.register({
id: `${serviceName}-${process.env.HOSTNAME}`,
name: serviceName,
address: process.env.SERVICE_IP,
port: servicePort,
check: {
http: `http://${process.env.SERVICE_IP}:${servicePort}/health`,
interval: '10s',
timeout: '5s'
}
});
}
// Discover service
async discover(serviceName: string): Promise<string> {
const result = await this.consul.health.service({
service: serviceName,
passing: true
});
if (result.length === 0) {
throw new Error(`Service ${serviceName} not found`);
}
// Simple round-robin
const service = result[Math.floor(Math.random() * result.length)];
return `http://${service.Service.Address}:${service.Service.Port}`;
}
// Deregister on shutdown
async deregister(serviceId: string) {
await this.consul.agent.service.deregister(serviceId);
}
}typescript
// service-registry/consul-client.ts
import Consul from 'consul';
export class ServiceRegistry {
private consul: Consul.Consul;
constructor() {
this.consul = new Consul({
host: 'consul',
port: 8500
});
}
// Register service
async register(serviceName: string, servicePort: number) {
await this.consul.agent.service.register({
id: `${serviceName}-${process.env.HOSTNAME}`,
name: serviceName,
address: process.env.SERVICE_IP,
port: servicePort,
check: {
http: `http://${process.env.SERVICE_IP}:${servicePort}/health`,
interval: '10s',
timeout: '5s'
}
});
}
// Discover service
async discover(serviceName: string): Promise<string> {
const result = await this.consul.health.service({
service: serviceName,
passing: true
});
if (result.length === 0) {
throw new Error(`Service ${serviceName} not found`);
}
// Simple round-robin
const service = result[Math.floor(Math.random() * result.length)];
return `http://${service.Service.Address}:${service.Service.Port}`;
}
// Deregister on shutdown
async deregister(serviceId: string) {
await this.consul.agent.service.deregister(serviceId);
}
}Kubernetes Service Discovery
Kubernetes服务发现
yaml
undefinedyaml
undefineduser-service-deployment.yaml
user-service-deployment.yaml
apiVersion: v1 kind: Service metadata: name: user-service spec: selector: app: user-service ports: - protocol: TCP port: 80 targetPort: 3000 type: ClusterIP
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 3
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: user-service:latest
ports:
- containerPort: 3000
env:
- name: SERVICE_NAME
value: "user-service"
```typescript
// Service call in Kubernetes
const userServiceUrl = process.env.USER_SERVICE_URL || 'http://user-service';
const response = await fetch(`${userServiceUrl}/users/${userId}`);apiVersion: v1 kind: Service metadata: name: user-service spec: selector: app: user-service ports: - protocol: TCP port: 80 targetPort: 3000 type: ClusterIP
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 3
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: user-service:latest
ports:
- containerPort: 3000
env:
- name: SERVICE_NAME
value: "user-service"
```typescript
// Service call in Kubernetes
const userServiceUrl = process.env.USER_SERVICE_URL || 'http://user-service';
const response = await fetch(`${userServiceUrl}/users/${userId}`);5. Data Consistency Patterns
5. 数据一致性模式
Saga Pattern (Orchestration)
Saga模式(编排式)
typescript
// order-saga-orchestrator.ts
export class OrderSagaOrchestrator {
async createOrder(orderData: CreateOrderRequest) {
const sagaId = uuidv4();
const saga = new SagaInstance(sagaId);
try {
// Step 1: Create order
const order = await this.orderService.createOrder(orderData);
saga.addCompensation(() => this.orderService.cancelOrder(order.id));
// Step 2: Reserve inventory
await this.inventoryService.reserveItems(order.items);
saga.addCompensation(() =>
this.inventoryService.releaseReservation(order.id)
);
// Step 3: Process payment
const payment = await this.paymentService.charge(order.total);
saga.addCompensation(() =>
this.paymentService.refund(payment.id)
);
// Step 4: Confirm order
await this.orderService.confirmOrder(order.id);
return order;
} catch (error) {
// Compensate in reverse order
await saga.compensate();
throw error;
}
}
}typescript
// order-saga-orchestrator.ts
export class OrderSagaOrchestrator {
async createOrder(orderData: CreateOrderRequest) {
const sagaId = uuidv4();
const saga = new SagaInstance(sagaId);
try {
// Step 1: Create order
const order = await this.orderService.createOrder(orderData);
saga.addCompensation(() => this.orderService.cancelOrder(order.id));
// Step 2: Reserve inventory
await this.inventoryService.reserveItems(order.items);
saga.addCompensation(() =>
this.inventoryService.releaseReservation(order.id)
);
// Step 3: Process payment
const payment = await this.paymentService.charge(order.total);
saga.addCompensation(() =>
this.paymentService.refund(payment.id)
);
// Step 4: Confirm order
await this.orderService.confirmOrder(order.id);
return order;
} catch (error) {
// Compensate in reverse order
await saga.compensate();
throw error;
}
}
}Event Sourcing Pattern
事件溯源模式
typescript
// order-aggregate.ts
export class OrderAggregate {
private id: string;
private status: OrderStatus;
private items: OrderItem[];
private events: DomainEvent[] = [];
// Command handler
createOrder(command: CreateOrderCommand) {
// Validation
if (this.id) throw new Error('Order already exists');
// Apply event
this.apply(new OrderCreatedEvent({
orderId: command.orderId,
userId: command.userId,
items: command.items
}));
}
// Event handler
private apply(event: DomainEvent) {
switch (event.type) {
case 'OrderCreated':
this.id = event.orderId;
this.items = event.items;
this.status = OrderStatus.PENDING;
break;
case 'OrderConfirmed':
this.status = OrderStatus.CONFIRMED;
break;
}
this.events.push(event);
}
getUncommittedEvents(): DomainEvent[] {
return this.events;
}
}typescript
// order-aggregate.ts
export class OrderAggregate {
private id: string;
private status: OrderStatus;
private items: OrderItem[];
private events: DomainEvent[] = [];
// Command handler
createOrder(command: CreateOrderCommand) {
// Validation
if (this.id) throw new Error('Order already exists');
// Apply event
this.apply(new OrderCreatedEvent({
orderId: command.orderId,
userId: command.userId,
items: command.items
}));
}
// Event handler
private apply(event: DomainEvent) {
switch (event.type) {
case 'OrderCreated':
this.id = event.orderId;
this.items = event.items;
this.status = OrderStatus.PENDING;
break;
case 'OrderConfirmed':
this.status = OrderStatus.CONFIRMED;
break;
}
this.events.push(event);
}
getUncommittedEvents(): DomainEvent[] {
return this.events;
}
}6. Service Mesh (Istio)
6. 服务网格(Istio)
yaml
undefinedyaml
undefinedistio-config.yaml
istio-config.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: order-service
spec:
hosts:
- order-service http:
- match:
- headers: user-type: exact: premium route:
- destination: host: order-service subset: v2 weight: 100
- route:
- destination: host: order-service subset: v1 weight: 90
- destination: host: order-service subset: v2 weight: 10
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: order-service
spec:
host: order-service
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 50
maxRequestsPerConnection: 2
outlierDetection:
consecutiveErrors: 5
interval: 30s
baseEjectionTime: 30s
subsets:
- name: v1 labels: version: v1
- name: v2 labels: version: v2
undefinedapiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: order-service
spec:
hosts:
- order-service http:
- match:
- headers: user-type: exact: premium route:
- destination: host: order-service subset: v2 weight: 100
- route:
- destination: host: order-service subset: v1 weight: 90
- destination: host: order-service subset: v2 weight: 10
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: order-service
spec:
host: order-service
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 50
maxRequestsPerConnection: 2
outlierDetection:
consecutiveErrors: 5
interval: 30s
baseEjectionTime: 30s
subsets:
- name: v1 labels: version: v1
- name: v2 labels: version: v2
undefinedBest Practices
最佳实践
✅ DO
✅ 建议
- Design services around business capabilities
- Use asynchronous communication where possible
- Implement circuit breakers for resilience
- Use API gateway for cross-cutting concerns
- Implement distributed tracing
- Use service mesh for service-to-service communication
- Design for failure (chaos engineering)
- Implement health checks for all services
- Use correlation IDs for request tracking
- Version your APIs
- Implement proper monitoring and alerting
- Use event-driven architecture for loose coupling
- Implement idempotent operations
- Use database per service pattern
- 围绕业务能力设计服务
- 尽可能使用异步通信
- 实现断路器以提升系统韧性
- 使用API网关处理横切关注点
- 实现分布式追踪
- 使用服务网格管理服务间通信
- 面向故障设计(混沌工程)
- 为所有服务实现健康检查
- 使用关联ID追踪请求
- 对API进行版本管理
- 实现完善的监控与告警
- 使用事件驱动架构实现松耦合
- 实现幂等操作
- 采用单服务单数据库模式
❌ DON'T
❌ 避免
- Share databases between services
- Create overly granular services (nanoservices)
- Use distributed transactions (two-phase commit)
- Ignore network latency and failures
- Share domain models between services
- Deploy all services as one unit
- Hardcode service URLs
- Forget to implement authentication/authorization
- Use synchronous calls for long-running operations
- Ignore backward compatibility
- Skip monitoring and logging
- Create circular dependencies between services
- 服务间共享数据库
- 设计过于细分的服务(纳米服务)
- 使用分布式事务(两阶段提交)
- 忽略网络延迟与故障
- 服务间共享领域模型
- 将所有服务作为一个单元部署
- 硬编码服务URL
- 忽略身份认证与授权实现
- 对长时间运行的操作使用同步调用
- 忽略向后兼容性
- 跳过监控与日志
- 服务间创建循环依赖
Common Patterns
常见模式
Pattern 1: Backend for Frontend (BFF)
模式1:前端后端(BFF)
typescript
// mobile-bff/src/api.ts - Optimized for mobile
app.get('/api/home', async (req, res) => {
const [featured, recommendations] = await Promise.all([
productService.getFeatured(5),
recommendationService.getForUser(req.user.id, 10)
]);
res.json({ featured, recommendations });
});
// web-bff/src/api.ts - More data for web
app.get('/api/home', async (req, res) => {
const [featured, recommendations, categories, promotions] = await Promise.all([
productService.getFeatured(20),
recommendationService.getForUser(req.user.id, 50),
categoryService.getAll(),
promotionService.getActive()
]);
res.json({ featured, recommendations, categories, promotions });
});typescript
// mobile-bff/src/api.ts - Optimized for mobile
app.get('/api/home', async (req, res) => {
const [featured, recommendations] = await Promise.all([
productService.getFeatured(5),
recommendationService.getForUser(req.user.id, 10)
]);
res.json({ featured, recommendations });
});
// web-bff/src/api.ts - More data for web
app.get('/api/home', async (req, res) => {
const [featured, recommendations, categories, promotions] = await Promise.all([
productService.getFeatured(20),
recommendationService.getForUser(req.user.id, 50),
categoryService.getAll(),
promotionService.getActive()
]);
res.json({ featured, recommendations, categories, promotions });
});Pattern 2: Sidecar Pattern
模式2:边车模式
yaml
undefinedyaml
undefinedPod with sidecar
Pod with sidecar
apiVersion: v1
kind: Pod
metadata:
name: app-with-sidecar
spec:
containers:
- name: app image: my-app:latest
- name: logging-sidecar
image: fluentd:latest
volumeMounts:
- name: logs mountPath: /logs volumes:
- name: logs emptyDir: {}
undefinedapiVersion: v1
kind: Pod
metadata:
name: app-with-sidecar
spec:
containers:
- name: app image: my-app:latest
- name: logging-sidecar
image: fluentd:latest
volumeMounts:
- name: logs mountPath: /logs volumes:
- name: logs emptyDir: {}
undefinedTools & Resources
工具与资源
- Service Mesh: Istio, Linkerd, Consul Connect
- API Gateway: Kong, Apigee, AWS API Gateway
- Service Discovery: Consul, Eureka, Zookeeper
- Message Queue: RabbitMQ, Apache Kafka, AWS SQS
- Orchestration: Kubernetes, Docker Swarm, Nomad
- Monitoring: Prometheus, Grafana, Datadog
- Tracing: Jaeger, Zipkin, AWS X-Ray
- Circuit Breaker: Hystrix, Resilience4j, Polly
- 服务网格:Istio, Linkerd, Consul Connect
- API网关:Kong, Apigee, AWS API Gateway
- 服务发现:Consul, Eureka, Zookeeper
- 消息队列:RabbitMQ, Apache Kafka, AWS SQS
- 编排工具:Kubernetes, Docker Swarm, Nomad
- 监控工具:Prometheus, Grafana, Datadog
- 追踪工具:Jaeger, Zipkin, AWS X-Ray
- 断路器:Hystrix, Resilience4j, Polly