Node.js 部署基础

核心知识点

部署概述

部署是将开发完成的 Node.js 应用发布到生产环境的过程,使其能够被用户访问和使用。部署过程涉及多个环节,包括环境准备、应用构建、配置管理、服务启动和监控等。

部署的主要目标:

  • 确保应用在生产环境中正常运行
  • 实现应用的高可用性和可靠性
  • 简化部署流程,提高部署效率
  • 确保部署过程的安全性
  • 实现应用的版本管理和回滚

部署环境

  1. 开发环境(Development)

    • 开发者本地机器
    • 配置灵活,便于开发和调试
    • 可能包含开发工具和调试依赖
  2. 测试环境(Testing/Staging)

    • 模拟生产环境的配置
    • 用于测试和质量保证
    • 与生产环境隔离
  3. 生产环境(Production)

    • 面向用户的正式环境
    • 配置严格,注重性能和安全
    • 需要高可用性和可靠性

部署方式

  • 传统部署:直接在服务器上部署应用
  • 容器化部署:使用 Docker 等容器技术部署
  • 云平台部署:部署到 AWS、Azure、GCP 等云平台
  • Serverless 部署:使用 AWS Lambda、Azure Functions 等无服务器服务

实用案例分析

案例 1:传统服务器部署

问题:需要将 Node.js 应用部署到传统服务器

解决方案:准备服务器环境,上传应用代码,配置服务。

部署步骤

  1. 准备服务器
# 更新系统包
apt update && apt upgrade -y

# 安装 Node.js(使用 NodeSource 源)
curl -fsSL https://deb.nodesource.com/setup_18.x | bash -
apt install -y nodejs

# 验证 Node.js 和 npm 安装
node -v
npm -v

# 安装构建工具(可选)
apt install -y build-essential
  1. 上传应用代码
# 使用 scp 上传代码
scp -r ./my-app user@server-ip:/path/to/destination

# 或使用 git 克隆代码
git clone https://github.com/username/my-app.git /path/to/destination
  1. 安装依赖
cd /path/to/destination
npm install --production
  1. 配置环境变量
# 创建 .env 文件
nano .env

# 添加环境变量
NODE_ENV=production
PORT=3000
DATABASE_URL=mongodb://username:password@localhost:27017/myapp
  1. 启动应用
# 使用 PM2 启动应用
npm install -g pm2
pm start

# 或直接启动
node app.js
  1. 配置防火墙
# 允许应用端口
ufw allow 3000

# 启用防火墙
ufw enable

# 查看防火墙状态
ufw status
  1. 配置 Nginx 反向代理
# 安装 Nginx
apt install -y nginx

# 创建 Nginx 配置文件
nano /etc/nginx/sites-available/myapp

# 添加配置
server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

# 启用配置
ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/

# 测试 Nginx 配置
nginx -t

# 重启 Nginx
systemctl restart nginx

案例 2:使用 PM2 管理应用

问题:需要确保应用持续运行,自动重启

解决方案:使用 PM2 进程管理器管理应用。

代码示例

# 安装 PM2
npm install -g pm2

# 启动应用
pm start app.js

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

# 查看应用状态
pm status

# 监控应用
pm monit

# 重启应用
pm restart app

# 停止应用
pm stop app

# 查看应用日志
pm logs

# 生成启动脚本(系统重启后自动启动)
pm startup

# 保存当前进程列表
pm save

ecosystem.config.js

module.exports = {
  apps: [
    {
      name: 'myapp',
      script: 'app.js',
      instances: 'max',
      exec_mode: 'cluster',
      env: {
        NODE_ENV: 'development'
      },
      env_production: {
        NODE_ENV: 'production',
        PORT: 3000
      },
      log_file: 'logs/app.log',
      out_file: 'logs/out.log',
      error_file: 'logs/error.log',
      combine_logs: true,
      log_date_format: 'YYYY-MM-DD HH:mm:ss Z'
    }
  ]
};

案例 3:使用 Git 钩子自动化部署

问题:需要简化部署流程,实现代码更新后自动部署

解决方案:使用 Git 钩子实现自动化部署。

配置步骤

  1. 在服务器上创建 Git 仓库
# 创建仓库目录
mkdir -p /path/to/repo.git
cd /path/to/repo.git

# 初始化裸仓库
git init --bare

# 创建钩子目录
mkdir hooks
  1. 创建 post-receive 钩子
nano hooks/post-receive

钩子脚本

#!/bin/bash

# 仓库路径
REPO_DIR="/path/to/repo.git"
# 应用路径
APP_DIR="/path/to/app"
# 环境变量文件路径
ENV_FILE="$APP_DIR/.env"

