Node.js Web Server 开发指南

Node.js Web Server Development Guide

概述 (Overview)

Node.js是基于Chrome V8引擎的JavaScript运行时环境,广泛用于构建高性能的Web服务器和API。Node.js采用事件驱动、非阻塞I/O模型,特别适合I/O密集型应用。配合Express、Koa、Fastify等Web框架,Node.js可以快速构建现代化的Web应用和微服务。

Node.js is a JavaScript runtime built on Chrome's V8 engine, widely used for building high-performance web servers and APIs. Node.js uses an event-driven, non-blocking I/O model, making it particularly suitable for I/O-intensive applications. Combined with web frameworks like Express, Koa, and Fastify, Node.js can quickly build modern web applications and microservices.

核心特性 (Core Features)

⚡ 异步非阻塞 (Asynchronous Non-blocking)

  • 事件驱动架构
  • 非阻塞I/O操作
  • 单线程事件循环
  • 高并发处理能力
  • 异步编程模型

🚀 高性能 (High Performance)

  • V8引擎JIT编译
  • 快速的JavaScript执行
  • 高效的内存管理
  • 轻量级进程
  • 优秀的吞吐量

📦 丰富的生态系统 (Rich Ecosystem)

  • NPM包管理器(200万+包)
  • 活跃的开源社区
  • 丰富的Web框架选择
  • 完善的工具链
  • 持续的技术创新

🌐 全栈JavaScript (Full-stack JavaScript)

  • 前后端语言统一
  • 代码复用
  • JSON原生支持
  • 降低学习成本
  • 提高开发效率

Express.js (最流行)

const express = require('express');
const app = express();

// 中间件
app.use(express.json());
app.use(express.static('public'));

// 路由
app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.get('/api/users/:id', (req, res) => {
  const { id } = req.params;
  res.json({ id, name: 'John Doe' });
});

// 错误处理
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

特点:

  • 最成熟、使用最广泛
  • 中间件生态丰富
  • 学习曲线平缓
  • 社区资源丰富

Koa.js (新一代)

const Koa = require('koa');
const Router = require('@koa/router');
const app = new Koa();
const router = new Router();

// 错误处理中间件
app.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    ctx.status = err.status || 500;
    ctx.body = { error: err.message };
    ctx.app.emit('error', err, ctx);
  }
});

// 路由
router.get('/', async (ctx) => {
  ctx.body = 'Hello World!';
});

router.get('/api/users/:id', async (ctx) => {
  const { id } = ctx.params;
  ctx.body = { id, name: 'John Doe' };
});

app.use(router.routes());
app.use(router.allowedMethods());

app.listen(3000);

特点:

  • Express团队开发
  • async/await原生支持
  • 更小更优雅
  • 现代化设计

Fastify (高性能)

const fastify = require('fastify')({ logger: true });

// Schema验证
fastify.get('/api/users/:id', {
  schema: {
    params: {
      type: 'object',
      properties: {
        id: { type: 'string' }
      }
    },
    response: {
      200: {
        type: 'object',
        properties: {
          id: { type: 'string' },
          name: { type: 'string' }
        }
      }
    }
  }
}, async (request, reply) => {
  const { id } = request.params;
  return { id, name: 'John Doe' };
});

// 插件
fastify.register(require('@fastify/cors'));
fastify.register(require('@fastify/helmet'));

fastify.listen({ port: 3000 }, (err) => {
  if (err) {
    fastify.log.error(err);
    process.exit(1);
  }
});

特点:

  • 性能卓越(最快的框架之一)
  • 内置JSON Schema验证
  • 插件架构
  • TypeScript友好
  • 低开销

NestJS (企业级)

// app.controller.ts
import { Controller, Get, Param } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }

  @Get('api/users/:id')
  getUser(@Param('id') id: string) {
    return { id, name: 'John Doe' };
  }
}

// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();

特点:

  • TypeScript优先
  • 模块化架构
  • 依赖注入
  • Angular风格
  • 适合大型项目

HTTP服务器实现 (HTTP Server Implementation)

原生HTTP模块

const http = require('http');

const server = http.createServer((req, res) => {
  // 解析URL
  const url = new URL(req.url, `http://${req.headers.host}`);

  // 路由处理
  if (req.method === 'GET' && url.pathname === '/') {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end('<h1>Hello World!</h1>');
  } else if (req.method === 'GET' && url.pathname === '/api/data') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ message: 'Success', data: [] }));
  } else {
    res.writeHead(404, { 'Content-Type': 'text/plain' });
    res.end('404 Not Found');
  }
});

