Files
telegram-management-system/frontend-vben/apps/web-antd/docs/DEPLOYMENT.md
你的用户名 237c7802e5
Some checks failed
Deploy / deploy (push) Has been cancelled
Initial commit: Telegram Management System
Full-stack web application for Telegram management
- Frontend: Vue 3 + Vben Admin
- Backend: NestJS
- Features: User management, group broadcast, statistics

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 15:37:50 +08:00

56 KiB
Raw Blame History

Telegram 管理系统部署指南

版本: v2.0.0
更新时间: 2024-01-20
维护者: 开发团队

📋 文档目录


🏗️ 部署概述

系统架构

Telegram管理系统采用前后端分离架构包含以下组件

  • 前端应用: Vue 3 + Vben Admin
  • 后端API: Node.js + Express
  • 数据库: MySQL + Redis + MongoDB
  • 反向代理: Nginx
  • 实时通信: WebSocket

部署方式

支持多种部署方式:

  1. Docker Compose: 快速本地部署和开发
  2. Kubernetes: 生产环境容器编排
  3. 传统部署: 直接在服务器上安装
  4. 云原生部署: 支持AWS、阿里云等云平台

💻 环境要求

硬件要求

环境 CPU 内存 存储 网络
开发环境 2核 4GB 20GB 10Mbps
测试环境 4核 8GB 100GB 50Mbps
生产环境 8核 16GB 500GB 100Mbps
高可用环境 16核 32GB 1TB 1Gbps

软件要求

基础软件

软件 版本要求 说明
Node.js ≥18.0.0 运行时环境
npm/pnpm ≥8.0.0 包管理器
Git ≥2.30.0 版本控制
Docker ≥20.10.0 容器运行时
Docker Compose ≥2.0.0 容器编排

数据库

数据库 版本要求 用途
MySQL ≥8.0.0 主数据存储
Redis ≥7.0.0 缓存和会话
MongoDB ≥6.0.0 日志存储

Web服务器

服务器 版本要求 用途
Nginx ≥1.20.0 反向代理
Apache ≥2.4.0 备选web服务器

网络要求

  • 入站端口: 80 (HTTP), 443 (HTTPS), 3000 (API)
  • 出站访问: 访问Telegram API、邮件服务、短信服务
  • 内部通信: 各服务间网络连通性

快速部署

使用Docker Compose推荐

  1. 克隆项目
git clone https://github.com/your-org/telegram-management-system.git
cd telegram-management-system
  1. 配置环境变量
cp .env.example .env
# 编辑 .env 文件,配置必要的环境变量
  1. 启动所有服务
docker-compose up -d
  1. 初始化数据库
docker-compose exec backend npm run db:migrate
docker-compose exec backend npm run db:seed
  1. 访问系统

一键安装脚本

提供快速安装脚本:

# 下载并执行安装脚本
curl -fsSL https://raw.githubusercontent.com/your-org/telegram-management-system/main/scripts/install.sh | bash

# 或者下载后执行
wget https://raw.githubusercontent.com/your-org/telegram-management-system/main/scripts/install.sh
chmod +x install.sh
./install.sh

🔧 开发环境部署

前端开发环境

  1. 安装依赖
cd frontend-vben/apps/web-antd
pnpm install
  1. 配置开发环境
# 复制环境配置文件
cp .env.development.example .env.development

# 编辑配置文件
nano .env.development
# .env.development
VITE_API_URL=http://localhost:3001/api/v1
VITE_WS_URL=ws://localhost:3001/ws
VITE_APP_TITLE=Telegram管理系统(开发)
  1. 启动开发服务器
pnpm dev

后端开发环境

  1. 安装依赖
cd backend
npm install
  1. 配置数据库
# 启动MySQL (使用Docker)
docker run -d --name mysql-dev \
  -e MYSQL_ROOT_PASSWORD=root123 \
  -e MYSQL_DATABASE=telegram_system \
  -e MYSQL_USER=app_user \
  -e MYSQL_PASSWORD=app_password \
  -p 3306:3306 \
  mysql:8.0

# 启动Redis
docker run -d --name redis-dev \
  -p 6379:6379 \
  redis:7-alpine

# 启动MongoDB
docker run -d --name mongodb-dev \
  -p 27017:27017 \
  mongo:6.0
  1. 配置环境变量
cp .env.example .env.development
# .env.development
NODE_ENV=development
PORT=3001

# 数据库配置
DB_HOST=localhost
DB_PORT=3306
DB_NAME=telegram_system
DB_USER=app_user
DB_PASSWORD=app_password

# Redis配置
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=

# MongoDB配置
MONGODB_URI=mongodb://localhost:27017/telegram_system_logs

# JWT配置
JWT_SECRET=your-jwt-secret-key
JWT_EXPIRE=7d
REFRESH_TOKEN_EXPIRE=30d

# Telegram配置
TELEGRAM_BOT_TOKEN=your-telegram-bot-token
TELEGRAM_WEBHOOK_URL=https://your-domain.com/webhook/telegram
  1. 初始化数据库
# 运行数据库迁移
npm run db:migrate

# 填充初始数据
npm run db:seed
  1. 启动开发服务器
npm run dev

开发环境验证

验证开发环境是否正常:

# 检查前端
curl http://localhost:5173

# 检查后端API
curl http://localhost:3001/api/v1/health

# 检查数据库连接
npm run db:check

🏭 生产环境部署

服务器准备

  1. 系统要求
# Ubuntu 20.04 LTS 或更高版本
lsb_release -a

# 安装基础软件
sudo apt update
sudo apt install -y curl wget git nginx certbot
  1. 安装Node.js
# 安装Node.js 18.x
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs

# 验证安装
node --version
npm --version
  1. 安装Docker
# 安装Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# 安装Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# 验证安装
docker --version
docker-compose --version

应用部署

  1. 克隆代码
sudo mkdir -p /opt/telegram-system
sudo chown $USER:$USER /opt/telegram-system
cd /opt/telegram-system

git clone https://github.com/your-org/telegram-management-system.git .
  1. 构建前端
cd frontend-vben/apps/web-antd

# 安装pnpm
npm install -g pnpm

# 安装依赖
pnpm install

# 构建生产版本
pnpm build
  1. 配置生产环境变量
cp .env.example .env.production
# .env.production
NODE_ENV=production
PORT=3001

# 数据库配置
DB_HOST=mysql
DB_PORT=3306
DB_NAME=telegram_system
DB_USER=app_user
DB_PASSWORD=your-secure-password

# Redis配置
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=your-redis-password

# MongoDB配置
MONGODB_URI=mongodb://mongodb:27017/telegram_system_logs