# 输出颜色配置
GREEN="\033[0;32m"
YELLOW="\033[1;33m"
RED="\033[0;31m"
NC="\033[0m" # No Color

echo -e "${GREEN}开始部署应用...${NC}"

# 切换到应用目录
cd "$APP_DIR" || exit 1

# 从仓库拉取代码
echo -e "${YELLOW}拉取最新代码...${NC}"
git --git-dir="$REPO_DIR" --work-tree="$APP_DIR" checkout -f

# 安装依赖
echo -e "${YELLOW}安装依赖...${NC}"
npm install --production

# 重启应用
echo -e "${YELLOW}重启应用...${NC}"
if command -v pm2 &> /dev/null; then
    pm2 restart all
else
    # 如果没有 PM2,使用其他方式重启
    echo -e "${RED}警告:未安装 PM2,请手动重启应用${NC}"
fi

echo -e "${GREEN}部署完成!${NC}"
  1. 设置脚本权限
chmod +x hooks/post-receive
  1. 本地配置远程仓库
# 添加远程仓库
git remote add production ssh://user@server-ip/path/to/repo.git

# 推送代码到服务器
git push production master

案例 4:使用 Nginx 作为反向代理

问题:需要配置 Nginx 作为 Node.js 应用的反向代理,处理静态文件和 HTTPS

解决方案:配置 Nginx 服务器块,设置反向代理和静态文件服务。

Nginx 配置示例

# /etc/nginx/sites-available/myapp

upstream nodejs_app {
    server localhost:3000;
    # 可以添加多个服务器实现负载均衡
    # server localhost:3001;
    # server localhost:3002;
}

