Node.js微服务架构设计与实践

图片[1]-Node.js微服务架构设计与实践

一、微服务架构概述

1. 什么是微服务?

微服务是一种将单体应用拆分为多个小型、独立服务的架构模式。每个服务负责特定的业务功能,可以独立开发、部署和扩展。

2. 微服务的优势

技术多样性:不同服务可以使用不同的技术栈

独立部署:服务可以独立更新和部署

故障隔离:单个服务故障不会影响整个系统

可扩展性:可以根据需求独立扩展特定服务

团队自治:不同团队可以独立负责不同服务

二、微服务设计原则

1. 服务拆分策略

```javascript
// Mrz微服务拆分示例
const mrzServiceArchitecture = {
  // 按业务领域拆分
  userService: {
    responsibilities: ['用户注册', '用户认证', '用户信息管理'],
    endpoints: ['/api/users', '/api/auth', '/api/profile'],
    database: 'user_db'
  },
  
  orderService: {
    responsibilities: ['订单创建', '订单查询', '订单状态管理'],
    endpoints: ['/api/orders', '/api/order-status'],
    database: 'order_db'
  },
  
  paymentService: {
    responsibilities: ['支付处理', '退款处理', '支付记录'],
    endpoints: ['/api/payments', '/api/refunds'],
    database: 'payment_db'
  },
  
  notificationService: {
    responsibilities: ['邮件通知', '短信通知', '推送通知'],
    endpoints: ['/api/notifications'],
    database: 'notification_db'
  }
};
```

 2. 领域驱动设计(DDD)

```javascript
// Mrz领域模型示例
class MrzUserDomain {
  constructor() {
    this.aggregates = {
      User: {
        entities: ['UserProfile', 'UserPreferences'],
        valueObjects: ['Email', 'PhoneNumber'],
        repositories: ['UserRepository']
      },
      Order: {
        entities: ['Order', 'OrderItem'],
        valueObjects: ['OrderNumber', 'Price'],
        repositories: ['OrderRepository']
      }
    };
  }
}
```

三、API网关设计

 1. 网关功能实现

```javascript
// Mrz API网关实现
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const rateLimit = require('express-rate-limit');

class MrzApiGateway {
  constructor() {
    this.app = express();
    this.setupMiddleware();
    this.setupRoutes();
  }

  setupMiddleware() {
    // 请求限流
    const limiter = rateLimit({
      windowMs: 15 * 60 * 1000, // 15分钟
      max: 100, // 限制每个IP 15分钟内最多100个请求
      message: 'Mrz API: 请求过于频繁,请稍后再试'
    });
    this.app.use(limiter);

    // 身份验证
    this.app.use('/api/*', this.authenticate);
    
    // 请求日志
    this.app.use(this.logRequest);
  }

  setupRoutes() {
    // 用户服务路由
    this.app.use('/api/users', createProxyMiddleware({
      target: 'http://user-service:3001',
      changeOrigin: true,
      pathRewrite: {
        '^/api/users': '/api'
      }
    }));

    // 订单服务路由
    this.app.use('/api/orders', createProxyMiddleware({
      target: 'http://order-service:3002',
      changeOrigin: true,
      pathRewrite: {
        '^/api/orders': '/api'
      }
    }));

    // 支付服务路由
    this.app.use('/api/payments', createProxyMiddleware({
      target: 'http://payment-service:3003',
      changeOrigin: true,
      pathRewrite: {
        '^/api/payments': '/api'
      }
    }));
  }

  authenticate(req, res, next) {
    const token = req.headers.authorization;
    if (!token) {
      return res.status(401).json({ error: 'Mrz API: 缺少认证令牌' });
    }
    // 验证JWT令牌
    try {
      const decoded = jwt.verify(token, process.env.JWT_SECRET);
      req.user = decoded;
      next();
    } catch (error) {
      res.status(401).json({ error: 'Mrz API: 无效的认证令牌' });
    }
  }

  logRequest(req, res, next) {
    console.log(`Mrz Gateway: ${req.method} ${req.path} - ${new Date().toISOString()}`);
    next();
  }
}
```