# JWT配置
JWT_SECRET=your-very-secure-jwt-secret-key
JWT_EXPIRE=7d
REFRESH_TOKEN_EXPIRE=30d

# Telegram配置
TELEGRAM_BOT_TOKEN=your-telegram-bot-token
TELEGRAM_WEBHOOK_URL=https://yourdomain.com/webhook/telegram

# 安全配置
CORS_ORIGINS=https://yourdomain.com
RATE_LIMIT_MAX=100
RATE_LIMIT_WINDOW=60000

# 邮件配置
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-app-password

# 文件存储
FILE_STORAGE_TYPE=local
FILE_STORAGE_PATH=/app/uploads
MAX_FILE_SIZE=10485760

# 日志配置
LOG_LEVEL=info
LOG_FILE_PATH=/app/logs/app.log
  1. 配置Docker Compose
# docker-compose.prod.yml
version: '3.8'

services:
  frontend:
    build:
      context: ./frontend-vben/apps/web-antd
      dockerfile: Dockerfile.prod
    container_name: telegram-frontend
    restart: unless-stopped
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
    ports:
      - '80:80'
      - '443:443'
    depends_on:
      - backend
    networks:
      - telegram-network

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile.prod
    container_name: telegram-backend
    restart: unless-stopped
    env_file:
      - .env.production
    volumes:
      - ./uploads:/app/uploads
      - ./logs:/app/logs
    ports:
      - '3001:3001'
    depends_on:
      - mysql
      - redis
      - mongodb
    networks:
      - telegram-network
    healthcheck:
      test: ['CMD', 'curl', '-f', 'http://localhost:3001/health']
      interval: 30s
      timeout: 10s
      retries: 3

  mysql:
    image: mysql:8.0
    container_name: telegram-mysql
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASSWORD}
    volumes:
      - mysql_data:/var/lib/mysql
      - ./sql/init:/docker-entrypoint-initdb.d
    ports:
      - '3306:3306'
    networks:
      - telegram-network
    command: --default-authentication-plugin=mysql_native_password

  redis:
    image: redis:7-alpine
    container_name: telegram-redis
    restart: unless-stopped
    command: redis-server --requirepass ${REDIS_PASSWORD} --appendonly yes
    volumes:
      - redis_data:/data
    ports:
      - '6379:6379'
    networks:
      - telegram-network

  mongodb:
    image: mongo:6.0
    container_name: telegram-mongodb
    restart: unless-stopped
    environment:
      MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USER}
      MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASSWORD}
    volumes:
      - mongodb_data:/data/db
    ports:
      - '27017:27017'
    networks:
      - telegram-network

volumes:
  mysql_data:
    driver: local
  redis_data:
    driver: local
  mongodb_data:
    driver: local

networks:
  telegram-network:
    driver: bridge
  1. 启动生产服务
# 构建并启动所有服务
docker-compose -f docker-compose.prod.yml up -d

# 检查服务状态
docker-compose -f docker-compose.prod.yml ps

# 查看日志
docker-compose -f docker-compose.prod.yml logs -f

🐳 Docker部署

Dockerfile配置

前端Dockerfile

# frontend-vben/apps/web-antd/Dockerfile.prod
FROM node:18-alpine AS builder

WORKDIR /app

# 复制package文件
COPY package*.json ./
COPY pnpm-lock.yaml ./

# 安装pnpm和依赖
RUN npm install -g pnpm
RUN pnpm install --frozen-lockfile

# 复制源码
COPY . .

# 构建应用
RUN pnpm build

# 生产阶段
FROM nginx:alpine

# 复制构建产物
COPY --from=builder /app/dist /usr/share/nginx/html

# 复制nginx配置
COPY nginx.conf /etc/nginx/nginx.conf

# 创建必要目录
RUN mkdir -p /var/log/nginx

# 暴露端口
EXPOSE 80 443

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

CMD ["nginx", "-g", "daemon off;"]

后端Dockerfile

# backend/Dockerfile.prod
FROM node:18-alpine

# 设置工作目录
WORKDIR /app

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

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

# 安装生产依赖
RUN npm install --only=production && npm cache clean --force

# 复制源码
COPY . .

# 创建必要目录
RUN mkdir -p uploads logs
RUN chown -R nodejs:nodejs /app

# 切换到非root用户
USER nodejs

# 暴露端口
EXPOSE 3001

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

# 启动应用
CMD ["node", "server.js"]

Docker构建优化

  1. 多阶段构建
# 使用多阶段构建减少镜像大小
FROM node:18-alpine AS dependencies
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM node:18-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:18-alpine AS runtime
WORKDIR /app
COPY --from=dependencies /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY package*.json ./
EXPOSE 3001
CMD ["node", "dist/server.js"]
  1. .dockerignore文件
# .dockerignore
node_modules
npm-debug.log
.git
.gitignore
README.md
.env.development
.env.local
coverage
.coverage
.nyc_output
.DS_Store
*.log
logs

Docker网络配置

# 创建自定义网络
docker network create telegram-network

# 运行数据库服务
docker run -d --name mysql \
  --network telegram-network \
  -e MYSQL_ROOT_PASSWORD=root123 \
  -e MYSQL_DATABASE=telegram_system \
  -v mysql_data:/var/lib/mysql \
  mysql:8.0

# 运行Redis
docker run -d --name redis \
  --network telegram-network \
  -v redis_data:/data \
  redis:7-alpine

# 运行应用
docker run -d --name telegram-backend \
  --network telegram-network \
  -p 3001:3001 \
  -e DB_HOST=mysql \
  -e REDIS_HOST=redis \
  telegram-system/backend:latest

☸️ Kubernetes部署

命名空间配置

# k8s/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: telegram-system
  labels:
    name: telegram-system

ConfigMap配置

# k8s/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: telegram-config
  namespace: telegram-system
data:
  NODE_ENV: 'production'
  DB_HOST: 'mysql-service'
  DB_PORT: '3306'
  DB_NAME: 'telegram_system'
  REDIS_HOST: 'redis-service'
  REDIS_PORT: '6379'
  MONGODB_URI: 'mongodb://mongodb-service:27017/telegram_system_logs'
  LOG_LEVEL: 'info'

Secret配置

# k8s/secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: telegram-secret
  namespace: telegram-system
type: Opaque
data:
  DB_PASSWORD: <base64-encoded-password>
  REDIS_PASSWORD: <base64-encoded-password>
  JWT_SECRET: <base64-encoded-jwt-secret>
  TELEGRAM_BOT_TOKEN: <base64-encoded-bot-token>

MySQL部署