server.listen(3000, () => {
  console.log('Server listening on port 3000');
});

HTTPS服务器

const https = require('https');
const fs = require('fs');

const options = {
  key: fs.readFileSync('private-key.pem'),
  cert: fs.readFileSync('certificate.pem')
};

const server = https.createServer(options, (req, res) => {
  res.writeHead(200);
  res.end('Secure Hello World!');
});

server.listen(443);

HTTP/2服务器

const http2 = require('http2');
const fs = require('fs');

const server = http2.createSecureServer({
  key: fs.readFileSync('private-key.pem'),
  cert: fs.readFileSync('certificate.pem')
});

server.on('stream', (stream, headers) => {
  stream.respond({
    'content-type': 'text/html; charset=utf-8',
    ':status': 200
  });
  stream.end('<h1>Hello HTTP/2!</h1>');
});

server.listen(443);

中间件系统 (Middleware System)

Express中间件示例

const express = require('express');
const app = express();

// 日志中间件
app.use((req, res, next) => {
  console.log(`${new Date().toISOString()} - ${req.method} ${req.path}`);
  next();
});

// 认证中间件
const authenticate = (req, res, next) => {
  const token = req.headers.authorization;
  if (!token) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  // 验证token
  next();
};

// CORS中间件
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  next();
});

// 速率限制中间件
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15分钟
  max: 100 // 最多100个请求
});
app.use('/api/', limiter);

// 使用认证中间件保护路由
app.get('/api/protected', authenticate, (req, res) => {
  res.json({ message: 'Protected resource' });
});

RESTful API开发 (RESTful API Development)

完整的CRUD API示例

const express = require('express');
const app = express();

app.use(express.json());

// 模拟数据库
let users = [
  { id: 1, name: 'John Doe', email: 'john@example.com' },
  { id: 2, name: 'Jane Smith', email: 'jane@example.com' }
];

// GET - 获取所有用户
app.get('/api/users', (req, res) => {
  res.json(users);
});

// GET - 获取单个用户
app.get('/api/users/:id', (req, res) => {
  const user = users.find(u => u.id === parseInt(req.params.id));
  if (!user) {
    return res.status(404).json({ error: 'User not found' });
  }
  res.json(user);
});

// POST - 创建用户
app.post('/api/users', (req, res) => {
  const { name, email } = req.body;

  if (!name || !email) {
    return res.status(400).json({ error: 'Name and email required' });
  }

  const newUser = {
    id: users.length + 1,
    name,
    email
  };

  users.push(newUser);
  res.status(201).json(newUser);
});

// PUT - 更新用户
app.put('/api/users/:id', (req, res) => {
  const user = users.find(u => u.id === parseInt(req.params.id));
  if (!user) {
    return res.status(404).json({ error: 'User not found' });
  }

  const { name, email } = req.body;
  if (name) user.name = name;
  if (email) user.email = email;

  res.json(user);
});

// DELETE - 删除用户
app.delete('/api/users/:id', (req, res) => {
  const index = users.findIndex(u => u.id === parseInt(req.params.id));
  if (index === -1) {
    return res.status(404).json({ error: 'User not found' });
  }

  users.splice(index, 1);
  res.status(204).send();
});

app.listen(3000);

数据库集成 (Database Integration)

MongoDB (Mongoose)

const mongoose = require('mongoose');

// 连接数据库
mongoose.connect('mongodb://localhost:27017/myapp', {
  useNewUrlParser: true,
  useUnifiedTopology: true
});

// 定义模型
const User = mongoose.model('User', {
  name: { type: String, required: true },
  email: { type: String, required: true, unique: true },
  createdAt: { type: Date, default: Date.now }
});