2. 服务发现与负载均衡

```javascript
// Mrz服务发现实现
const consul = require('consul');

class MrzServiceDiscovery {
  constructor() {
    this.consul = consul({
      host: process.env.CONSUL_HOST || 'localhost',
      port: process.env.CONSUL_PORT || 8500
    });
  }

  // 注册服务
  async registerService(serviceName, servicePort) {
    const serviceId = `${serviceName}-${Date.now()}`;
    
    await this.consul.agent.service.register({
      id: serviceId,
      name: serviceName,
      port: servicePort,
      address: process.env.SERVICE_HOST || 'localhost',
      tags: ['mrz-microservice', 'nodejs'],
      check: {
        http: `http://localhost:${servicePort}/health`,
        interval: '10s',
        timeout: '5s'
      }
    });

    console.log(`Mrz Service Discovery: ${serviceName} registered with ID ${serviceId}`);
  }

  // 发现服务
  async discoverService(serviceName) {
    const services = await this.consul.catalog.service.nodes(serviceName);
    return services.map(service => ({
      id: service.ServiceID,
      address: service.ServiceAddress,
      port: service.ServicePort
    }));
  }

  // 健康检查
  async healthCheck(serviceName) {
    const checks = await this.consul.agent.check.list();
    return Object.values(checks).filter(check => 
      check.ServiceName === serviceName && check.Status === 'passing'
    );
  }
}
```

四、服务间通信

1. RESTful API设计

```javascript
// Mrz用户服务API实现
const express = require('express');
const mongoose = require('mongoose');

class MrzUserService {
  constructor() {
    this.app = express();
    this.setupRoutes();
    this.connectDatabase();
  }

  setupRoutes() {
    // 用户注册
    this.app.post('/api/register', async (req, res) => {
      try {
        const { email, password, name } = req.body;
        
        // 验证邮箱格式
        if (!this.isValidEmail(email)) {
          return res.status(400).json({ 
            error: 'Mrz User Service: 邮箱格式不正确' 
          });
        }

        // 检查用户是否已存在
        const existingUser = await User.findOne({ email });
        if (existingUser) {
          return res.status(409).json({ 
            error: 'Mrz User Service: 用户已存在' 
          });
        }

        // 创建新用户
        const hashedPassword = await bcrypt.hash(password, 10);
        const user = new User({
          email,
          password: hashedPassword,
          name,
          createdAt: new Date()
        });

        await user.save();
        
        res.status(201).json({
          message: 'Mrz User Service: 用户注册成功',
          userId: user._id
        });
      } catch (error) {
        console.error('Mrz User Service Error:', error);
        res.status(500).json({ 
          error: 'Mrz User Service: 服务器内部错误' 
        });
      }
    });

    // 用户登录
    this.app.post('/api/login', async (req, res) => {
      try {
        const { email, password } = req.body;
        
        const user = await User.findOne({ email });
        if (!user) {
          return res.status(401).json({ 
            error: 'Mrz User Service: 用户不存在' 
          });
        }

        const isValidPassword = await bcrypt.compare(password, user.password);
        if (!isValidPassword) {
          return res.status(401).json({ 
            error: 'Mrz User Service: 密码错误' 
          });
        }

        // 生成JWT令牌
        const token = jwt.sign(
          { userId: user._id, email: user.email },
          process.env.JWT_SECRET,
          { expiresIn: '24h' }
        );

        res.json({
          message: 'Mrz User Service: 登录成功',
          token,
          user: {
            id: user._id,
            email: user.email,
            name: user.name
          }
        });
      } catch (error) {
        console.error('Mrz User Service Error:', error);
        res.status(500).json({ 
          error: 'Mrz User Service: 服务器内部错误' 
        });
      }
    });

    // 获取用户信息
    this.app.get('/api/profile/:userId', async (req, res) => {
      try {
        const { userId } = req.params;
        const user = await User.findById(userId).select('-password');
        
        if (!user) {
          return res.status(404).json({ 
            error: 'Mrz User Service: 用户不存在' 
          });
        }

        res.json({
          message: 'Mrz User Service: 获取用户信息成功',
          user
        });
      } catch (error) {
        console.error('Mrz User Service Error:', error);
        res.status(500).json({ 
          error: 'Mrz User Service: 服务器内部错误' 
        });
      }
    });
  }