# k8s/mysql-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
  namespace: telegram-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:8.0
          ports:
            - containerPort: 3306
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: telegram-secret
                  key: DB_PASSWORD
            - name: MYSQL_DATABASE
              valueFrom:
                configMapKeyRef:
                  name: telegram-config
                  key: DB_NAME
          volumeMounts:
            - name: mysql-storage
              mountPath: /var/lib/mysql
          resources:
            requests:
              memory: '1Gi'
              cpu: '500m'
            limits:
              memory: '2Gi'
              cpu: '1000m'
      volumes:
        - name: mysql-storage
          persistentVolumeClaim:
            claimName: mysql-pvc

---
apiVersion: v1
kind: Service
metadata:
  name: mysql-service
  namespace: telegram-system
spec:
  selector:
    app: mysql
  ports:
    - port: 3306
      targetPort: 3306
  type: ClusterIP

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
  namespace: telegram-system
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

Redis部署

# k8s/redis-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  namespace: telegram-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
        - name: redis
          image: redis:7-alpine
          ports:
            - containerPort: 6379
          command:
            - redis-server
            - --requirepass
            - $(REDIS_PASSWORD)
            - --appendonly
            - 'yes'
          env:
            - name: REDIS_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: telegram-secret
                  key: REDIS_PASSWORD
          volumeMounts:
            - name: redis-storage
              mountPath: /data
          resources:
            requests:
              memory: '256Mi'
              cpu: '250m'
            limits:
              memory: '512Mi'
              cpu: '500m'
      volumes:
        - name: redis-storage
          persistentVolumeClaim:
            claimName: redis-pvc

---
apiVersion: v1
kind: Service
metadata:
  name: redis-service
  namespace: telegram-system
spec:
  selector:
    app: redis
  ports:
    - port: 6379
      targetPort: 6379
  type: ClusterIP

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: redis-pvc
  namespace: telegram-system
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

后端应用部署

# k8s/backend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  namespace: telegram-system
spec:
  replicas: 3
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
        - name: backend
          image: telegram-system/backend:latest
          ports:
            - containerPort: 3001
          envFrom:
            - configMapRef:
                name: telegram-config
            - secretRef:
                name: telegram-secret
          volumeMounts:
            - name: uploads-storage
              mountPath: /app/uploads
            - name: logs-storage
              mountPath: /app/logs
          livenessProbe:
            httpGet:
              path: /health
              port: 3001
            initialDelaySeconds: 30
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /ready
              port: 3001
            initialDelaySeconds: 5
            periodSeconds: 5
          resources:
            requests:
              memory: '512Mi'
              cpu: '250m'
            limits:
              memory: '1Gi'
              cpu: '500m'
      volumes:
        - name: uploads-storage
          persistentVolumeClaim:
            claimName: uploads-pvc
        - name: logs-storage
          persistentVolumeClaim:
            claimName: logs-pvc

---
apiVersion: v1
kind: Service
metadata:
  name: backend-service
  namespace: telegram-system
spec:
  selector:
    app: backend
  ports:
    - port: 3001
      targetPort: 3001
  type: ClusterIP

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: uploads-pvc
  namespace: telegram-system
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: logs-pvc
  namespace: telegram-system
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 2Gi

前端应用部署

# k8s/frontend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  namespace: telegram-system
spec:
  replicas: 3
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
        - name: frontend
          image: telegram-system/frontend:latest
          ports:
            - containerPort: 80
          resources:
            requests:
              memory: '128Mi'
              cpu: '100m'
            limits:
              memory: '256Mi'
              cpu: '200m'

---
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
  namespace: telegram-system
spec:
  selector:
    app: frontend
  ports:
    - port: 80
      targetPort: 80
  type: LoadBalancer

Ingress配置

# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: telegram-ingress
  namespace: telegram-system
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/ssl-redirect: 'true'
    nginx.ingress.kubernetes.io/proxy-body-size: '50m'
spec:
  tls:
    - hosts:
        - yourdomain.com
        - api.yourdomain.com
      secretName: telegram-tls
  rules:
    - host: yourdomain.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-service
                port:
                  number: 80
    - host: api.yourdomain.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: backend-service
                port:
                  number: 3001

部署命令

# 创建命名空间
kubectl apply -f k8s/namespace.yaml

# 创建配置
kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/secret.yaml

# 部署数据库
kubectl apply -f k8s/mysql-deployment.yaml
kubectl apply -f k8s/redis-deployment.yaml

# 等待数据库就绪
kubectl wait --for=condition=ready pod -l app=mysql -n telegram-system --timeout=300s
kubectl wait --for=condition=ready pod -l app=redis -n telegram-system --timeout=300s

# 部署应用
kubectl apply -f k8s/backend-deployment.yaml
kubectl apply -f k8s/frontend-deployment.yaml

# 配置Ingress
kubectl apply -f k8s/ingress.yaml

# 检查部署状态
kubectl get pods -n telegram-system
kubectl get services -n telegram-system
kubectl get ingress -n telegram-system

🗄️ 数据库配置

MySQL配置

  1. 创建数据库和用户
-- 连接到MySQL
mysql -u root -p

-- 创建数据库
CREATE DATABASE telegram_system CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 创建用户
CREATE USER 'app_user'@'%' IDENTIFIED BY 'your_secure_password';

-- 授权
GRANT ALL PRIVILEGES ON telegram_system.* TO 'app_user'@'%';
FLUSH PRIVILEGES;

-- 验证
SHOW DATABASES;
SELECT User, Host FROM mysql.user WHERE User = 'app_user';
  1. MySQL配置优化
# /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
# 基础配置
port = 3306
bind-address = 0.0.0.0
socket = /var/run/mysqld/mysqld.sock

# 字符集配置
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

# 内存配置
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
key_buffer_size = 128M
max_connections = 500

# 性能配置
innodb_flush_log_at_trx_commit = 2
sync_binlog = 0
query_cache_size = 0
query_cache_type = 0

# 日志配置
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2

# 二进制日志
log-bin = mysql-bin
binlog_format = ROW
expire_logs_days = 7
  1. 数据库初始化脚本
-- sql/init/01-schema.sql
-- 用户表
CREATE TABLE users (
  id VARCHAR(36) PRIMARY KEY,
  username VARCHAR(50) UNIQUE NOT NULL,
  email VARCHAR(100) UNIQUE NOT NULL,
  password_hash VARCHAR(255) NOT NULL,
  profile JSON,
  status ENUM('active', 'inactive', 'suspended') DEFAULT 'active',
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

  INDEX idx_username (username),
  INDEX idx_email (email),
  INDEX idx_status (status)
);