// CRUD操作
app.post('/api/users', async (req, res) => {
  try {
    const user = new User(req.body);
    await user.save();
    res.status(201).json(user);
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

app.get('/api/users', async (req, res) => {
  try {
    const users = await User.find();
    res.json(users);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

PostgreSQL (Sequelize)

const { Sequelize, DataTypes } = require('sequelize');

// 连接数据库
const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: 'postgres'
});

// 定义模型
const User = sequelize.define('User', {
  name: {
    type: DataTypes.STRING,
    allowNull: false
  },
  email: {
    type: DataTypes.STRING,
    allowNull: false,
    unique: true
  }
});

// 同步模型
await sequelize.sync();

// CRUD操作
app.post('/api/users', async (req, res) => {
  try {
    const user = await User.create(req.body);
    res.status(201).json(user);
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

Redis (缓存)

const redis = require('redis');
const client = redis.createClient();

await client.connect();

// 缓存中间件
const cacheMiddleware = async (req, res, next) => {
  const key = `cache:${req.url}`;
  const cached = await client.get(key);

  if (cached) {
    return res.json(JSON.parse(cached));
  }

  // 保存原始send方法
  const originalSend = res.json.bind(res);

  // 重写send方法以缓存响应
  res.json = (body) => {
    client.setEx(key, 300, JSON.stringify(body)); // 缓存5分钟
    originalSend(body);
  };

  next();
};

app.get('/api/data', cacheMiddleware, async (req, res) => {
  // 耗时的数据库操作
  const data = await fetchDataFromDatabase();
  res.json(data);
});

性能优化 (Performance Optimization)

集群模式 (Cluster Mode)

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  console.log(`Master ${process.pid} is running`);

  // Fork workers
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`Worker ${worker.process.pid} died`);
    cluster.fork(); // 重启worker
  });
} else {
  // Workers可以共享TCP连接
  const app = require('./app'); // 你的Express应用

  app.listen(3000, () => {
    console.log(`Worker ${process.pid} started`);
  });
}

PM2进程管理

# 安装PM2
npm install -g pm2

# 启动应用
pm2 start app.js -i max  # max表示使用所有CPU核心

# 配置文件 ecosystem.config.js
module.exports = {
  apps: [{
    name: 'myapp',
    script: './app.js',
    instances: 'max',
    exec_mode: 'cluster',
    env: {
      NODE_ENV: 'production',
      PORT: 3000
    },
    error_file: './logs/err.log',
    out_file: './logs/out.log',
    log_date_format: 'YYYY-MM-DD HH:mm:ss',
    max_memory_restart: '1G'
  }]
};

# 使用配置文件启动
pm2 start ecosystem.config.js

# 监控
pm2 monit

# 日志
pm2 logs

# 重启
pm2 reload myapp  # 零停机重启

压缩和缓存

const compression = require('compression');
const helmet = require('helmet');

// 启用Gzip压缩
app.use(compression());

// 安全头
app.use(helmet());

// 静态文件缓存
app.use(express.static('public', {
  maxAge: '7d',
  etag: true,
  lastModified: true
}));

// HTTP缓存头
app.get('/api/data', (req, res) => {
  res.set('Cache-Control', 'public, max-age=300'); // 5分钟
  res.json(data);
});

WebSocket支持 (WebSocket Support)

Socket.io

const express = require('express');
const http = require('http');
const socketIO = require('socket.io');

const app = express();
const server = http.createServer(app);
const io = socketIO(server);

// WebSocket连接
io.on('connection', (socket) => {
  console.log('Client connected:', socket.id);

  // 接收消息
  socket.on('message', (data) => {
    console.log('Received:', data);

    // 广播给所有客户端
    io.emit('message', data);
  });

  // 断开连接
  socket.on('disconnect', () => {
    console.log('Client disconnected:', socket.id);
  });
});

server.listen(3000);

原生WebSocket

const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', (ws) => {
  console.log('Client connected');

  ws.on('message', (message) => {
    console.log('Received:', message);

    // 回显消息
    ws.send(`Echo: ${message}`);

    // 广播给所有客户端
    wss.clients.forEach((client) => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(message);
      }
    });
  });

  ws.on('close', () => {
    console.log('Client disconnected');
  });
});

生产环境部署 (Production Deployment)

Docker部署

# Dockerfile
FROM node:18-alpine

WORKDIR /app

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

# 安装依赖(生产环境)
RUN npm ci --only=production

# 复制源代码
COPY . .

# 暴露端口
EXPOSE 3000

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
  CMD node healthcheck.js

# 启动应用
CMD ["node", "app.js"]
# docker-compose.yml
version: '3.8'

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://user:pass@db:5432/mydb
      - REDIS_URL=redis://redis:6379
    depends_on:
      - db
      - redis
    restart: unless-stopped

  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_PASSWORD=password
    volumes:
      - postgres_data:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data

volumes:
  postgres_data:
  redis_data:

Nginx反向代理

upstream nodejs_backend {
    least_conn;
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
    server 127.0.0.1:3002;
    server 127.0.0.1:3003;
}