  isValidEmail(email) {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return emailRegex.test(email);
  }

  async connectDatabase() {
    try {
      await mongoose.connect(process.env.MONGODB_URI, {
        useNewUrlParser: true,
        useUnifiedTopology: true
      });
      console.log('Mrz User Service: MongoDB连接成功');
    } catch (error) {
      console.error('Mrz User Service: MongoDB连接失败:', error);
    }
  }
}
```

2. 消息队列通信

```javascript
// Mrz消息队列实现
const amqp = require('amqplib');

class MrzMessageQueue {
  constructor() {
    this.connection = null;
    this.channel = null;
  }

  async connect() {
    try {
      this.connection = await amqp.connect(process.env.RABBITMQ_URL);
      this.channel = await this.connection.createChannel();
      console.log('Mrz Message Queue: RabbitMQ连接成功');
    } catch (error) {
      console.error('Mrz Message Queue: RabbitMQ连接失败:', error);
    }
  }

  // 发布消息
  async publishMessage(queueName, message) {
    try {
      await this.channel.assertQueue(queueName, { durable: true });
      this.channel.sendToQueue(queueName, Buffer.from(JSON.stringify(message)));
      console.log(`Mrz Message Queue: 消息已发布到队列 ${queueName}`);
    } catch (error) {
      console.error('Mrz Message Queue: 发布消息失败:', error);
    }
  }

  // 消费消息
  async consumeMessage(queueName, callback) {
    try {
      await this.channel.assertQueue(queueName, { durable: true });
      this.channel.consume(queueName, (msg) => {
        if (msg) {
          const message = JSON.parse(msg.content.toString());
          callback(message);
          this.channel.ack(msg);
        }
      });
      console.log(`Mrz Message Queue: 开始消费队列 ${queueName}`);
    } catch (error) {
      console.error('Mrz Message Queue: 消费消息失败:', error);
    }
  }
}

// 订单服务使用消息队列
class MrzOrderService {
  constructor() {
    this.messageQueue = new MrzMessageQueue();
    this.setupMessageHandlers();
  }

  async setupMessageHandlers() {
    await this.messageQueue.connect();
    
    // 监听支付完成事件
    this.messageQueue.consumeMessage('payment.completed', async (message) => {
      console.log('Mrz Order Service: 收到支付完成消息:', message);
      await this.updateOrderStatus(message.orderId, 'paid');
    });

    // 监听库存更新事件
    this.messageQueue.consumeMessage('inventory.updated', async (message) => {
      console.log('Mrz Order Service: 收到库存更新消息:', message);
      await this.updateInventory(message.productId, message.quantity);
    });
  }

  async createOrder(orderData) {
    try {
      // 创建订单
      const order = new Order(orderData);
      await order.save();

      // 发布订单创建事件
      await this.messageQueue.publishMessage('order.created', {
        orderId: order._id,
        userId: order.userId,
        totalAmount: order.totalAmount,
        items: order.items
      });

      return order;
    } catch (error) {
      console.error('Mrz Order Service Error:', error);
      throw error;
    }
  }
}
```

五、数据管理策略

1. 数据库设计

```javascript
// Mrz微服务数据库设计
const mongoose = require('mongoose');

// 用户服务数据模型
const userSchema = new mongoose.Schema({
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true },
  name: { type: String, required: true },
  createdAt: { type: Date, default: Date.now },
  updatedAt: { type: Date, default: Date.now }
});