-- Telegram账号表
CREATE TABLE telegram_accounts (
  id VARCHAR(36) PRIMARY KEY,
  telegram_id VARCHAR(20) UNIQUE NOT NULL,
  username VARCHAR(50),
  first_name VARCHAR(50),
  last_name VARCHAR(50),
  phone VARCHAR(20),
  status ENUM('active', 'inactive', 'blocked') DEFAULT 'active',
  metadata JSON,
  managed_by VARCHAR(36),
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

  INDEX idx_telegram_id (telegram_id),
  INDEX idx_username (username),
  INDEX idx_managed_by (managed_by),
  FOREIGN KEY (managed_by) REFERENCES users(id)
);

-- 更多表定义...

Redis配置

  1. Redis配置文件
# redis.conf
port 6379
bind 0.0.0.0
requirepass your_redis_password

# 持久化配置
save 900 1
save 300 10
save 60 10000

appendonly yes
appendfsync everysec

# 内存配置
maxmemory 512mb
maxmemory-policy allkeys-lru

# 网络配置
timeout 300
keepalive 60

# 日志配置
loglevel notice
logfile /var/log/redis/redis-server.log

# 安全配置
protected-mode yes
  1. Redis集群配置可选
# redis-cluster.conf
port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

MongoDB配置

  1. MongoDB初始化
// mongo-init.js
db = db.getSiblingDB('telegram_system_logs');

// 创建用户
db.createUser({
  user: 'app_user',
  pwd: 'your_mongodb_password',
  roles: [
    {
      role: 'readWrite',
      db: 'telegram_system_logs',
    },
  ],
});

// 创建索引
db.logs.createIndex({ timestamp: 1 });
db.logs.createIndex({ level: 1 });
db.logs.createIndex({ source: 1 });
db.logs.createIndex({ userId: 1 });

// 创建TTL索引日志保留30天
db.logs.createIndex({ timestamp: 1 }, { expireAfterSeconds: 2592000 });
  1. MongoDB配置文件
# mongod.conf
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log

storage:
  dbPath: /var/lib/mongodb
  journal:
    enabled: true

processManagement:
  fork: true
  pidFilePath: /var/run/mongodb/mongod.pid

net:
  port: 27017
  bindIpAll: true

security:
  authorization: enabled

replication:
  replSetName: 'rs0'

🔧 环境变量配置

完整环境变量列表

# .env.production
# ======================
# 应用基础配置
# ======================
NODE_ENV=production
PORT=3001
APP_NAME=Telegram管理系统
APP_VERSION=2.0.0

# ======================
# 数据库配置
# ======================
# MySQL配置
DB_HOST=mysql
DB_PORT=3306
DB_NAME=telegram_system
DB_USER=app_user
DB_PASSWORD=your_secure_mysql_password
DB_POOL_MIN=5
DB_POOL_MAX=50
DB_TIMEOUT=60000

# Redis配置
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=your_secure_redis_password
REDIS_DB=0
REDIS_KEY_PREFIX=telegram:
REDIS_CONNECT_TIMEOUT=10000

# MongoDB配置
MONGODB_URI=mongodb://app_user:your_mongodb_password@mongodb:27017/telegram_system_logs
MONGODB_OPTIONS={"authSource":"telegram_system_logs","useNewUrlParser":true}

# ======================
# 安全配置
# ======================
# JWT配置
JWT_SECRET=your_very_secure_jwt_secret_key_at_least_32_characters
JWT_EXPIRE=7d
REFRESH_TOKEN_SECRET=your_refresh_token_secret_key
REFRESH_TOKEN_EXPIRE=30d

# 加密配置
ENCRYPTION_KEY=your_32_character_encryption_key
HASH_ROUNDS=12

# CORS配置
CORS_ORIGINS=https://yourdomain.com,https://api.yourdomain.com
CORS_CREDENTIALS=true

# 安全头配置
HELMET_ENABLED=true
CSP_ENABLED=true

# ======================
# 第三方服务配置
# ======================
# Telegram配置
TELEGRAM_BOT_TOKEN=your_telegram_bot_token
TELEGRAM_WEBHOOK_URL=https://api.yourdomain.com/webhook/telegram
TELEGRAM_API_URL=https://api.telegram.org/bot
TELEGRAM_RATE_LIMIT=30

# 邮件配置
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=your_email@gmail.com
SMTP_PASS=your_app_password
SMTP_FROM_NAME=Telegram管理系统
SMTP_FROM_EMAIL=noreply@yourdomain.com

# 短信配置
SMS_PROVIDER=aliyun
SMS_ACCESS_KEY=your_sms_access_key
SMS_SECRET_KEY=your_sms_secret_key
SMS_SIGN_NAME=你的签名
SMS_TEMPLATE_CODE=SMS_123456789

# ======================
# 文件存储配置
# ======================
# 本地存储
FILE_STORAGE_TYPE=local
FILE_STORAGE_PATH=/app/uploads
FILE_STORAGE_URL=https://yourdomain.com/uploads

# 云存储阿里云OSS
# FILE_STORAGE_TYPE=oss
# OSS_REGION=oss-cn-beijing
# OSS_ACCESS_KEY_ID=your_oss_access_key
# OSS_ACCESS_KEY_SECRET=your_oss_secret_key
# OSS_BUCKET=your_bucket_name
# OSS_ENDPOINT=https://oss-cn-beijing.aliyuncs.com

# 文件限制
MAX_FILE_SIZE=10485760
ALLOWED_FILE_TYPES=jpg,jpeg,png,gif,pdf,doc,docx,xls,xlsx

# ======================
# 性能配置
# ======================
# 缓存配置
CACHE_TTL=3600
CACHE_MAX_SIZE=100
ENABLE_CACHE=true

# 限流配置
RATE_LIMIT_ENABLED=true
RATE_LIMIT_MAX=100
RATE_LIMIT_WINDOW=60000
RATE_LIMIT_SKIP_SUCCESSFUL=false

# 会话配置
SESSION_SECRET=your_session_secret_key
SESSION_TTL=86400
SESSION_STORE=redis

# ======================
# 日志配置
# ======================
LOG_LEVEL=info
LOG_FORMAT=json
LOG_FILE_ENABLED=true
LOG_FILE_PATH=/app/logs/app.log
LOG_FILE_MAX_SIZE=100m
LOG_FILE_MAX_FILES=10

# 访问日志
ACCESS_LOG_ENABLED=true
ACCESS_LOG_PATH=/app/logs/access.log

# 错误日志
ERROR_LOG_ENABLED=true
ERROR_LOG_PATH=/app/logs/error.log

# ======================
# 监控配置
# ======================
# 健康检查
HEALTH_CHECK_ENABLED=true
HEALTH_CHECK_TIMEOUT=5000

