
API 网关模式
API 网关的作用
客户端请求
|
v
API 网关
| | | |
| | | +-- 速率限制
| | +------ 身份验证/授权
| +---------- 请求/响应转换
+-------------- 路由、负载均衡、熔断
|
v
微服务(用户服务、订单服务、产品服务...)

面向前端的后端(BFF)模式
// Web BFF:聚合针对桌面 Web 优化的数据
app.get('/dashboard', authenticate, async (req, res) => {
const userId = req.user.id;
// 并行从多个服务聚合
const [user, orders, recommendations, notifications] = await Promise.all([
userService.getProfile(userId),
orderService.getRecentOrders(userId, { limit: 5 }),
recommendationService.getForUser(userId, { limit: 6 }),
notificationService.getUnread(userId),
]);
// 为 Web UI 需求塑造数据
res.json({
user: { name: user.name, avatar: user.avatar, plan: user.plan },
recentOrders: orders.map(o => ({ id: o.id, status: o.status, total: o.total, date: o.createdAt })),
recommendations: recommendations.map(r => ({ id: r.id, name: r.name, price: r.price, image: r.imageUrl })),
unreadCount: notifications.filter(n => !n.read).length,
});
});
// Mobile BFF:更少的数据,移动端优化的字段
mobileBFF.get('/dashboard', authenticate, async (req, res) => {
const [user, notifications] = await Promise.all([
userService.getProfile(req.user.id),
notificationService.getUnread(req.user.id),
]);
// 移动端需要更少的数据(注重带宽)
res.json({
name: user.name,
avatar: user.avatarSmall, // 更小的图片
unreadCount: notifications.length,
});
});

请求聚合
// 将多个服务调用聚合为一个 API 调用
app.get('/products/:id/full', async (req, res) => {
const productId = req.params.id;
const [product, inventory, reviews, seller] = await Promise.allSettled([
productService.getProduct(productId),
inventoryService.getStock(productId),
reviewService.getSummary(productId),
sellerService.getSeller(productId),
]);
// 优雅处理部分失败
res.json({
product: product.status === 'fulfilled' ? product.value : null,
inStock: inventory.status === 'fulfilled' ? inventory.value.quantity > 0 : null,
rating: reviews.status === 'fulfilled' ? reviews.value.average : null,
seller: seller.status === 'fulfilled' ? seller.value : null,
});
});

横切关注点
// 身份验证中间件
const authenticate = async (req: Request, res: Response, next: NextFunction) => {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) return res.status(401).json({ error: 'Authentication required' });
try {
req.user = await verifyJWT(token);
next();
} catch {
res.status(401).json({ error: 'Invalid token' });
}
};
// 用于追踪的请求 ID
app.use((req, res, next) => {
req.id = req.headers['x-request-id'] as string || uuid();
res.setHeader('x-request-id', req.id);
next();
});
// 超时中间件
app.use((req, res, next) => {
const timeout = setTimeout(() => {
res.status(504).json({ error: 'Gateway Timeout' });
}, 30000);
res.on('finish', () => clearTimeout(timeout));
next();
});
// 每个下游服务的熔断器
const orderCircuit = new CircuitBreaker({ failureThreshold: 5, timeout: 60000 });
app.get('/orders', authenticate, async (req, res) => {
try {
const orders = await orderCircuit.execute(() => orderService.list(req.user.id));
res.json(orders);
} catch (err) {
if (err.message === 'Circuit breaker is open') {
return res.status(503).json({ error: 'Service temporarily unavailable' });
}
throw err;
}
});
协议转换
// gRPC 到 REST 的网关
import grpc from '@grpc/grpc-js';
const userServiceClient = new UserServiceClient('user-service:50051', grpc.credentials.createInsecure());
app.get('/users/:id', async (req, res) => {
// REST 请求 -> gRPC 调用 -> REST 响应
userServiceClient.getUser({ id: req.params.id }, (err, user) => {
if (err) return res.status(err.code === 5 ? 404 : 500).json({ error: err.message });
res.json({ id: user.id, name: user.name, email: user.email });
});
});
API 网关是微服务的前门——保持其轻量并专注于路由关注点。