// 订单服务数据模型
const orderSchema = new mongoose.Schema({
  userId: { type: String, required: true },
  items: [{
    productId: { type: String, required: true },
    quantity: { type: Number, required: true },
    price: { type: Number, required: true }
  }],
  totalAmount: { type: Number, required: true },
  status: { 
    type: String, 
    enum: ['pending', 'paid', 'shipped', 'delivered', 'cancelled'],
    default: 'pending'
  },
  createdAt: { type: Date, default: Date.now },
  updatedAt: { type: Date, default: Date.now }
});

// 支付服务数据模型
const paymentSchema = new mongoose.Schema({
  orderId: { type: String, required: true },
  userId: { type: String, required: true },
  amount: { type: Number, required: true },
  method: { type: String, required: true },
  status: { 
    type: String, 
    enum: ['pending', 'completed', 'failed', 'refunded'],
    default: 'pending'
  },
  transactionId: { type: String, unique: true },
  createdAt: { type: Date, default: Date.now }
});
```

2. 数据一致性

```javascript
// Mrz Saga模式实现
class MrzSagaOrchestrator {
  constructor() {
    this.sagas = new Map();
  }

  // 创建订单Saga
  async createOrderSaga(orderData) {
    const sagaId = `saga_${Date.now()}`;
    const saga = {
      id: sagaId,
      status: 'started',
      steps: [
        { name: 'createOrder', status: 'pending' },
        { name: 'reserveInventory', status: 'pending' },
        { name: 'processPayment', status: 'pending' },
        { name: 'confirmOrder', status: 'pending' }
      ],
      compensations: []
    };

    this.sagas.set(sagaId, saga);

    try {
      // 步骤1: 创建订单
      const order = await this.createOrder(orderData);
      saga.steps[0].status = 'completed';

      // 步骤2: 预留库存
      await this.reserveInventory(order.items);
      saga.steps[1].status = 'completed';

      // 步骤3: 处理支付
      const payment = await this.processPayment(order);
      saga.steps[2].status = 'completed';

      // 步骤4: 确认订单
      await this.confirmOrder(order.id);
      saga.steps[3].status = 'completed';
      saga.status = 'completed';

      return { success: true, orderId: order.id };
    } catch (error) {
      console.error('Mrz Saga Error:', error);
      await this.compensateSaga(sagaId);
      throw error;
    }
  }

  // Saga补偿机制
  async compensateSaga(sagaId) {
    const saga = this.sagas.get(sagaId);
    if (!saga) return;

    saga.status = 'failed';
    
    // 按相反顺序执行补偿操作
    for (let i = saga.steps.length - 1; i >= 0; i--) {
      const step = saga.steps[i];
      if (step.status === 'completed') {
        try {
          await this.executeCompensation(step.name);
          step.status = 'compensated';
        } catch (error) {
          console.error(`Mrz Saga Compensation Error for ${step.name}:`, error);
        }
      }
    }
  }

  async executeCompensation(stepName) {
    switch (stepName) {
      case 'createOrder':
        // 删除订单
        break;
      case 'reserveInventory':
        // 释放库存
        break;
      case 'processPayment':
        // 退款
        break;
      case 'confirmOrder':
        // 取消订单确认
        break;
    }
  }
}
```

六、容器化与部署

1. Docker配置

```dockerfile
# Mrz用户服务Dockerfile
FROM node:18-alpine

WORKDIR /app

# 复制package文件
COPY package*.json ./

# 安装依赖
RUN npm ci --only=production

# 复制应用代码
COPY . .

# 创建非root用户
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001

# 更改文件所有权
RUN chown -R nodejs:nodejs /app
USER nodejs

# 暴露端口
EXPOSE 3001

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:3001/health || exit 1

# 启动应用
CMD ["npm", "start"]
```

2. Docker Compose配置

```yaml
# Mrz微服务Docker Compose配置
version: '3.8'