# 性能监控
PERFORMANCE_MONITORING=true
METRICS_ENDPOINT=/metrics

# APM配置
APM_ENABLED=false
APM_SERVICE_NAME=telegram-system-api
APM_SERVER_URL=http://apm-server:8200

# ======================
# WebSocket配置
# ======================
WS_ENABLED=true
WS_PORT=3001
WS_PATH=/ws
WS_HEARTBEAT_INTERVAL=30000
WS_TIMEOUT=60000

# ======================
# 队列配置
# ======================
QUEUE_ENABLED=true
QUEUE_REDIS_HOST=redis
QUEUE_REDIS_PORT=6379
QUEUE_REDIS_DB=1
QUEUE_CONCURRENCY=5

# 消息队列
MESSAGE_QUEUE_NAME=message_tasks
MESSAGE_QUEUE_ATTEMPTS=3
MESSAGE_QUEUE_DELAY=5000

# ======================
# 开发配置(仅开发环境)
# ======================
# DEBUG模式
DEBUG=false
DEVELOPMENT_FEATURES=false

# 热重载
HOT_RELOAD=false

# 测试配置
ENABLE_TEST_ROUTES=false
TEST_DATA_ENABLED=false

环境变量验证

创建环境变量验证脚本:

// scripts/validate-env.js
const requiredVars = [
  'NODE_ENV',
  'PORT',
  'DB_HOST',
  'DB_NAME',
  'DB_USER',
  'DB_PASSWORD',
  'REDIS_HOST',
  'JWT_SECRET',
  'TELEGRAM_BOT_TOKEN',
];

const optionalVars = [
  'MONGODB_URI',
  'SMTP_HOST',
  'SMS_PROVIDER',
  'FILE_STORAGE_TYPE',
];

function validateEnvironment() {
  const missing = [];
  const warnings = [];

  // 检查必需变量
  requiredVars.forEach((varName) => {
    if (!process.env[varName]) {
      missing.push(varName);
    }
  });

  // 检查可选变量
  optionalVars.forEach((varName) => {
    if (!process.env[varName]) {
      warnings.push(varName);
    }
  });

  // 检查JWT密钥长度
  if (process.env.JWT_SECRET && process.env.JWT_SECRET.length < 32) {
    missing.push('JWT_SECRET (must be at least 32 characters)');
  }

  // 输出结果
  if (missing.length > 0) {
    console.error('❌ Missing required environment variables:');
    missing.forEach((varName) => {
      console.error(`  - ${varName}`);
    });
    process.exit(1);
  }

  if (warnings.length > 0) {
    console.warn('⚠️  Optional environment variables not set:');
    warnings.forEach((varName) => {
      console.warn(`  - ${varName}`);
    });
  }

  console.log('✅ Environment validation passed');
}

if (require.main === module) {
  validateEnvironment();
}

module.exports = { validateEnvironment };

运行验证:

node scripts/validate-env.js

🔒 SSL证书配置

使用Let's Encrypt免费证书

  1. 安装Certbot
# Ubuntu/Debian
sudo apt update
sudo apt install certbot python3-certbot-nginx

# CentOS/Rocky Linux
sudo dnf install certbot python3-certbot-nginx
  1. 获取SSL证书
# 为域名申请证书
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com -d api.yourdomain.com

# 或者使用DNS验证推荐
sudo certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
  -d yourdomain.com \
  -d "*.yourdomain.com"
  1. 自动续期配置
# 添加到crontab
sudo crontab -e

# 添加以下行(每天检查一次)
0 2 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"

Nginx SSL配置

# /etc/nginx/sites-available/telegram-system
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name yourdomain.com www.yourdomain.com;

    # SSL配置
    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

    # SSL安全配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # HSTS
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # 其他安全头
    add_header X-Frame-Options DENY always;
    add_header X-Content-Type-Options nosniff always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # 前端静态文件
    root /var/www/telegram-system/dist;
    index index.html;

    # Gzip压缩
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;

    # 静态文件缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # API代理
    location /api/ {
        proxy_pass http://backend-service:3001;
        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_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;

        # 缓冲配置
        proxy_buffering on;
        proxy_buffer_size 128k;
        proxy_buffers 4 256k;
        proxy_busy_buffers_size 256k;
    }

    # WebSocket代理
    location /ws {
        proxy_pass http://backend-service:3001;
        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;

        # WebSocket特定配置
        proxy_read_timeout 86400;
        proxy_send_timeout 86400;
    }

    # SPA路由支持
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 健康检查
    location /health {
        access_log off;
        return 200 "healthy\n";
        add_header Content-Type text/plain;
    }
}

# API子域名
server {
    listen 443 ssl http2;
    server_name api.yourdomain.com;

    # SSL配置复用主域名证书
    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

    # 直接代理到后端
    location / {
        proxy_pass http://backend-service:3001;
        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;
    }
}

安全最佳实践

  1. SSL配置测试
# 使用SSL Labs测试
curl -s "https://api.ssllabs.com/api/v3/analyze?host=yourdomain.com" | jq .

# 使用testssl.sh
git clone https://github.com/drwetter/testssl.sh.git
cd testssl.sh
./testssl.sh yourdomain.com
  1. HTTP安全头检查
# 检查安全头
curl -I https://yourdomain.com

# 使用securityheaders.com
curl -s "https://securityheaders.com/?q=yourdomain.com&hide=on&followRedirects=on" | grep grade

📊 监控与日志

系统监控

  1. Prometheus + Grafana部署
# docker-compose.monitoring.yml
version: '3.8'

services:
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
      - '9090:9090'
    volumes:
      - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/usr/share/prometheus/console_libraries'
      - '--web.console.templates=/usr/share/prometheus/consoles'
      - '--web.enable-lifecycle'

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - '3000:3000'
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin123
    volumes:
      - grafana_data:/var/lib/grafana
      - ./monitoring/grafana/dashboards:/etc/grafana/provisioning/dashboards
      - ./monitoring/grafana/datasources:/etc/grafana/provisioning/datasources

  node-exporter:
    image: prom/node-exporter:latest
    container_name: node-exporter
    ports:
      - '9100:9100'
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
      - /run/systemd/private:/run/systemd/private:ro
    command:
      - '--path.procfs=/host/proc'
      - '--path.sysfs=/host/sys'
      - '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)'

  alertmanager:
    image: prom/alertmanager:latest
    container_name: alertmanager
    ports:
      - '9093:9093'
    volumes:
      - ./monitoring/alertmanager.yml:/etc/alertmanager/alertmanager.yml

