22.02-Node.js部署
要点
- Node.js 是最经典的 JS 运行时,部署方式成熟:PM2、Docker、systemd
- Hono 在 Node.js 上用
@hono/node-server适配器跑 - 传统服务器部署的核心问题:进程管理、日志、重启、扩缩容
- 适合长时间运行、重计算的场景,但运维复杂度比 Serverless 高
内容
1. Hono 在 Node.js 上跑
Hono 提供了 Node.js 适配器 @hono/node-server:
// terminal
npm install @hono/node-server// src/index.ts
import { serve } from '@hono/node-server'
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => c.text('Hello Hono on Node.js!'))
app.get('/api/users', (c) => c.json({ users: [] }))
serve(app, (info) => {
console.log(`Server running on port ${info.port}`)
})@hono/node-server 的作用是把 Node.js 的原生 http 模块桥接到 Hono 的 Web Standards API 上。你写代码时还是用 c.json()、c.text(),适配器帮你翻译成 Node.js 的 Request/Response。
2. 构建和启动
Node.js 项目通常需要先编译 TypeScript 再运行:
// terminal
# 编译
npx tsc
# 或者用 tsx 直接运行(开发期)
npx tsx src/index.tspackage.json 里的 scripts:
{
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc",
"start": "node dist/index.js"
}
}3. 进程管理:PM2
直接 node dist/index.js 跑的问题是:进程挂了不会自动重启,终端关了进程也就结束了。
PM2 是 Node.js 最常用的进程管理器:
// terminal
# 安装
npm install -g pm2
# 启动
pm2 start dist/index.js --name my-api
# 查看状态
pm2 status
# 查看日志
pm2 logs my-api
# 重启
pm2 restart my-api
# 停止
pm2 stop my-api
# 开机自启
pm2 startup
pm2 savePM2 的核心功能:
| 功能 | 说明 |
|---|---|
| 自动重启 | 进程挂了自动拉起 |
| 日志管理 | 自动收集 stdout/stderr |
| 集群模式 | 利用多核 CPU,pm2 start -i max |
| 零停机重启 | pm2 reload,先启动新进程再杀旧进程 |
| 开机自启 | 系统重启后自动启动 |
3.1 集群模式
// terminal
# 启动和 CPU 核心数相同的实例
pm2 start dist/index.js -i max --name my-api
# 查看状态
pm2 status
# ┌─────────────┬────┬─────────┬──────┬───────┬──────────┐
# │ App name │ id │ mode │ pid │ status│ restart │
# ├─────────────┼────┼─────────┼──────┼───────┼──────────┤
# │ my-api │ 0 │ cluster │ 1234 │ online│ 0 │
# │ my-api │ 1 │ cluster │ 1235 │ online│ 0 │
# │ my-api │ 2 │ cluster │ 1236 │ online│ 0 │
# │ my-api │ 3 │ cluster │ 1237 │ online│ 0 │
# └─────────────┴────┴─────────┴──────┴───────┴──────────┘集群模式下,PM2 会在多个实例之间做负载均衡。适合 CPU 密集型的应用。
4. Docker 容器化部署
Docker 是另一种主流的部署方式。先把应用容器化,然后在任何支持 Docker 的平台上运行。
# Dockerfile
FROM node:22-alpine AS builder
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
# ---
FROM node:22-alpine AS runner
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
EXPOSE 3000
CMD ["node", "dist/index.js"]// terminal
# 构建镜像
docker build -t my-api .
# 运行
docker run -p 3000:3000 --name my-api my-api
# 后台运行
docker run -d -p 3000:3000 --restart always --name my-api my-apiDocker 的优势:
- 环境一致:开发、测试、生产用同一个镜像
- 可移植:在任何支持 Docker 的平台上运行
- 隔离性:每个应用在自己的容器里,互不影响
- 编排:用 Docker Compose 或 K8s 管理多个服务
5. systemd 部署
如果不用 Docker 和 PM2,可以直接用 Linux 的 systemd 管理进程:
# /etc/systemd/system/my-api.service
[Unit]
Description=My Hono API
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/my-api
ExecStart=/usr/bin/node dist/index.js
Restart=on-failure
RestartSec=5
Environment=NODE_ENV=production
Environment=PORT=3000
[Install]
WantedBy=multi-user.target// terminal
# 启用
sudo systemctl enable my-api
# 启动
sudo systemctl start my-api
# 查看状态
sudo systemctl status my-api
# 查看日志
sudo journalctl -u my-api -fsystemd 是 Linux 原生的进程管理,不需要额外安装 PM2。但配置相对复杂。
6. 反向代理:Nginx
生产环境通常不会让 Node.js 直接暴露 3000 端口,而是用 Nginx 做反向代理:
用户 → Nginx (80/443) → Node.js (3000)
# /etc/nginx/sites-available/my-api
upstream my-api {
server 127.0.0.1:3000;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://my-api;
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_cache_bypass $http_upgrade;
}
}Nginx 的作用:
- SSL 终止:在 Nginx 层处理 HTTPS
- 负载均衡:多个 Node.js 实例时做负载均衡
- 静态文件:静态资源直接由 Nginx 返回
- 限流和安全:防 DDoS、限速率
7. 传统部署的运维清单
Node.js 传统服务器部署需要关注:
| 事项 | 工具 |
|---|---|
| 进程管理 | PM2 / systemd |
| 日志收集 | PM2 logs / journald / 文件日志 |
| SSL 证书 | Let's Encrypt / Certbot |
| 反向代理 | Nginx / Caddy |
| 监控 | PM2 Plus / Datadog / Prometheus |
| 备份 | 数据库定时备份脚本 |
| 安全 | 防火墙、SSH 密钥、fail2ban |
8. 和边缘计算的对比
传统 Node.js 部署 vs Workers 边缘部署:
| 维度 | Node.js 传统部署 | Cloudflare Workers |
|---|---|---|
| 延迟 | 取决于服务器位置 | 全球边缘,极低延迟 |
| 扩缩容 | 手动配置或自动扩缩 | 自动 |
| 运维 | 需要管服务器 | 不需要 |
| 成本 | 固定月租 | 按请求计费 |
| 运行时 | 完整 Node.js | V8 isolate |
| 适用场景 | 长时间运行、重计算 | 低延迟 API、全球服务 |
对于 AI 项目来说,如果主要逻辑是调用外部 AI API(网络 I/O 密集),Workers 的延迟优势很明显。如果有大量的本地计算(如模型推理),传统服务器可能更合适。
9. 小结
Node.js 部署的核心:
- Hono 用
@hono/node-server跑在 Node.js 上 - PM2 管理进程(自动重启、日志、集群)
- Docker 容器化(环境一致、可移植)
- Nginx 反向代理(SSL、负载均衡)
- systemd 是 Linux 原生的替代方案
传统部署适合需要完全控制、长时间运行的场景,但运维复杂度比 Serverless 和边缘计算高。