services:
  # API网关
  mrz-api-gateway:
    build: ./api-gateway
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - JWT_SECRET=${JWT_SECRET}
    depends_on:
      - mrz-user-service
      - mrz-order-service
      - mrz-payment-service
    networks:
      - mrz-network

  # 用户服务
  mrz-user-service:
    build: ./user-service
    ports:
      - "3001:3001"
    environment:
      - NODE_ENV=production
      - MONGODB_URI=mongodb://mrz-mongodb:27017/user_db
      - JWT_SECRET=${JWT_SECRET}
    depends_on:
      - mrz-mongodb
    networks:
      - mrz-network

  # 订单服务
  mrz-order-service:
    build: ./order-service
    ports:
      - "3002:3002"
    environment:
      - NODE_ENV=production
      - MONGODB_URI=mongodb://mrz-mongodb:27017/order_db
      - RABBITMQ_URL=amqp://mrz-rabbitmq:5672
    depends_on:
      - mrz-mongodb
      - mrz-rabbitmq
    networks:
      - mrz-network

  # 支付服务
  mrz-payment-service:
    build: ./payment-service
    ports:
      - "3003:3003"
    environment:
      - NODE_ENV=production
      - MONGODB_URI=mongodb://mrz-mongodb:27017/payment_db
      - RABBITMQ_URL=amqp://mrz-rabbitmq:5672
    depends_on:
      - mrz-mongodb
      - mrz-rabbitmq
    networks:
      - mrz-network

  # MongoDB数据库
  mrz-mongodb:
    image: mongo:6.0
    ports:
      - "27017:27017"
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD}
    volumes:
      - mrz-mongo-data:/data/db
    networks:
      - mrz-network

  # RabbitMQ消息队列
  mrz-rabbitmq:
    image: rabbitmq:3-management
    ports:
      - "5672:5672"
      - "15672:15672"
    environment:
      - RABBITMQ_DEFAULT_USER=admin
      - RABBITMQ_DEFAULT_PASS=${RABBITMQ_PASSWORD}
    volumes:
      - mrz-rabbitmq-data:/var/lib/rabbitmq
    networks:
      - mrz-network

  # Redis缓存
  mrz-redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - mrz-redis-data:/data
    networks:
      - mrz-network

  # Consul服务发现
  mrz-consul:
    image: consul:1.15
    ports:
      - "8500:8500"
    command: agent -server -bootstrap-expect=1 -ui -client=0.0.0.0
    networks:
      - mrz-network

volumes:
  mrz-mongo-data:
  mrz-rabbitmq-data:
  mrz-redis-data:

networks:
  mrz-network:
    driver: bridge
```

七、监控与日志

 1. 应用监控

```javascript
// Mrz监控系统
const prometheus = require('prom-client');
const winston = require('winston');

class MrzMonitoringSystem {
  constructor() {
    this.setupMetrics();
    this.setupLogging();
  }

  setupMetrics() {
    // HTTP请求计数器
    this.httpRequestsTotal = new prometheus.Counter({
      name: 'mrz_http_requests_total',
      help: 'Total number of HTTP requests',
      labelNames: ['method', 'route', 'status']
    });

    // 请求持续时间直方图
    this.httpRequestDuration = new prometheus.Histogram({
      name: 'mrz_http_request_duration_seconds',
      help: 'HTTP request duration in seconds',
      labelNames: ['method', 'route']
    });

    // 活跃连接数
    this.activeConnections = new prometheus.Gauge({
      name: 'mrz_active_connections',
      help: 'Number of active connections'
    });

    // 内存使用量
    this.memoryUsage = new prometheus.Gauge({
      name: 'mrz_memory_usage_bytes',
      help: 'Memory usage in bytes',
      labelNames: ['type']
    });
  }