volumes:
  prometheus_data:
  grafana_data:
  1. Prometheus配置
# monitoring/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - 'rules/*.yml'

alerting:
  alertmanagers:
    - static_configs:
        - targets:
            - alertmanager:9093

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node-exporter'
    static_configs:
      - targets: ['node-exporter:9100']

  - job_name: 'telegram-backend'
    static_configs:
      - targets: ['backend:3001']
    metrics_path: '/metrics'
    scrape_interval: 30s

  - job_name: 'mysql'
    static_configs:
      - targets: ['mysql-exporter:9104']

  - job_name: 'redis'
    static_configs:
      - targets: ['redis-exporter:9121']
  1. 告警规则
# monitoring/rules/alerts.yml
groups:
  - name: telegram-system-alerts
    rules:
      - alert: HighCPUUsage
        expr: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: 'High CPU usage detected'
          description: 'CPU usage is above 80% for more than 5 minutes'

      - alert: HighMemoryUsage
        expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100 > 90
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: 'High memory usage detected'
          description: 'Memory usage is above 90% for more than 5 minutes'

      - alert: ApplicationDown
        expr: up{job="telegram-backend"} == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: 'Application is down'
          description: 'Telegram system backend is not responding'

      - alert: DatabaseConnectionFailure
        expr: mysql_up == 0
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: 'Database connection failure'
          description: 'Cannot connect to MySQL database'

      - alert: HighErrorRate
        expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) * 100 > 5
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: 'High error rate detected'
          description: 'Error rate is above 5% for more than 2 minutes'

日志管理

  1. ELK Stack部署
# docker-compose.elk.yml
version: '3.8'

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.17.0
    container_name: elasticsearch
    environment:
      - discovery.type=single-node
      - 'ES_JAVA_OPTS=-Xms1g -Xmx1g'
    ports:
      - '9200:9200'
    volumes:
      - elasticsearch_data:/usr/share/elasticsearch/data

  logstash:
    image: docker.elastic.co/logstash/logstash:7.17.0
    container_name: logstash
    volumes:
      - ./elk/logstash/config:/usr/share/logstash/pipeline
      - ./elk/logstash/logstash.yml:/usr/share/logstash/config/logstash.yml
    ports:
      - '5044:5044'
    depends_on:
      - elasticsearch

  kibana:
    image: docker.elastic.co/kibana/kibana:7.17.0
    container_name: kibana
    ports:
      - '5601:5601'
    environment:
      ELASTICSEARCH_HOSTS: http://elasticsearch:9200
    depends_on:
      - elasticsearch

volumes:
  elasticsearch_data:
  1. Logstash配置
# elk/logstash/config/pipeline.conf
input {
  beats {
    port => 5044
  }

  tcp {
    port => 5000
    codec => json_lines
  }
}

filter {
  if [fields][service] == "telegram-system" {
    json {
      source => "message"
    }

    date {
      match => [ "timestamp", "ISO8601" ]
    }

    if [level] == "error" {
      mutate {
        add_tag => [ "error" ]
      }
    }

    # 解析用户代理
    if [userAgent] {
      useragent {
        source => "userAgent"
        target => "ua"
      }
    }

    # IP地理位置
    if [clientIP] {
      geoip {
        source => "clientIP"
        target => "geoip"
      }
    }
  }
}

output {
  elasticsearch {
    hosts => ["elasticsearch:9200"]
    index => "telegram-system-%{+YYYY.MM.dd}"
  }

  if "error" in [tags] {
    email {
      to => "admin@yourdomain.com"
      subject => "Telegram System Error Alert"
      body => "Error: %{message}\nTimestamp: %{timestamp}\nLevel: %{level}"
    }
  }
}
  1. 应用日志配置
// backend/utils/logger.js
const winston = require('winston');
require('winston-daily-rotate-file');

const logFormat = winston.format.combine(
  winston.format.timestamp(),
  winston.format.errors({ stack: true }),
  winston.format.json(),
);

const logger = winston.createLogger({
  level: process.env.LOG_LEVEL || 'info',
  format: logFormat,
  defaultMeta: {
    service: 'telegram-system',
    version: process.env.APP_VERSION,
  },
  transports: [
    // 控制台输出
    new winston.transports.Console({
      format: winston.format.combine(
        winston.format.colorize(),
        winston.format.simple(),
      ),
    }),

    // 文件输出
    new winston.transports.DailyRotateFile({
      filename: 'logs/app-%DATE%.log',
      datePattern: 'YYYY-MM-DD',
      maxSize: '20m',
      maxFiles: '14d',
      level: 'info',
    }),

    // 错误日志
    new winston.transports.DailyRotateFile({
      filename: 'logs/error-%DATE%.log',
      datePattern: 'YYYY-MM-DD',
      maxSize: '20m',
      maxFiles: '30d',
      level: 'error',
    }),

    // 发送到Logstash
    new winston.transports.Http({
      host: 'logstash',
      port: 5000,
      level: 'warn',
    }),
  ],
});

module.exports = logger;

💾 备份与恢复

数据库备份

  1. MySQL备份脚本
#!/bin/bash
# scripts/backup-mysql.sh

# 配置
BACKUP_DIR="/opt/backups/mysql"
DB_NAME="telegram_system"
DB_USER="backup_user"
DB_PASSWORD="backup_password"
DB_HOST="localhost"
RETENTION_DAYS=30

# 创建备份目录
mkdir -p $BACKUP_DIR

# 生成备份文件名
BACKUP_FILE="$BACKUP_DIR/telegram_system_$(date +%Y%m%d_%H%M%S).sql"

# 执行备份
mysqldump -h $DB_HOST -u $DB_USER -p$DB_PASSWORD \
  --single-transaction \
  --routines \
  --triggers \
  --events \
  --hex-blob \
  --complete-insert \
  $DB_NAME > $BACKUP_FILE

# 压缩备份文件
gzip $BACKUP_FILE

# 删除旧备份
find $BACKUP_DIR -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete

# 验证备份
if [ -f "$BACKUP_FILE.gz" ]; then
    echo "Backup completed successfully: $BACKUP_FILE.gz"

    # 上传到云存储(可选)
    # aws s3 cp "$BACKUP_FILE.gz" s3://your-backup-bucket/mysql/
else
    echo "Backup failed!"
    exit 1
fi
  1. Redis备份脚本
#!/bin/bash
# scripts/backup-redis.sh

BACKUP_DIR="/opt/backups/redis"
REDIS_HOST="localhost"
REDIS_PORT="6379"
REDIS_PASSWORD="your_redis_password"
RETENTION_DAYS=7

mkdir -p $BACKUP_DIR

