Some checks failed
Deploy / deploy (push) Has been cancelled
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>
56 KiB
56 KiB
Telegram 管理系统部署指南
版本: v2.0.0
更新时间: 2024-01-20
维护者: 开发团队
📋 文档目录
🏗️ 部署概述
系统架构
Telegram管理系统采用前后端分离架构,包含以下组件:
- 前端应用: Vue 3 + Vben Admin
- 后端API: Node.js + Express
- 数据库: MySQL + Redis + MongoDB
- 反向代理: Nginx
- 实时通信: WebSocket
部署方式
支持多种部署方式:
- Docker Compose: 快速本地部署和开发
- Kubernetes: 生产环境容器编排
- 传统部署: 直接在服务器上安装
- 云原生部署: 支持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(推荐)
- 克隆项目
git clone https://github.com/your-org/telegram-management-system.git
cd telegram-management-system
- 配置环境变量
cp .env.example .env
# 编辑 .env 文件,配置必要的环境变量
- 启动所有服务
docker-compose up -d
- 初始化数据库
docker-compose exec backend npm run db:migrate
docker-compose exec backend npm run db:seed
- 访问系统
- 前端地址: http://localhost
- API地址: http://localhost:3000
- 默认账号: admin / 111111
一键安装脚本
提供快速安装脚本:
# 下载并执行安装脚本
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
🔧 开发环境部署
前端开发环境
- 安装依赖
cd frontend-vben/apps/web-antd
pnpm install
- 配置开发环境
# 复制环境配置文件
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管理系统(开发)
- 启动开发服务器
pnpm dev
后端开发环境
- 安装依赖
cd backend
npm install
- 配置数据库
# 启动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
- 配置环境变量
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
- 初始化数据库
# 运行数据库迁移
npm run db:migrate
# 填充初始数据
npm run db:seed
- 启动开发服务器
npm run dev
开发环境验证
验证开发环境是否正常:
# 检查前端
curl http://localhost:5173
# 检查后端API
curl http://localhost:3001/api/v1/health
# 检查数据库连接
npm run db:check
🏭 生产环境部署
服务器准备
- 系统要求
# Ubuntu 20.04 LTS 或更高版本
lsb_release -a
# 安装基础软件
sudo apt update
sudo apt install -y curl wget git nginx certbot
- 安装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
- 安装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
应用部署
- 克隆代码
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 .
- 构建前端
cd frontend-vben/apps/web-antd
# 安装pnpm
npm install -g pnpm
# 安装依赖
pnpm install
# 构建生产版本
pnpm build
- 配置生产环境变量
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
- 配置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
- 启动生产服务
# 构建并启动所有服务
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构建优化
- 多阶段构建
# 使用多阶段构建减少镜像大小
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"]
- .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配置
- 创建数据库和用户
-- 连接到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';
- 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
- 数据库初始化脚本
-- 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配置
- 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
- Redis集群配置(可选)
# redis-cluster.conf
port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
MongoDB配置
- 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 });
- 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免费证书
- 安装Certbot
# Ubuntu/Debian
sudo apt update
sudo apt install certbot python3-certbot-nginx
# CentOS/Rocky Linux
sudo dnf install certbot python3-certbot-nginx
- 获取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"
- 自动续期配置
# 添加到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;
}
}
安全最佳实践
- 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
- HTTP安全头检查
# 检查安全头
curl -I https://yourdomain.com
# 使用securityheaders.com
curl -s "https://securityheaders.com/?q=yourdomain.com&hide=on&followRedirects=on" | grep grade
📊 监控与日志
系统监控
- 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:
- 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']
- 告警规则
# 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'
日志管理
- 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:
- 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}"
}
}
}
- 应用日志配置
// 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;
💾 备份与恢复
数据库备份
- 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
- 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"
- 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"
自动化备份
- 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
- 文件备份脚本
#!/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"
恢复流程
- 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"
- 灾难恢复计划
#!/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
监控告警处理
告警响应流程
-
收到告警
- 查看告警详情
- 确认告警级别
- 开始故障处理
-
问题排查
- 检查监控面板
- 分析相关日志
- 确定问题范围
-
问题修复
- 实施修复措施
- 验证修复效果
- 更新告警状态
-
后续跟进
- 编写事故报告
- 优化监控规则
- 预防类似问题
应急处理脚本
#!/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
联系方式
- 技术支持: support@yourdomain.com
- 紧急联系: +86-138-0000-0000
- 文档地址: https://docs.yourdomain.com
- 监控地址: https://monitor.yourdomain.com
最后更新: 2024-01-20
文档版本: v2.0.0
本部署指南涵盖了从开发环境到生产环境的完整部署流程。如有疑问或需要支持,请联系技术团队。