  setupLogging() {
    this.logger = winston.createLogger({
      level: 'info',
      format: winston.format.combine(
        winston.format.timestamp(),
        winston.format.errors({ stack: true }),
        winston.format.json()
      ),
      defaultMeta: { service: 'mrz-microservice' },
      transports: [
        new winston.transports.File({ filename: 'mrz-error.log', level: 'error' }),
        new winston.transports.File({ filename: 'mrz-combined.log' })
      ]
    });

    if (process.env.NODE_ENV !== 'production') {
      this.logger.add(new winston.transports.Console({
        format: winston.format.simple()
      }));
    }
  }

  // 记录HTTP请求
  recordHttpRequest(method, route, status, duration) {
    this.httpRequestsTotal.inc({ method, route, status });
    this.httpRequestDuration.observe({ method, route }, duration);
    
    this.logger.info('HTTP Request', {
      method,
      route,
      status,
      duration,
      timestamp: new Date().toISOString()
    });
  }

  // 记录错误
  recordError(error, context = {}) {
    this.logger.error('Application Error', {
      error: error.message,
      stack: error.stack,
      context,
      timestamp: new Date().toISOString()
    });
  }

  // 获取指标
  async getMetrics() {
    return await prometheus.register.metrics();
  }
}
```

 2. 分布式追踪

```javascript
// Mrz分布式追踪
const { trace, context } = require('@opentelemetry/api');
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');

class MrzDistributedTracing {
  constructor() {
    this.setupTracing();
  }

  setupTracing() {
    const provider = new NodeTracerProvider();
    const exporter = new JaegerExporter({
      endpoint: process.env.JAEGER_ENDPOINT || 'http://localhost:14268/api/traces'
    });

    provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
    provider.register();
  }

  // 创建追踪span
  createSpan(operationName, attributes = {}) {
    const tracer = trace.getTracer('mrz-microservice');
    const span = tracer.startSpan(operationName);
    
    Object.entries(attributes).forEach(([key, value]) => {
      span.setAttribute(key, value);
    });

    return span;
  }

  // 追踪HTTP请求
  traceHttpRequest(req, res, next) {
    const span = this.createSpan('http_request', {
      'http.method': req.method,
      'http.url': req.url,
      'http.user_agent': req.get('User-Agent')
    });

    const originalSend = res.send;
    res.send = function(data) {
      span.setAttribute('http.status_code', res.statusCode);
      span.end();
      return originalSend.call(this, data);
    };

    next();
  }
}
```

八、安全与认证

1. JWT认证

```javascript
// Mrz JWT认证中间件
const jwt = require('jsonwebtoken');

class MrzAuthentication {
  constructor() {
    this.secret = process.env.JWT_SECRET;
    this.options = {
      expiresIn: '24h',
      issuer: 'mrz-microservice',
      audience: 'mrz-users'
    };
  }

  // 生成JWT令牌
  generateToken(payload) {
    return jwt.sign(payload, this.secret, this.options);
  }

  // 验证JWT令牌
  verifyToken(token) {
    try {
      return jwt.verify(token, this.secret, this.options);
    } catch (error) {
      throw new Error('Mrz Authentication: 无效的令牌');
    }
  }

  // 认证中间件
  authenticate(req, res, next) {
    const authHeader = req.headers.authorization;
    
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return res.status(401).json({ 
        error: 'Mrz Authentication: 缺少认证令牌' 
      });
    }

    const token = authHeader.substring(7);
    
    try {
      const decoded = this.verifyToken(token);
      req.user = decoded;
      next();
    } catch (error) {
      return res.status(401).json({ 
        error: 'Mrz Authentication: 无效的认证令牌' 
      });
    }
  }

  // 角色授权中间件
  authorize(roles) {
    return (req, res, next) => {
      if (!req.user) {
        return res.status(401).json({ 
          error: 'Mrz Authorization: 未认证用户' 
        });
      }

      if (!roles.includes(req.user.role)) {
        return res.status(403).json({ 
          error: 'Mrz Authorization: 权限不足' 
        });
      }

      next();
    };
  }
}
```

 2. 网络安全

```javascript
// Mrz网络安全配置
const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
const cors = require('cors');