server {
    listen 80;
    server_name example.com www.example.com;
    
    # 重定向 HTTP 到 HTTPS
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;
    
    # SSL 配置
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    
    # 静态文件服务
    location /static/ {
        alias /path/to/app/public/;
        expires 30d;
        add_header Cache-Control "public, max-age=2592000";
    }
    
    # 反向代理到 Node.js 应用
    location / {
        proxy_pass http://nodejs_app;
        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;
        proxy_read_timeout 300s;
        proxy_connect_timeout 75s;
    }
    
    # 错误页面
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

案例 5:使用 Let's Encrypt 配置 HTTPS

问题:需要为 Node.js 应用配置 HTTPS,获取免费的 SSL 证书

解决方案:使用 Let's Encrypt 和 Certbot 获取和配置 SSL 证书。

配置步骤

  1. 安装 Certbot
# 安装 Certbot
apt install -y certbot python3-certbot-nginx
  1. 获取 SSL 证书
# 使用 Nginx 插件获取证书
certbot --nginx -d example.com -d www.example.com

# 或手动获取证书
certbot certonly --standalone -d example.com -d www.example.com
  1. 配置自动续期
# 测试续期
certbot renew --dry-run

# 添加定时任务
crontab -e

# 添加以下内容(每天凌晨 2 点执行)
0 2 * * * /usr/bin/certbot renew --quiet --renew-hook "systemctl restart nginx"
  1. 验证 HTTPS 配置

使用浏览器访问 https://example.com,检查证书是否有效。

部署最佳实践

1. 环境管理

  • 使用环境变量

    • 存储敏感配置,如数据库连接字符串、API 密钥
    • 使用 .env 文件或系统环境变量
    • 不同环境使用不同的环境变量
  • 环境隔离

    • 开发、测试和生产环境严格隔离
    • 避免在生产环境中使用开发依赖
    • 使用不同的数据库和服务实例

2. 配置管理

  • 集中化配置

    • 使用配置文件管理应用配置
    • 支持不同环境的配置文件
    • 配置版本控制
  • 安全配置

    • 避免在代码中硬编码敏感信息
    • 使用密钥管理服务存储敏感配置
    • 定期轮换密钥和密码

3. 应用构建

  • 构建流程

    • 自动化构建过程
    • 执行代码质量检查和测试
    • 生成构建产物
  • 依赖管理

    • 锁定依赖版本(使用 package-lock.json 或 yarn.lock)
    • 定期更新依赖,修复安全漏洞
    • 区分生产依赖和开发依赖

4. 部署流程

  • 自动化部署

    • 使用 CI/CD 工具自动化部署流程
    • 实现代码提交到部署的全流程自动化
    • 部署前执行测试和质量检查
  • 部署策略

    • 蓝绿部署:减少 downtime
    • 滚动部署:逐步更新实例
    • 金丝雀部署:先部署到部分实例,验证后再全量部署

5. 监控和维护

  • 应用监控

    • 监控应用的健康状态和性能
    • 设置告警机制,及时发现问题
    • 收集和分析应用日志
  • 系统监控

    • 监控服务器的 CPU、内存、磁盘和网络使用
    • 监控系统负载和进程状态
    • 定期备份数据
  • 维护计划

    • 定期更新系统和依赖
    • 执行安全审计和漏洞扫描
    • 制定应急预案,处理突发情况

常见问题与解决方案

问题 1:端口占用

症状

  • 应用启动失败,提示端口已被占用
  • 服务无法正常访问

解决方案

  • 检查端口使用情况:lsof -i :端口号netstat -tulpn | grep 端口号
  • 停止占用端口的进程:kill -9 进程ID
  • 修改应用配置,使用不同的端口

问题 2:依赖安装失败

症状

  • npm install 失败
  • 依赖版本冲突
  • 构建错误

解决方案

  • 清除 npm 缓存:npm cache clean --force
  • 删除 node_modules 目录和 package-lock.json 文件,重新安装
  • 检查依赖版本兼容性
  • 确保服务器有足够的内存和磁盘空间

问题 3:应用启动后无法访问

症状

  • 应用启动成功,但无法通过浏览器访问
  • 网络连接超时

解决方案

  • 检查防火墙配置,确保端口已开放
  • 检查应用绑定的 IP 地址,确保不是 localhost 或 127.0.0.1
  • 检查 Nginx 配置,确保反向代理设置正确
  • 检查应用日志,查找错误信息

问题 4:内存溢出

症状

  • 应用崩溃,提示 "JavaScript heap out of memory"
  • 服务器内存使用率高

解决方案

  • 增加 Node.js 内存限制:NODE_OPTIONS=--max-old-space-size=4096 node app.js
  • 优化应用代码,减少内存使用
  • 使用 PM2 的集群模式,分散内存负载
  • 考虑增加服务器内存

问题 5:部署后应用性能差

症状

  • 应用响应速度慢
  • 系统负载高

解决方案

  • 优化应用代码和数据库查询
  • 使用缓存减少重复计算和数据库查询
  • 配置 Nginx 缓存静态资源
  • 使用 PM2 的集群模式,充分利用多核 CPU
  • 考虑使用负载均衡,分散请求压力

部署工具

1. PM2

PM2 是一个生产级的 Node.js 进程管理器,提供了应用管理、负载均衡、自动重启等功能。

主要功能

  • 进程管理:启动、停止、重启应用
  • 负载均衡:使用集群模式充分利用多核 CPU
  • 自动重启:应用崩溃时自动重启
  • 日志管理:集中管理应用日志
  • 监控:实时监控应用状态和性能
  • 部署:简化应用部署流程

2. Nginx

Nginx 是一个高性能的 HTTP 和反向代理服务器,常用于为 Node.js 应用提供静态文件服务和负载均衡。

主要功能

  • 反向代理:将请求转发到 Node.js 应用
  • 负载均衡:分散请求到多个应用实例
  • 静态文件服务:高效处理静态资源
  • SSL 终端:处理 HTTPS 请求
  • 缓存:缓存静态资源和 API 响应

3. Certbot

Certbot 是一个自动化工具,用于获取和续期 Let's Encrypt 的免费 SSL 证书。

主要功能

  • 自动获取 SSL 证书
  • 自动配置 Web 服务器
  • 自动续期证书
  • 支持多种验证方式

4. Git

Git 是一个分布式版本控制系统,可用于代码管理和自动化部署。

在部署中的应用

  • 代码版本管理
  • 通过 Git 钩子实现自动化部署
  • 支持代码回滚,确保部署安全

总结

Node.js 部署是将应用从开发环境发布到生产环境的关键环节,涉及多个步骤和工具。通过本文的学习,你应该:

  1. 理解 Node.js 应用部署的核心概念和目标
  2. 掌握传统服务器部署的流程和方法
  3. 学会使用 PM2 管理 Node.js 应用
  4. 配置 Nginx 作为反向代理和静态文件服务器
  5. 实现 HTTPS 配置,确保应用安全
  6. 了解部署最佳实践和常见问题解决方案

部署过程需要细心和谨慎,特别是在生产环境中。通过自动化部署流程、合理的环境配置和有效的监控机制,可以确保应用的稳定运行和高可用性。

记住,部署不是一次性的任务,而是一个持续的过程。随着应用的发展和业务需求的变化,部署策略也需要不断调整和优化。通过不断学习和实践,你将能够构建更加可靠、高效的部署流程。

« 上一篇 Node.js 进程管理 下一篇 » Node.js Docker 容器化