# 触发Redis保存
redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD BGSAVE

# 等待保存完成
while [ $(redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD LASTSAVE) -eq $(redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD LASTSAVE) ]; do
    sleep 1
done

# 复制RDB文件
BACKUP_FILE="$BACKUP_DIR/redis_$(date +%Y%m%d_%H%M%S).rdb"
cp /var/lib/redis/dump.rdb $BACKUP_FILE

# 压缩
gzip $BACKUP_FILE

# 清理旧备份
find $BACKUP_DIR -name "*.rdb.gz" -mtime +$RETENTION_DAYS -delete

echo "Redis backup completed: $BACKUP_FILE.gz"
  1. MongoDB备份脚本
#!/bin/bash
# scripts/backup-mongodb.sh

BACKUP_DIR="/opt/backups/mongodb"
DB_NAME="telegram_system_logs"
MONGO_HOST="localhost"
MONGO_PORT="27017"
MONGO_USER="backup_user"
MONGO_PASSWORD="backup_password"
RETENTION_DAYS=14

mkdir -p $BACKUP_DIR

BACKUP_FILE="$BACKUP_DIR/mongodb_$(date +%Y%m%d_%H%M%S)"

# 执行备份
mongodump \
  --host $MONGO_HOST:$MONGO_PORT \
  --username $MONGO_USER \
  --password $MONGO_PASSWORD \
  --db $DB_NAME \
  --out $BACKUP_FILE

# 压缩备份
tar -czf "$BACKUP_FILE.tar.gz" -C $BACKUP_DIR $(basename $BACKUP_FILE)
rm -rf $BACKUP_FILE

# 清理旧备份
find $BACKUP_DIR -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete

echo "MongoDB backup completed: $BACKUP_FILE.tar.gz"

自动化备份

  1. Crontab配置
# 编辑crontab
sudo crontab -e

# 添加备份任务
# MySQL备份 - 每天凌晨2点
0 2 * * * /opt/telegram-system/scripts/backup-mysql.sh >> /var/log/backup-mysql.log 2>&1

# Redis备份 - 每6小时
0 */6 * * * /opt/telegram-system/scripts/backup-redis.sh >> /var/log/backup-redis.log 2>&1

# MongoDB备份 - 每天凌晨3点
0 3 * * * /opt/telegram-system/scripts/backup-mongodb.sh >> /var/log/backup-mongodb.log 2>&1

# 文件备份 - 每周日凌晨1点
0 1 * * 0 /opt/telegram-system/scripts/backup-files.sh >> /var/log/backup-files.log 2>&1
  1. 文件备份脚本
#!/bin/bash
# scripts/backup-files.sh

BACKUP_DIR="/opt/backups/files"
SOURCE_DIR="/opt/telegram-system/uploads"
RETENTION_DAYS=90

mkdir -p $BACKUP_DIR

BACKUP_FILE="$BACKUP_DIR/files_$(date +%Y%m%d_%H%M%S).tar.gz"

# 备份上传文件
tar -czf $BACKUP_FILE -C $(dirname $SOURCE_DIR) $(basename $SOURCE_DIR)

# 清理旧备份
find $BACKUP_DIR -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete

echo "Files backup completed: $BACKUP_FILE"

恢复流程

  1. MySQL恢复
#!/bin/bash
# scripts/restore-mysql.sh

BACKUP_FILE=$1
DB_NAME="telegram_system"
DB_USER="root"
DB_PASSWORD="root_password"
DB_HOST="localhost"

if [ -z "$BACKUP_FILE" ]; then
    echo "Usage: $0 <backup_file>"
    exit 1
fi

# 解压备份文件
if [[ $BACKUP_FILE == *.gz ]]; then
    gunzip -c $BACKUP_FILE > /tmp/restore.sql
    RESTORE_FILE="/tmp/restore.sql"
else
    RESTORE_FILE=$BACKUP_FILE
fi

# 停止应用服务
docker-compose stop backend

# 删除现有数据库
mysql -h $DB_HOST -u $DB_USER -p$DB_PASSWORD -e "DROP DATABASE IF EXISTS $DB_NAME;"
mysql -h $DB_HOST -u $DB_USER -p$DB_PASSWORD -e "CREATE DATABASE $DB_NAME CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

# 恢复数据
mysql -h $DB_HOST -u $DB_USER -p$DB_PASSWORD $DB_NAME < $RESTORE_FILE

# 清理临时文件
if [ "$RESTORE_FILE" = "/tmp/restore.sql" ]; then
    rm /tmp/restore.sql
fi

# 重启应用服务
docker-compose start backend

echo "MySQL restore completed from: $BACKUP_FILE"
  1. 灾难恢复计划
#!/bin/bash
# scripts/disaster-recovery.sh

echo "Starting disaster recovery process..."

# 1. 停止所有服务
echo "Stopping all services..."
docker-compose down

# 2. 恢复数据库
echo "Restoring databases..."
./scripts/restore-mysql.sh /opt/backups/mysql/latest.sql.gz
./scripts/restore-redis.sh /opt/backups/redis/latest.rdb.gz
./scripts/restore-mongodb.sh /opt/backups/mongodb/latest.tar.gz

# 3. 恢复文件
echo "Restoring files..."
tar -xzf /opt/backups/files/latest.tar.gz -C /opt/telegram-system/

# 4. 重新启动服务
echo "Starting services..."
docker-compose up -d

# 5. 验证服务
echo "Verifying services..."
sleep 30

# 检查服务状态
if curl -f http://localhost:3001/health; then
    echo "✅ Disaster recovery completed successfully"
else
    echo "❌ Disaster recovery failed - manual intervention required"
    exit 1
fi

🔧 故障排除

常见问题

1. 应用无法启动

问题症状

  • 容器启动失败
  • 应用日志显示连接错误
  • 健康检查失败

解决步骤

# 检查容器状态
docker-compose ps

# 查看详细日志
docker-compose logs backend

# 检查环境变量
docker-compose exec backend printenv

# 检查网络连接
docker-compose exec backend ping mysql
docker-compose exec backend ping redis

# 验证数据库连接
docker-compose exec backend npm run db:check

常见原因

  • 数据库未就绪
  • 环境变量配置错误
  • 网络连接问题
  • 端口冲突

2. 数据库连接失败

问题症状

  • ECONNREFUSED 错误
  • 数据库超时
  • 认证失败

解决步骤

# 检查MySQL状态
docker-compose exec mysql mysql -u root -p -e "SHOW DATABASES;"

# 检查用户权限
docker-compose exec mysql mysql -u root -p -e "SELECT User, Host FROM mysql.user;"