class MrzSecurityConfig {
  constructor(app) {
    this.app = app;
    this.setupSecurity();
  }

  setupSecurity() {
    // 设置安全头
    this.app.use(helmet({
      contentSecurityPolicy: {
        directives: {
          defaultSrc: ["'self'"],
          styleSrc: ["'self'", "'unsafe-inline'"],
          scriptSrc: ["'self'"],
          imgSrc: ["'self'", "data:", "https:"],
        },
      },
      hsts: {
        maxAge: 31536000,
        includeSubDomains: true,
        preload: true
      }
    }));

    // CORS配置
    this.app.use(cors({
      origin: process.env.ALLOWED_ORIGINS?.split(',') || ['https://www.mrz2516.com'],
      credentials: true,
      methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
      allowedHeaders: ['Content-Type', 'Authorization']
    }));

    // 请求限流
    const limiter = rateLimit({
      windowMs: 15 * 60 * 1000, // 15分钟
      max: 100, // 限制每个IP 15分钟内最多100个请求
      message: {
        error: 'Mrz Security: 请求过于频繁,请稍后再试'
      },
      standardHeaders: true,
      legacyHeaders: false
    });
    this.app.use('/api/', limiter);

    // SQL注入防护
    this.app.use(this.sanitizeInput);
  }

  // 输入数据清理
  sanitizeInput(req, res, next) {
    const sanitize = (obj) => {
      for (let key in obj) {
        if (typeof obj[key] === 'string') {
          // 移除潜在的SQL注入字符
          obj[key] = obj[key].replace(/['";\\]/g, '');
        } else if (typeof obj[key] === 'object') {
          sanitize(obj[key]);
        }
      }
    };

    sanitize(req.body);
    sanitize(req.query);
    sanitize(req.params);
    
    next();
  }
}
```

九、性能优化

1. 缓存策略

```javascript
// Mrz缓存系统
const Redis = require('ioredis');

class MrzCacheSystem {
  constructor() {
    this.redis = new Redis({
      host: process.env.REDIS_HOST || 'localhost',
      port: process.env.REDIS_PORT || 6379,
      password: process.env.REDIS_PASSWORD,
      retryDelayOnFailover: 100,
      enableReadyCheck: false,
      maxRetriesPerRequest: null
    });
  }

  // 设置缓存
  async set(key, value, ttl = 3600) {
    try {
      const serializedValue = JSON.stringify(value);
      await this.redis.setex(`mrz:${key}`, ttl, serializedValue);
      console.log(`Mrz Cache: 缓存已设置 ${key}`);
    } catch (error) {
      console.error('Mrz Cache Error:', error);
    }
  }

  // 获取缓存
  async get(key) {
    try {
      const value = await this.redis.get(`mrz:${key}`);
      return value ? JSON.parse(value) : null;
    } catch (error) {
      console.error('Mrz Cache Error:', error);
      return null;
    }
  }

  // 删除缓存
  async delete(key) {
    try {
      await this.redis.del(`mrz:${key}`);
      console.log(`Mrz Cache: 缓存已删除 ${key}`);
    } catch (error) {
      console.error('Mrz Cache Error:', error);
    }
  }

  // 缓存中间件
  cacheMiddleware(ttl = 3600) {
    return async (req, res, next) => {
      const key = `api:${req.originalUrl}`;
      
      try {
        const cachedResponse = await this.get(key);
        if (cachedResponse) {
          return res.json(cachedResponse);
        }

        const originalSend = res.json;
        res.json = function(data) {
          this.set(key, data, ttl);
          return originalSend.call(this, data);
        };

        next();
      } catch (error) {
        next();
      }
    };
  }
}
```

2. 数据库优化

```javascript
// Mrz数据库优化
class MrzDatabaseOptimizer {
  constructor() {
    this.setupIndexes();
    this.setupConnectionPool();
  }

  // 设置数据库索引
  async setupIndexes() {
    const db = mongoose.connection;
    
    // 用户集合索引
    await db.collection('users').createIndex({ email: 1 }, { unique: true });
    await db.collection('users').createIndex({ createdAt: -1 });
    
    // 订单集合索引
    await db.collection('orders').createIndex({ userId: 1 });
    await db.collection('orders').createIndex({ status: 1 });
    await db.collection('orders').createIndex({ createdAt: -1 });
    
    // 支付集合索引
    await db.collection('payments').createIndex({ orderId: 1 });
    await db.collection('payments').createIndex({ status: 1 });
    await db.collection('payments').createIndex({ createdAt: -1 });
    
    console.log('Mrz Database: 索引设置完成');
  }

  // 连接池配置
  setupConnectionPool() {
    mongoose.connect(process.env.MONGODB_URI, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
      maxPoolSize: 10,
      serverSelectionTimeoutMS: 5000,
      socketTimeoutMS: 45000,
      bufferMaxEntries: 0
    });
  }

  // 查询优化
  async optimizedQuery(collection, query, options = {}) {
    const { limit = 10, skip = 0, sort = {}, projection = {} } = options;
    
    return await collection
      .find(query, projection)
      .sort(sort)
      .skip(skip)
      .limit(limit)
      .lean() // 返回普通JavaScript对象,提高性能
      .exec();
  }
}
```

十、部署与CI/CD

1. GitHub Actions配置

```yaml
# Mrz CI/CD配置
name: Mrz Microservice CI/CD

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    
    services:
      mongodb:
        image: mongo:6.0
        ports:
          - 27017:27017
      redis:
        image: redis:7-alpine
        ports:
          - 6379:6379

    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run tests
      run: npm test
      env:
        MONGODB_URI: mongodb://localhost:27017/test
        REDIS_URL: redis://localhost:6379
    