server {
    listen 80;
    server_name example.com;

    # 重定向到HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate /etc/ssl/certs/cert.pem;
    ssl_certificate_key /etc/ssl/private/key.pem;

    # 代理到Node.js
    location / {
        proxy_pass http://nodejs_backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }

    # 静态文件
    location /static {
        alias /var/www/static;
        expires 7d;
        add_header Cache-Control "public, immutable";
    }
}

监控与日志 (Monitoring and Logging)

Winston日志

const winston = require('winston');

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.errors({ stack: true }),
    winston.format.json()
  ),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' })
  ]
});

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

// 使用logger
app.use((req, res, next) => {
  logger.info(`${req.method} ${req.url}`);
  next();
});

Prometheus监控

const promClient = require('prom-client');
const register = new promClient.Registry();

// 默认指标
promClient.collectDefaultMetrics({ register });

// 自定义指标
const httpRequestDuration = new promClient.Histogram({
  name: 'http_request_duration_seconds',
  help: 'Duration of HTTP requests in seconds',
  labelNames: ['method', 'route', 'status_code'],
  registers: [register]
});

// 中间件
app.use((req, res, next) => {
  const start = Date.now();

  res.on('finish', () => {
    const duration = (Date.now() - start) / 1000;
    httpRequestDuration
      .labels(req.method, req.route?.path || req.url, res.statusCode)
      .observe(duration);
  });

  next();
});

// 指标端点
app.get('/metrics', async (req, res) => {
  res.set('Content-Type', register.contentType);
  res.end(await register.metrics());
});

最佳实践 (Best Practices)

1. 错误处理

// 异步错误处理包装器
const asyncHandler = (fn) => (req, res, next) => {
  Promise.resolve(fn(req, res, next)).catch(next);
};

// 使用
app.get('/api/users', asyncHandler(async (req, res) => {
  const users = await User.find();
  res.json(users);
}));

// 全局错误处理
app.use((err, req, res, next) => {
  logger.error(err.stack);

  if (err.name === 'ValidationError') {
    return res.status(400).json({ error: err.message });
  }

  res.status(500).json({ error: 'Internal server error' });
});

2. 环境配置

// config.js
require('dotenv').config();

module.exports = {
  port: process.env.PORT || 3000,
  nodeEnv: process.env.NODE_ENV || 'development',
  database: {
    url: process.env.DATABASE_URL,
    pool: {
      min: parseInt(process.env.DB_POOL_MIN) || 2,
      max: parseInt(process.env.DB_POOL_MAX) || 10
    }
  },
  redis: {
    url: process.env.REDIS_URL || 'redis://localhost:6379'
  },
  jwt: {
    secret: process.env.JWT_SECRET,
    expiresIn: process.env.JWT_EXPIRES_IN || '24h'
  }
};

3. 安全实践

const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
const mongoSanitize = require('express-mongo-sanitize');

// 安全头
app.use(helmet());

// 防止NoSQL注入
app.use(mongoSanitize());

// 速率限制
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 100,
  message: 'Too many requests'
});
app.use('/api/', limiter);

// CORS配置
app.use(cors({
  origin: process.env.ALLOWED_ORIGINS?.split(','),
  credentials: true
}));

// 输入验证
const { body, validationResult } = require('express-validator');

app.post('/api/users',
  body('email').isEmail().normalizeEmail(),
  body('password').isLength({ min: 8 }),
  (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }
    // 处理请求
  }
);

学习资源 (Learning Resources)

总结 (Summary)

Node.js作为Web服务器平台的主要优势:

✅ 适用场景

  • RESTful API和微服务
  • 实时应用(聊天、协作工具)
  • 单页应用(SPA)后端
  • 数据密集型应用
  • I/O密集型任务
  • 全栈JavaScript项目

⚠️ 不太适合

  • CPU密集型计算
  • 长时间运行的同步任务
  • 需要多线程的场景

主要优势

  • 🚀 高性能异步I/O
  • 📦 丰富的NPM生态
  • 🌐 前后端技术栈统一
  • 💡 活跃的社区支持
  • ⚡ 快速开发迭代

Node.js已成为现代Web开发的重要组成部分,适合快速构建可扩展的网络应用。


最后更新: 2025年11月

Last Updated: November 2025

powered by Gitbook© 2025 编外计划 | 最后修改: 2025-11-25 18:08:14

results matching ""

    No results matching ""