# 测试连接
docker-compose exec backend mysql -h mysql -u app_user -p

# 检查网络
docker network ls
docker network inspect telegram-system_default

3. Redis连接问题

问题症状

  • 缓存功能异常
  • 会话丢失
  • WebSocket连接问题

解决步骤

# 检查Redis状态
docker-compose exec redis redis-cli ping

# 测试认证
docker-compose exec redis redis-cli -a your_password ping

# 检查配置
docker-compose exec redis redis-cli config get "*"

# 查看连接信息
docker-compose exec redis redis-cli info clients

4. 前端无法访问后端

问题症状

  • API请求失败
  • CORS错误
  • 502/504错误

解决步骤

# 检查Nginx配置
nginx -t

# 重新加载Nginx
nginx -s reload

# 检查代理配置
curl -I http://localhost/api/health

# 检查网络连接
telnet backend 3001

5. SSL证书问题

问题症状

  • 证书过期警告
  • SSL握手失败
  • 混合内容错误

解决步骤

# 检查证书状态
openssl x509 -in /etc/letsencrypt/live/yourdomain.com/cert.pem -text -noout

# 验证证书链
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt /etc/letsencrypt/live/yourdomain.com/cert.pem

# 续期证书
certbot renew --dry-run

# 检查证书有效期
certbot certificates

性能问题排查

1. 响应时间过长

排查步骤

# 检查系统资源
top
htop
iostat -x 1

# 检查数据库性能
docker-compose exec mysql mysql -u root -p -e "SHOW PROCESSLIST;"
docker-compose exec mysql mysql -u root -p -e "SHOW STATUS LIKE 'Slow_queries';"

# 检查Redis性能
docker-compose exec redis redis-cli --latency
docker-compose exec redis redis-cli info stats

# 分析应用日志
tail -f logs/app.log | grep -E "(slow|timeout|error)"

2. 内存使用过高

排查步骤

# 检查容器内存使用
docker stats

# 检查Node.js内存泄漏
docker-compose exec backend node --expose-gc --inspect=0.0.0.0:9229 server.js

# 分析heap dump
npm install -g heapdump

3. 数据库锁等待

排查步骤

# 检查锁等待
docker-compose exec mysql mysql -u root -p -e "SHOW ENGINE INNODB STATUS\G" | grep -A 10 "TRANSACTIONS"

# 查看当前事务
docker-compose exec mysql mysql -u root -p -e "SELECT * FROM information_schema.innodb_trx;"

# 查看锁等待
docker-compose exec mysql mysql -u root -p -e "SELECT * FROM information_schema.innodb_locks;"

日志分析

应用日志分析

# 错误日志分析
grep -E "ERROR|FATAL" logs/app.log | tail -n 50

# 慢查询分析
grep "slow query" logs/app.log | awk '{print $NF}' | sort | uniq -c | sort -nr

# API错误统计
grep "api_error" logs/access.log | cut -d' ' -f7 | sort | uniq -c | sort -nr

# 用户活动分析
grep "user_action" logs/app.log | cut -d' ' -f4 | sort | uniq -c | sort -nr

系统日志分析

# 系统错误
journalctl -u docker -f

# 内核日志
dmesg | tail -n 50

# 磁盘空间检查
df -h
du -sh /opt/telegram-system/* | sort -h

监控告警处理

告警响应流程

  1. 收到告警

    • 查看告警详情
    • 确认告警级别
    • 开始故障处理
  2. 问题排查

    • 检查监控面板
    • 分析相关日志
    • 确定问题范围
  3. 问题修复

    • 实施修复措施
    • 验证修复效果
    • 更新告警状态
  4. 后续跟进

    • 编写事故报告
    • 优化监控规则
    • 预防类似问题

应急处理脚本

#!/bin/bash
# scripts/emergency-response.sh

ISSUE_TYPE=$1

case $ISSUE_TYPE in
    "high-cpu")
        echo "处理高CPU使用率问题..."
        # 重启应用服务
        docker-compose restart backend
        # 清理临时文件
        docker system prune -f
        ;;

    "high-memory")
        echo "处理高内存使用问题..."
        # 清理缓存
        docker-compose exec redis redis-cli FLUSHDB
        # 重启服务
        docker-compose restart backend
        ;;

    "database-down")
        echo "处理数据库故障..."
        # 尝试重启数据库
        docker-compose restart mysql
        # 检查数据完整性
        docker-compose exec mysql mysqlcheck --all-databases
        ;;

    "disk-full")
        echo "处理磁盘空间不足..."
        # 清理日志文件
        find /var/log -name "*.log" -mtime +7 -delete
        # 清理Docker缓存
        docker system prune -a -f
        # 清理备份文件
        find /opt/backups -mtime +30 -delete
        ;;

    *)
        echo "用法: $0 {high-cpu|high-memory|database-down|disk-full}"
        exit 1
        ;;
esac

echo "应急处理完成,请检查系统状态"

📚 附录

部署检查清单

部署前检查

  • 服务器资源满足要求
  • 域名DNS配置正确
  • SSL证书已申请
  • 环境变量已配置
  • 数据库已创建
  • 备份策略已制定

部署过程检查

  • 代码版本正确
  • 构建过程无错误
  • 数据库迁移成功
  • 服务启动正常
  • 健康检查通过
  • SSL证书生效

部署后验证

  • 前端页面可访问
  • API接口正常
  • 用户登录功能
  • 数据库连接正常
  • 缓存功能正常
  • WebSocket连接正常
  • 邮件发送功能
  • 文件上传功能
  • 监控告警配置

常用命令

Docker相关

# 查看服务状态
docker-compose ps

# 查看日志
docker-compose logs -f backend

# 重启服务
docker-compose restart backend

# 进入容器
docker-compose exec backend bash

# 更新服务
docker-compose pull
docker-compose up -d

# 清理资源
docker system prune -f

数据库相关

# 连接MySQL
docker-compose exec mysql mysql -u root -p

# 导出数据库
docker-compose exec mysql mysqldump -u root -p telegram_system > backup.sql

# 导入数据库
docker-compose exec -T mysql mysql -u root -p telegram_system < backup.sql

# 检查Redis
docker-compose exec redis redis-cli ping

# MongoDB操作
docker-compose exec mongodb mongo telegram_system_logs

系统维护

# 检查磁盘空间
df -h

# 检查内存使用
free -h

# 检查系统负载
uptime

# 查看网络连接
netstat -tlnp

# 检查端口占用
lsof -i :3001

联系方式


最后更新: 2024-01-20
文档版本: v2.0.0

本部署指南涵盖了从开发环境到生产环境的完整部署流程。如有疑问或需要支持,请联系技术团队。