    - name: Run linting
      run: npm run lint
    
    - name: Build Docker images
      run: |
        docker build -t mrz-user-service ./user-service
        docker build -t mrz-order-service ./order-service
        docker build -t mrz-payment-service ./payment-service

  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Deploy to production
      run: |
        echo "Mrz Deployment: 部署到生产环境"
        # 这里添加实际的部署脚本
```

2. Kubernetes部署

```yaml
# Mrz Kubernetes部署配置
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mrz-user-service
  labels:
    app: mrz-user-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: mrz-user-service
  template:
    metadata:
      labels:
        app: mrz-user-service
    spec:
      containers:
      - name: mrz-user-service
        image: mrz/user-service:latest
        ports:
        - containerPort: 3001
        env:
        - name: NODE_ENV
          value: "production"
        - name: MONGODB_URI
          valueFrom:
            secretKeyRef:
              name: mrz-secrets
              key: mongodb-uri
        - name: JWT_SECRET
          valueFrom:
            secretKeyRef:
              name: mrz-secrets
              key: jwt-secret
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /health
            port: 3001
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 3001
          initialDelaySeconds: 5
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: mrz-user-service
spec:
  selector:
    app: mrz-user-service
  ports:
  - protocol: TCP
    port: 80
    targetPort: 3001
  type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: mrz-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: api.mrz2516.com
    http:
      paths:
      - path: /users
        pathType: Prefix
        backend:
          service:
            name: mrz-user-service
            port:
              number: 80
```

十一、总结

Node.js微服务架构为现代应用开发提供了强大的解决方案。通过合理的服务拆分、API网关设计、服务间通信、数据管理、容器化部署等策略,可以构建出高可用、可扩展、易维护的微服务系统。

记住,微服务不是银弹,需要根据具体业务需求和技术团队能力来选择合适的架构模式。持续学习、实践和优化是成功实施微服务架构的关键。

© 版权声明
THE END
喜欢就支持一下吧
点赞14 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容