# Telegram 管理系统架构文档 > **版本**: v2.0.0 > **更新时间**: 2024-01-20 > **维护者**: 开发团队 ## 📋 文档目录 - [系统概述](#系统概述) - [技术架构](#技术架构) - [前端架构](#前端架构) - [后端架构](#后端架构) - [数据库设计](#数据库设计) - [安全架构](#安全架构) - [部署架构](#部署架构) - [性能优化](#性能优化) - [监控体系](#监控体系) - [扩展性设计](#扩展性设计) --- ## 🏗️ 系统概述 ### 系统简介 Telegram 管理系统是一个基于现代Web技术栈构建的企业级营销管理平台,专注于Telegram渠道的用户管理、消息群发、营销活动等核心功能。 ### 核心特性 - 🚀 **高性能**: 基于Vue 3 + Vite构建,支持秒级响应 - 🔒 **安全可靠**: 完整的权限控制体系,支持多角色管理 - 🌐 **国际化**: 支持中英文双语,可扩展更多语言 - 📱 **响应式设计**: 完美适配桌面端、平板和移动端 - ⚡ **实时通信**: 基于WebSocket的实时状态同步 - 🔧 **高度可配置**: 支持灵活的系统配置和个性化定制 ### 业务模块 ```mermaid graph TB A[Telegram管理系统] --> B[用户管理] A --> C[消息管理] A --> D[营销中心] A --> E[系统管理] B --> B1[账号管理] B --> B2[权限控制] B --> B3[角色管理] C --> C1[私信群发] C --> C2[群组管理] C --> C3[消息模板] C --> C4[发送记录] D --> D1[营销活动] D --> D2[客户分析] D --> D3[效果统计] D --> D4[智能推荐] E --> E1[系统配置] E --> E2[日志管理] E --> E3[监控报警] E --> E4[数据统计] ``` --- ## 🏛️ 技术架构 ### 整体架构图 ```mermaid graph TB subgraph "前端层" A1[Vue 3 + TypeScript] A2[Vben Admin Framework] A3[Ant Design Vue] A4[Vite 构建工具] end subgraph "API网关层" B1[Nginx 反向代理] B2[API Gateway] B3[负载均衡] B4[SSL终端] end subgraph "应用服务层" C1[Node.js/Express] C2[业务逻辑层] C3[权限中间件] C4[WebSocket 服务] end subgraph "数据存储层" D1[MySQL 主数据库] D2[Redis 缓存] D3[MongoDB 日志] D4[文件存储 OSS] end subgraph "外部服务" E1[Telegram Bot API] E2[短信服务商] E3[邮件服务] E4[CDN 服务] end A1 --> B1 A2 --> B2 B1 --> C1 B2 --> C2 C1 --> D1 C2 --> D2 C3 --> D3 C4 --> E1 ``` ### 技术栈选型 #### 前端技术栈 | 技术 | 版本 | 用途 | 选型理由 | | --- | --- | --- | --- | | Vue 3 | ^3.4.0 | 前端框架 | 组合式API,更好的TypeScript支持,性能提升 | | TypeScript | ^5.0.0 | 类型系统 | 提供类型安全,减少运行时错误 | | Vben Admin | ^5.5.8 | 管理后台框架 | 功能丰富,开发效率高,社区活跃 | | Ant Design Vue | ^4.0.0 | UI组件库 | 组件丰富,设计规范,企业级应用首选 | | Vite | ^5.0.0 | 构建工具 | 快速的开发服务器,优化的生产构建 | | Pinia | ^2.1.0 | 状态管理 | Vue 3官方推荐,简洁的API | | Vue Router | ^4.2.0 | 路由管理 | Vue 3官方路由器 | | VueUse | ^10.0.0 | 组合式工具库 | 丰富的组合式函数 | #### 后端技术栈 | 技术 | 版本 | 用途 | 选型理由 | | --------- | ------- | ------------ | -------------------------- | | Node.js | ^18.0.0 | 运行时环境 | 高性能,丰富的生态系统 | | Express | ^4.18.0 | Web框架 | 成熟稳定,中间件丰富 | | MySQL | ^8.0.0 | 关系型数据库 | ACID特性,适合业务数据存储 | | Redis | ^7.0.0 | 内存数据库 | 高性能缓存,会话存储 | | MongoDB | ^6.0.0 | 文档数据库 | 适合日志和非结构化数据 | | Socket.io | ^4.7.0 | 实时通信 | 可靠的WebSocket实现 | #### 开发工具 | 工具 | 版本 | 用途 | | ---------- | ------- | -------------- | | ESLint | ^8.50.0 | 代码规范检查 | | Prettier | ^3.0.0 | 代码格式化 | | Husky | ^8.0.0 | Git钩子管理 | | Commitizen | ^4.3.0 | 规范化提交信息 | | Playwright | ^1.40.0 | 端到端测试 | --- ## 🎨 前端架构 ### 项目结构 ``` apps/web-antd/ ├── build/ # 构建相关配置 │ ├── compression.ts # 资源压缩配置 │ ├── image-optimizer.ts # 图片优化工具 │ ├── cdn-config.ts # CDN配置 │ └── optimize.ts # 构建优化脚本 ├── docs/ # 项目文档 ├── public/ # 静态资源 ├── src/ # 源码目录 │ ├── api/ # API接口层 │ ├── assets/ # 静态资源 │ ├── components/ # 通用组件 │ ├── hooks/ # 组合式函数 │ ├── layouts/ # 布局组件 │ ├── locales/ # 国际化资源 │ ├── router/ # 路由配置 │ ├── stores/ # 状态管理 │ ├── types/ # 类型定义 │ ├── utils/ # 工具函数 │ └── views/ # 页面组件 ├── tests/ # 测试文件 │ ├── e2e/ # 端到端测试 │ ├── global-setup.ts # 全局测试设置 │ └── global-teardown.ts # 全局测试清理 └── types/ # 全局类型定义 ``` ### 组件架构 ```mermaid graph TB subgraph "页面层 (Views)" A1[业务页面组件] A2[路由页面组件] end subgraph "布局层 (Layouts)" B1[主布局 Layout] B2[侧边栏 Sidebar] B3[头部 Header] B4[内容区 Content] end subgraph "组件层 (Components)" C1[业务组件] C2[通用组件] C3[基础组件] end subgraph "基础层 (Base)" D1[Ant Design Vue] D2[Vue 3 内置组件] end A1 --> B1 A2 --> B2 B1 --> C1 B2 --> C2 C1 --> D1 C2 --> D2 ``` ### 状态管理架构 采用 Pinia 进行状态管理,按模块划分: ```typescript // stores/index.ts export interface AppState { // 用户状态 user: UserState; // 权限状态 permission: PermissionState; // 应用设置 settings: SettingsState; // 业务数据 business: BusinessState; } // 状态模块示例 export const useUserStore = defineStore('user', () => { const userInfo = ref(null); const token = ref(''); const permissions = ref([]); const login = async (credentials: LoginCredentials) => { // 登录逻辑 }; const logout = async () => { // 登出逻辑 }; return { userInfo, token, permissions, login, logout, }; }); ``` ### 路由架构 采用动态路由 + 权限控制的方式: ```typescript // router/index.ts const router = createRouter({ history: createWebHistory(), routes: [ // 静态路由 { path: '/login', component: LoginView, meta: { requiresAuth: false }, }, // 动态路由(根据权限加载) { path: '/dashboard', component: DashboardLayout, meta: { requiresAuth: true }, children: dynamicRoutes, }, ], }); // 路由守卫 router.beforeEach(async (to, from, next) => { const userStore = useUserStore(); if (to.meta.requiresAuth && !userStore.token) { next('/login'); } else { // 权限验证 const hasPermission = await checkPermission(to); hasPermission ? next() : next('/403'); } }); ``` ### API架构 统一的API请求层: ```typescript // api/base.ts class ApiClient { private instance: AxiosInstance; constructor() { this.instance = axios.create({ baseURL: import.meta.env.VITE_API_URL, timeout: 10000, }); this.setupInterceptors(); } private setupInterceptors() { // 请求拦截器 this.instance.interceptors.request.use((config) => { const token = getToken(); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); // 响应拦截器 this.instance.interceptors.response.use( (response) => response.data, (error) => this.handleError(error), ); } } // API模块化 export const accountApi = { getList: (params: AccountListParams) => apiClient.get('/accounts', { params }), create: (data: CreateAccountData) => apiClient.post('/accounts', data), update: (id: string, data: UpdateAccountData) => apiClient.put(`/accounts/${id}`, data), }; ``` --- ## ⚙️ 后端架构 ### 分层架构 ```mermaid graph TB subgraph "控制层 (Controller)" A1[路由控制器] A2[参数验证] A3[权限验证] end subgraph "服务层 (Service)" B1[业务逻辑] B2[数据处理] B3[外部服务调用] end subgraph "数据访问层 (DAO)" C1[MySQL 操作] C2[Redis 操作] C3[MongoDB 操作] end subgraph "中间件层 (Middleware)" D1[认证中间件] D2[日志中间件] D3[错误处理] D4[限流中间件] end A1 --> B1 A2 --> B2 B1 --> C1 B2 --> C2 D1 --> A1 D2 --> A2 ``` ### 核心模块 #### 1. 用户认证模块 ```javascript // auth/auth.service.js class AuthService { async login(credentials) { // 用户验证 const user = await this.validateUser(credentials); // 生成token const token = this.generateJWT(user); // 记录登录日志 await this.logLoginActivity(user); return { user, token }; } async validateToken(token) { try { const decoded = jwt.verify(token, process.env.JWT_SECRET); const user = await User.findById(decoded.userId); return user; } catch (error) { throw new UnauthorizedError('Invalid token'); } } } ``` #### 2. 权限控制模块 ```javascript // permission/permission.service.js class PermissionService { async checkPermission(userId, resource, action) { const userRoles = await this.getUserRoles(userId); const permissions = await this.getRolePermissions(userRoles); return permissions.some( (permission) => permission.resource === resource && permission.action === action, ); } middleware() { return async (req, res, next) => { const { user } = req; const { resource, action } = req.route.meta; const hasPermission = await this.checkPermission( user.id, resource, action, ); if (hasPermission) { next(); } else { res.status(403).json({ error: 'Forbidden' }); } }; } } ``` #### 3. 消息处理模块 ```javascript // message/message.service.js class MessageService { async sendBulkMessage(taskData) { const { templateId, targetUsers, scheduledTime } = taskData; // 创建发送任务 const task = await this.createTask(taskData); // 如果是定时发送 if (scheduledTime) { await this.scheduleTask(task, scheduledTime); } else { await this.executeTask(task); } return task; } async executeTask(task) { const { id, targetUsers, template } = task; const results = []; for (const user of targetUsers) { try { // 渲染消息模板 const message = this.renderTemplate(template, user); // 发送消息 const result = await this.sendTelegramMessage(user.telegramId, message); // 记录发送结果 await this.recordSendResult(task.id, user.id, result); results.push({ userId: user.id, status: 'success' }); } catch (error) { results.push({ userId: user.id, status: 'failed', error: error.message, }); } } // 更新任务状态 await this.updateTaskStatus(id, 'completed', results); } } ``` ### 数据模型 #### 用户模型 ```javascript // models/User.js const UserSchema = new Schema({ username: { type: String, required: true, unique: true }, email: { type: String, required: true, unique: true }, password: { type: String, required: true }, profile: { firstName: String, lastName: String, avatar: String, phone: String, }, roles: [{ type: Schema.Types.ObjectId, ref: 'Role' }], settings: { language: { type: String, default: 'zh-CN' }, timezone: { type: String, default: 'Asia/Shanghai' }, notifications: { email: { type: Boolean, default: true }, sms: { type: Boolean, default: false }, }, }, status: { type: String, enum: ['active', 'inactive', 'suspended'], default: 'active', }, lastLogin: Date, createdAt: { type: Date, default: Date.now }, updatedAt: { type: Date, default: Date.now }, }); ``` #### 消息任务模型 ```javascript // models/MessageTask.js const MessageTaskSchema = new Schema({ name: { type: String, required: true }, description: String, template: { type: Schema.Types.ObjectId, ref: 'MessageTemplate' }, targetUsers: [{ type: Schema.Types.ObjectId, ref: 'TelegramAccount' }], scheduling: { type: { type: String, enum: ['immediate', 'scheduled', 'recurring'] }, scheduledTime: Date, recurrence: { frequency: { type: String, enum: ['daily', 'weekly', 'monthly'] }, interval: Number, endDate: Date, }, }, status: { type: String, enum: ['pending', 'running', 'completed', 'failed', 'cancelled'], default: 'pending', }, progress: { total: { type: Number, default: 0 }, sent: { type: Number, default: 0 }, failed: { type: Number, default: 0 }, percentage: { type: Number, default: 0 }, }, results: [ { userId: { type: Schema.Types.ObjectId, ref: 'TelegramAccount' }, status: { type: String, enum: ['success', 'failed'] }, sentAt: Date, error: String, }, ], createdBy: { type: Schema.Types.ObjectId, ref: 'User' }, createdAt: { type: Date, default: Date.now }, updatedAt: { type: Date, default: Date.now }, }); ``` --- ## 🗄️ 数据库设计 ### 数据库架构 ```mermaid erDiagram User ||--o{ UserRole : has Role ||--o{ RolePermission : has Permission ||--o{ RolePermission : belongs User ||--o{ MessageTask : creates MessageTask ||--o{ MessageResult : contains MessageTemplate ||--o{ MessageTask : used_in TelegramAccount ||--o{ MessageResult : receives TelegramAccount }o--|| User : managed_by User { string id PK string username UK string email UK string password_hash json profile enum status datetime created_at datetime updated_at } Role { string id PK string name UK string description boolean is_system datetime created_at } Permission { string id PK string resource string action string description } TelegramAccount { string id PK string telegram_id UK string username string first_name string last_name string phone enum status json metadata string managed_by FK datetime created_at datetime updated_at } MessageTask { string id PK string name string description string template_id FK json target_users json scheduling enum status json progress string created_by FK datetime created_at datetime updated_at } MessageTemplate { string id PK string name string content json variables enum type string created_by FK datetime created_at datetime updated_at } ``` ### 数据表设计 #### 核心业务表 1. **用户表 (users)** ```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', last_login TIMESTAMP NULL, 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) ); ``` 2. **Telegram账号表 (telegram_accounts)** ```sql 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) ); ``` 3. **消息任务表 (message_tasks)** ```sql CREATE TABLE message_tasks ( id VARCHAR(36) PRIMARY KEY, name VARCHAR(100) NOT NULL, description TEXT, template_id VARCHAR(36), target_users JSON NOT NULL, scheduling JSON, status ENUM('pending', 'running', 'completed', 'failed', 'cancelled') DEFAULT 'pending', progress JSON, created_by VARCHAR(36) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_status (status), INDEX idx_created_by (created_by), INDEX idx_created_at (created_at), FOREIGN KEY (created_by) REFERENCES users(id), FOREIGN KEY (template_id) REFERENCES message_templates(id) ); ``` ### 缓存策略 #### Redis 数据结构设计 ```javascript // 缓存键命名规范 const CACHE_KEYS = { // 用户相关 USER_INFO: 'user:info:{userId}', USER_PERMISSIONS: 'user:permissions:{userId}', USER_SESSION: 'session:{sessionId}', // 任务相关 TASK_STATUS: 'task:status:{taskId}', TASK_PROGRESS: 'task:progress:{taskId}', TASK_QUEUE: 'task:queue', // 统计数据 DAILY_STATS: 'stats:daily:{date}', USER_ACTIVITY: 'activity:user:{userId}', // 配置缓存 SYSTEM_CONFIG: 'config:system', RATE_LIMIT: 'rate_limit:{userId}:{endpoint}', }; // 缓存操作示例 class CacheService { async getUserInfo(userId) { const cacheKey = CACHE_KEYS.USER_INFO.replace('{userId}', userId); let userInfo = await redis.get(cacheKey); if (!userInfo) { userInfo = await User.findById(userId); await redis.setex(cacheKey, 3600, JSON.stringify(userInfo)); // 1小时过期 } else { userInfo = JSON.parse(userInfo); } return userInfo; } async setTaskProgress(taskId, progress) { const cacheKey = CACHE_KEYS.TASK_PROGRESS.replace('{taskId}', taskId); await redis.setex(cacheKey, 86400, JSON.stringify(progress)); // 24小时过期 // 发布进度更新事件 await redis.publish( 'task:progress:update', JSON.stringify({ taskId, progress, }), ); } } ``` --- ## 🔐 安全架构 ### 认证与授权 #### JWT认证流程 ```mermaid sequenceDiagram participant Client participant Gateway participant AuthService participant Database Client->>Gateway: 登录请求 (username, password) Gateway->>AuthService: 验证凭据 AuthService->>Database: 查询用户信息 Database-->>AuthService: 返回用户数据 AuthService->>AuthService: 验证密码 AuthService->>AuthService: 生成JWT Token AuthService-->>Gateway: 返回Token和用户信息 Gateway-->>Client: 返回认证结果 Note over Client: 后续请求携带Token Client->>Gateway: API请求 (Header: Authorization) Gateway->>AuthService: 验证Token AuthService-->>Gateway: 返回用户信息 Gateway->>Gateway: 检查权限 Gateway-->>Client: 返回API响应 ``` #### 权限控制模型 采用RBAC (Role-Based Access Control) 模型: ```typescript // 权限定义 interface Permission { id: string; resource: string; // 资源类型: account, message, task action: string; // 操作类型: create, read, update, delete conditions?: { // 条件限制 owner?: boolean; // 只能操作自己的资源 department?: string; // 部门限制 }; } // 角色定义 interface Role { id: string; name: string; permissions: Permission[]; inherits?: string[]; // 继承其他角色 } // 权限检查 class PermissionChecker { async checkPermission( userId: string, resource: string, action: string, resourceData?: any, ): Promise { const userRoles = await this.getUserRoles(userId); const permissions = await this.flattenPermissions(userRoles); return permissions.some((permission) => { // 基础权限匹配 if (permission.resource !== resource || permission.action !== action) { return false; } // 条件检查 if (permission.conditions?.owner && resourceData?.ownerId !== userId) { return false; } return true; }); } } ``` ### 数据安全 #### 敏感数据加密 ```javascript // 数据加密服务 class CryptoService { constructor() { this.algorithm = 'aes-256-gcm'; this.secretKey = process.env.ENCRYPTION_KEY; } encrypt(text) { const iv = crypto.randomBytes(16); const cipher = crypto.createCipher(this.algorithm, this.secretKey); cipher.setAAD(Buffer.from('additional-data')); let encrypted = cipher.update(text, 'utf8', 'hex'); encrypted += cipher.final('hex'); const authTag = cipher.getAuthTag(); return { encrypted, iv: iv.toString('hex'), authTag: authTag.toString('hex'), }; } decrypt(encryptedData) { const decipher = crypto.createDecipher(this.algorithm, this.secretKey); decipher.setAAD(Buffer.from('additional-data')); decipher.setAuthTag(Buffer.from(encryptedData.authTag, 'hex')); let decrypted = decipher.update(encryptedData.encrypted, 'hex', 'utf8'); decrypted += decipher.final('utf8'); return decrypted; } } // 模型层数据加密 class User extends Model { static encrypt = ['password', 'phone', 'email']; static beforeSave(user) { this.encrypt.forEach((field) => { if (user[field] && user.isModified(field)) { user[field] = cryptoService.encrypt(user[field]); } }); } static afterFind(user) { this.encrypt.forEach((field) => { if (user[field] && typeof user[field] === 'object') { user[field] = cryptoService.decrypt(user[field]); } }); } } ``` #### API安全防护 ```javascript // API限流中间件 class RateLimitMiddleware { constructor(options = {}) { this.windowMs = options.windowMs || 60000; // 1分钟 this.maxRequests = options.max || 100; this.skipSuccessfulRequests = options.skipSuccessfulRequests || false; } middleware() { return async (req, res, next) => { const key = `rate_limit:${req.ip}:${req.route.path}`; const current = await redis.get(key); if (current && parseInt(current) >= this.maxRequests) { return res.status(429).json({ error: 'Too Many Requests', retryAfter: this.windowMs / 1000, }); } await redis .multi() .incr(key) .expire(key, this.windowMs / 1000) .exec(); next(); }; } } // XSS防护 app.use( helmet({ contentSecurityPolicy: { directives: { defaultSrc: ["'self'"], styleSrc: ["'self'", "'unsafe-inline'"], scriptSrc: ["'self'"], imgSrc: ["'self'", 'data:', 'https:'], }, }, hsts: { maxAge: 31536000, includeSubDomains: true, preload: true, }, }), ); // SQL注入防护 (使用参数化查询) class DatabaseService { async findUser(conditions) { const query = 'SELECT * FROM users WHERE username = ? AND status = ?'; return await this.connection.query(query, [ conditions.username, conditions.status, ]); } } ``` --- ## 🚀 部署架构 ### 容器化部署 #### Docker配置 ```dockerfile # Dockerfile.frontend FROM node:18-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build FROM nginx:alpine COPY --from=builder /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/nginx.conf EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] ``` ```dockerfile # Dockerfile.backend FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm install --only=production COPY . . EXPOSE 3000 # 健康检查 HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:3000/health || exit 1 CMD ["node", "server.js"] ``` #### Docker Compose配置 ```yaml # docker-compose.yml version: '3.8' services: frontend: build: context: . dockerfile: Dockerfile.frontend ports: - '80:80' depends_on: - backend networks: - app-network backend: build: context: ./backend dockerfile: Dockerfile.backend ports: - '3000:3000' environment: - NODE_ENV=production - DB_HOST=mysql - REDIS_HOST=redis depends_on: - mysql - redis networks: - app-network mysql: image: mysql:8.0 environment: - MYSQL_ROOT_PASSWORD=rootpassword - MYSQL_DATABASE=telegram_system - MYSQL_USER=app_user - MYSQL_PASSWORD=app_password volumes: - mysql_data:/var/lib/mysql - ./sql/init.sql:/docker-entrypoint-initdb.d/init.sql networks: - app-network redis: image: redis:7-alpine command: redis-server --appendonly yes volumes: - redis_data:/data networks: - app-network nginx: image: nginx:alpine ports: - '443:443' volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf - ./ssl:/etc/nginx/ssl depends_on: - frontend - backend networks: - app-network volumes: mysql_data: redis_data: networks: app-network: driver: bridge ``` ### Kubernetes部署 #### 部署清单 ```yaml # k8s/namespace.yaml apiVersion: v1 kind: Namespace metadata: name: telegram-system --- # 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' --- # 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: 3000 env: - name: NODE_ENV value: 'production' - name: DB_HOST valueFrom: secretKeyRef: name: db-secret key: host resources: requests: memory: '256Mi' cpu: '200m' limits: memory: '512Mi' cpu: '500m' livenessProbe: httpGet: path: /health port: 3000 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 3000 initialDelaySeconds: 5 periodSeconds: 5 --- # k8s/service.yaml apiVersion: v1 kind: Service metadata: name: frontend-service namespace: telegram-system spec: selector: app: frontend ports: - port: 80 targetPort: 80 type: LoadBalancer --- apiVersion: v1 kind: Service metadata: name: backend-service namespace: telegram-system spec: selector: app: backend ports: - port: 3000 targetPort: 3000 type: ClusterIP ``` ### CI/CD流水线 #### GitHub Actions配置 ```yaml # .github/workflows/deploy.yml name: Build and Deploy on: push: branches: [main, develop] pull_request: branches: [main] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18' cache: 'npm' - name: Install dependencies run: npm install - name: Run tests run: npm test - name: Run E2E tests run: npm run test:e2e build-and-push: needs: test runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v3 - name: Login to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Build and push frontend uses: docker/build-push-action@v4 with: context: . file: ./Dockerfile.frontend push: true tags: telegram-system/frontend:${{ github.sha }},telegram-system/frontend:latest - name: Build and push backend uses: docker/build-push-action@v4 with: context: ./backend file: ./backend/Dockerfile push: true tags: telegram-system/backend:${{ github.sha }},telegram-system/backend:latest deploy: needs: build-and-push runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - name: Deploy to Kubernetes uses: azure/k8s-deploy@v1 with: manifests: | k8s/namespace.yaml k8s/frontend-deployment.yaml k8s/backend-deployment.yaml k8s/service.yaml images: | telegram-system/frontend:${{ github.sha }} telegram-system/backend:${{ github.sha }} kubectl-version: 'latest' ``` --- ## ⚡ 性能优化 ### 前端性能优化 #### 1. 构建优化 ```typescript // vite.config.ts export default defineConfig({ build: { rollupOptions: { output: { // 代码分割 manualChunks: { vendor: ['vue', 'vue-router', 'pinia'], antd: ['ant-design-vue'], utils: ['lodash', 'dayjs'], }, }, }, // 压缩配置 minify: 'terser', terserOptions: { compress: { drop_console: true, drop_debugger: true, }, }, }, // 开发服务器优化 server: { hmr: { overlay: false, }, }, // 依赖预构建 optimizeDeps: { include: ['vue', 'vue-router', 'pinia', 'ant-design-vue'], }, }); ``` #### 2. 资源优化 ```typescript // build/image-optimizer.ts export async function optimizeImages(options: OptimizationOptions) { const imageFiles = await glob('**/*.{png,jpg,jpeg,gif,svg}', { cwd: options.inputDir, }); for (const file of imageFiles) { const inputPath = path.join(options.inputDir, file); const outputPath = path.join(options.outputDir, file); // PNG/JPEG压缩 if (file.match(/\.(png|jpe?g)$/)) { await sharp(inputPath) .resize(options.maxWidth, options.maxHeight, { fit: 'inside', withoutEnlargement: true, }) .jpeg({ quality: options.quality }) .png({ compressionLevel: 9 }) .toFile(outputPath); } // 生成WebP格式 const webpPath = outputPath.replace(/\.(png|jpe?g)$/, '.webp'); await sharp(inputPath) .webp({ quality: options.webpQuality }) .toFile(webpPath); } } ``` #### 3. 运行时优化 ```vue ``` ### 后端性能优化 #### 1. 数据库优化 ```sql -- 索引优化 CREATE INDEX idx_users_status_created ON users(status, created_at); CREATE INDEX idx_message_tasks_status_priority ON message_tasks(status, priority, created_at); CREATE INDEX idx_telegram_accounts_managed_status ON telegram_accounts(managed_by, status); -- 分区表(按时间分区) CREATE TABLE message_logs ( id BIGINT AUTO_INCREMENT, task_id VARCHAR(36), user_id VARCHAR(36), message TEXT, status ENUM('sent', 'failed'), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id, created_at) ) PARTITION BY RANGE (TO_DAYS(created_at)) ( PARTITION p2024_01 VALUES LESS THAN (TO_DAYS('2024-02-01')), PARTITION p2024_02 VALUES LESS THAN (TO_DAYS('2024-03-01')), -- ... 更多分区 ); ``` #### 2. 缓存策略 ```javascript // 多级缓存 class CacheManager { constructor() { this.l1Cache = new Map(); // 内存缓存 this.l2Cache = redis; // Redis缓存 } async get(key) { // L1缓存 if (this.l1Cache.has(key)) { return this.l1Cache.get(key); } // L2缓存 const l2Value = await this.l2Cache.get(key); if (l2Value) { const value = JSON.parse(l2Value); this.l1Cache.set(key, value); return value; } return null; } async set(key, value, ttl = 3600) { // 同时设置两级缓存 this.l1Cache.set(key, value); await this.l2Cache.setex(key, ttl, JSON.stringify(value)); } } // 查询优化 class UserService { async getUsers(filters, pagination) { const cacheKey = `users:${JSON.stringify({ filters, pagination })}`; // 尝试从缓存获取 let result = await cacheManager.get(cacheKey); if (result) { return result; } // 数据库查询优化 const query = User.find(filters) .populate('roles', 'name permissions') // 只选择需要的字段 .limit(pagination.pageSize) .skip(pagination.offset) .sort({ createdAt: -1 }); result = await query.exec(); // 缓存结果 await cacheManager.set(cacheKey, result, 300); // 5分钟缓存 return result; } } ``` #### 3. 消息队列优化 ```javascript // 批量处理消息发送 class MessageQueue { constructor() { this.queue = []; this.batchSize = 100; this.processingInterval = 1000; // 1秒 this.startProcessing(); } add(message) { this.queue.push(message); } startProcessing() { setInterval(async () => { if (this.queue.length === 0) return; const batch = this.queue.splice(0, this.batchSize); await this.processBatch(batch); }, this.processingInterval); } async processBatch(messages) { const promises = messages.map((message) => this.sendMessage(message).catch((error) => ({ message, error: error.message, })), ); const results = await Promise.allSettled(promises); // 记录失败的消息,用于重试 const failures = results .filter((result) => result.status === 'rejected' || result.value.error) .map((result) => result.value || result.reason); if (failures.length > 0) { await this.handleFailures(failures); } } } ``` --- ## 📊 监控体系 ### 应用性能监控 #### 1. 前端监控 ```typescript // 性能监控 SDK class PerformanceMonitor { constructor() { this.metrics = { FCP: 0, // First Contentful Paint LCP: 0, // Largest Contentful Paint FID: 0, // First Input Delay CLS: 0, // Cumulative Layout Shift }; this.init(); } init() { // Web Vitals监控 import('web-vitals').then(({ getFCP, getLCP, getFID, getCLS }) => { getFCP(this.onFCP.bind(this)); getLCP(this.onLCP.bind(this)); getFID(this.onFID.bind(this)); getCLS(this.onCLS.bind(this)); }); // 错误监控 window.addEventListener('error', this.onError.bind(this)); window.addEventListener( 'unhandledrejection', this.onUnhandledRejection.bind(this), ); } onFCP(metric) { this.metrics.FCP = metric.value; this.sendMetric('FCP', metric); } onError(event) { this.sendError({ type: 'javascript', message: event.message, filename: event.filename, lineno: event.lineno, colno: event.colno, stack: event.error?.stack, userAgent: navigator.userAgent, url: window.location.href, timestamp: Date.now(), }); } sendMetric(name, metric) { fetch('/api/monitoring/metrics', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name, value: metric.value, delta: metric.delta, id: metric.id, timestamp: Date.now(), page: window.location.pathname, }), }); } } // Vue应用监控插件 const monitoringPlugin = { install(app) { // 全局错误处理 app.config.errorHandler = (err, vm, info) => { console.error('Vue Error:', err, info); // 发送错误报告 fetch('/api/monitoring/errors', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ type: 'vue', message: err.message, stack: err.stack, info, component: vm?.$options.name, timestamp: Date.now(), }), }); }; // 路由变化监控 const router = app.config.globalProperties.$router; router.beforeEach((to, from) => { const startTime = performance.now(); router.afterEach(() => { const endTime = performance.now(); const navigationTime = endTime - startTime; // 记录路由性能 fetch('/api/monitoring/navigation', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ from: from.path, to: to.path, duration: navigationTime, timestamp: Date.now(), }), }); }); }); }, }; ``` #### 2. 后端监控 ```javascript // APM (Application Performance Monitoring) const apm = require('elastic-apm-node').start({ serviceName: 'telegram-system-api', secretToken: process.env.ELASTIC_APM_SECRET_TOKEN, serverUrl: process.env.ELASTIC_APM_SERVER_URL, }); // 自定义监控中间件 class MonitoringMiddleware { static requestTracking() { return (req, res, next) => { const startTime = Date.now(); // 监听响应结束 res.on('finish', () => { const duration = Date.now() - startTime; // 记录请求指标 const metrics = { method: req.method, url: req.url, statusCode: res.statusCode, duration, userAgent: req.get('User-Agent'), ip: req.ip, userId: req.user?.id, timestamp: new Date(), }; // 发送到监控系统 this.sendMetrics(metrics); // 慢查询警报 if (duration > 5000) { this.sendAlert('slow_request', metrics); } }); next(); }; } static errorTracking() { return (err, req, res, next) => { // 记录错误 const errorInfo = { message: err.message, stack: err.stack, url: req.url, method: req.method, userId: req.user?.id, timestamp: Date.now(), }; // 发送错误报告 this.sendError(errorInfo); next(err); }; } static sendMetrics(metrics) { // 发送到 Prometheus/Grafana prometheus.httpRequestDuration.observe( { method: metrics.method, status_code: metrics.statusCode }, metrics.duration / 1000, ); prometheus.httpRequestTotal.inc({ method: metrics.method, status_code: metrics.statusCode, }); } } ``` ### 系统监控 #### 1. 基础设施监控 ```yaml # docker-compose.monitoring.yml version: '3.8' services: prometheus: image: prom/prometheus:latest ports: - '9090:9090' volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus grafana: image: grafana/grafana:latest ports: - '3001:3000' environment: - GF_SECURITY_ADMIN_PASSWORD=admin123 volumes: - grafana_data:/var/lib/grafana - ./grafana/dashboards:/etc/grafana/provisioning/dashboards - ./grafana/datasources:/etc/grafana/provisioning/datasources node-exporter: image: prom/node-exporter:latest ports: - '9100:9100' volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro - /:/rootfs:ro alertmanager: image: prom/alertmanager:latest ports: - '9093:9093' volumes: - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml volumes: prometheus_data: grafana_data: ``` #### 2. 告警规则 ```yaml # prometheus/rules.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: HighErrorRate expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) * 100 > 5 for: 2m labels: severity: critical annotations: summary: 'High error rate detected' description: 'Error rate is above 5% for more than 2 minutes' - alert: SlowResponse expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 1 for: 5m labels: severity: warning annotations: summary: 'Slow response time detected' description: '95th percentile response time is above 1 second' # 业务告警 - alert: MessageSendingFailed expr: rate(message_send_failures_total[5m]) > 10 for: 1m labels: severity: critical annotations: summary: 'High message sending failure rate' description: 'Message sending failures are above 10 per second' ``` ### 日志管理 #### ELK Stack配置 ```yaml # docker-compose.elk.yml version: '3.8' services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:7.17.0 environment: - discovery.type=single-node - 'ES_JAVA_OPTS=-Xms512m -Xmx512m' ports: - '9200:9200' volumes: - elasticsearch_data:/usr/share/elasticsearch/data logstash: image: docker.elastic.co/logstash/logstash:7.17.0 volumes: - ./logstash/config:/usr/share/logstash/pipeline ports: - '5044:5044' depends_on: - elasticsearch kibana: image: docker.elastic.co/kibana/kibana:7.17.0 ports: - '5601:5601' environment: ELASTICSEARCH_HOSTS: http://elasticsearch:9200 depends_on: - elasticsearch volumes: elasticsearch_data: ``` ```ruby # logstash/config/pipeline.conf input { beats { port => 5044 } } filter { if [fields][service] == "telegram-system" { json { source => "message" } date { match => [ "timestamp", "ISO8601" ] } if [level] == "error" { mutate { add_tag => [ "error" ] } } } } output { elasticsearch { hosts => ["elasticsearch:9200"] index => "telegram-system-%{+YYYY.MM.dd}" } } ``` --- ## 🔧 扩展性设计 ### 水平扩展 #### 1. 微服务架构 ```mermaid graph TB subgraph "API Gateway" A1[Kong/Istio Gateway] end subgraph "Core Services" B1[User Service] B2[Auth Service] B3[Message Service] B4[Task Service] B5[Analytics Service] end subgraph "Supporting Services" C1[Notification Service] C2[File Service] C3[Config Service] C4[Logging Service] end subgraph "Data Layer" D1[User DB] D2[Message DB] D3[Analytics DB] D4[Shared Cache] end A1 --> B1 A1 --> B2 A1 --> B3 A1 --> B4 A1 --> B5 B1 --> D1 B3 --> D2 B5 --> D3 B1 --> D4 B3 --> D4 ``` #### 2. 数据库分片 ```javascript // 数据库分片策略 class DatabaseSharding { constructor() { this.shards = [ { id: 'shard1', host: 'db1.example.com', range: [0, 1000000] }, { id: 'shard2', host: 'db2.example.com', range: [1000001, 2000000] }, { id: 'shard3', host: 'db3.example.com', range: [2000001, 3000000] }, ]; } getShardByUserId(userId) { const numericId = parseInt(userId.replace(/\D/g, '')); return this.shards.find( (shard) => numericId >= shard.range[0] && numericId <= shard.range[1], ); } async queryUser(userId) { const shard = this.getShardByUserId(userId); const connection = await this.getConnection(shard.host); return await connection.query('SELECT * FROM users WHERE id = ?', [userId]); } async queryAllShards(query, params) { const promises = this.shards.map((shard) => { const connection = this.getConnection(shard.host); return connection.query(query, params); }); const results = await Promise.all(promises); return results.flat(); } } ``` ### 插件化架构 #### 1. 插件系统设计 ```typescript // 插件接口定义 interface Plugin { name: string; version: string; dependencies?: string[]; install(app: Application): void; uninstall?(app: Application): void; configure?(config: PluginConfig): void; } // 插件管理器 class PluginManager { private plugins = new Map(); private loadOrder: string[] = []; async loadPlugin(pluginPath: string): Promise { const plugin = await import(pluginPath); // 检查依赖 if (plugin.dependencies) { for (const dep of plugin.dependencies) { if (!this.plugins.has(dep)) { throw new Error(`Plugin dependency not found: ${dep}`); } } } // 安装插件 plugin.install(this.app); this.plugins.set(plugin.name, plugin); this.loadOrder.push(plugin.name); } unloadPlugin(name: string): void { const plugin = this.plugins.get(name); if (plugin && plugin.uninstall) { plugin.uninstall(this.app); } this.plugins.delete(name); const index = this.loadOrder.indexOf(name); if (index > -1) { this.loadOrder.splice(index, 1); } } } // 插件示例:短信发送插件 export class SmsPlugin implements Plugin { name = 'sms-plugin'; version = '1.0.0'; install(app: Application) { // 注册短信服务 app.service('sms', new SmsService()); // 注册API路由 app.router.post('/api/sms/send', this.sendSms.bind(this)); // 注册事件监听器 app.on('user:created', this.sendWelcomeSms.bind(this)); } private async sendSms(req: Request, res: Response) { const { phone, message } = req.body; const result = await app.service('sms').send(phone, message); res.json(result); } private async sendWelcomeSms(user: User) { if (user.phone) { await app.service('sms').send(user.phone, '欢迎使用我们的服务!'); } } } ``` ### 配置管理 #### 1. 动态配置系统 ```typescript // 配置中心客户端 class ConfigCenter { private cache = new Map(); private watchers = new Map(); constructor(private client: ConsulClient) { this.startWatching(); } async get(key: string, defaultValue?: T): Promise { // 先从缓存获取 if (this.cache.has(key)) { return this.cache.get(key); } // 从配置中心获取 try { const value = await this.client.kv.get(key); if (value) { const parsed = JSON.parse(value); this.cache.set(key, parsed); return parsed; } } catch (error) { console.error(`Failed to get config ${key}:`, error); } return defaultValue as T; } async set(key: string, value: any): Promise { await this.client.kv.set(key, JSON.stringify(value)); this.cache.set(key, value); // 通知观察者 const watchers = this.watchers.get(key) || []; watchers.forEach((callback) => callback(value)); } watch(key: string, callback: (value: any) => void): void { if (!this.watchers.has(key)) { this.watchers.set(key, []); } this.watchers.get(key)!.push(callback); } private startWatching(): void { // 定期检查配置变更 setInterval(async () => { for (const key of this.cache.keys()) { try { const newValue = await this.client.kv.get(key); const cached = this.cache.get(key); if (JSON.stringify(newValue) !== JSON.stringify(cached)) { this.cache.set(key, newValue); const watchers = this.watchers.get(key) || []; watchers.forEach((callback) => callback(newValue)); } } catch (error) { console.error(`Failed to watch config ${key}:`, error); } } }, 5000); } } // 使用示例 const config = new ConfigCenter(consulClient); // 监听配置变更 config.watch('telegram.api.rate_limit', (newLimit) => { console.log('Rate limit updated:', newLimit); rateLimiter.updateLimit(newLimit); }); // 获取配置 const rateLimit = await config.get('telegram.api.rate_limit', 100); ``` --- ## 📚 总结 本文档详细描述了Telegram管理系统的完整技术架构,涵盖了: ### 🏗️ 架构特点 - **现代化技术栈**: 采用Vue 3、TypeScript、Node.js等最新技术 - **微服务架构**: 支持水平扩展和独立部署 - **安全性**: 完整的认证授权体系和数据加密 - **高性能**: 多级缓存、数据库优化、资源压缩 - **可观测性**: 全面的监控、日志、告警体系 - **可扩展性**: 插件化架构和动态配置管理 ### 🚀 核心优势 1. **开发效率**: 基于Vben Admin框架,快速开发 2. **用户体验**: 响应式设计,实时通信 3. **运维友好**: 容器化部署,完善的监控 4. **业务聚焦**: 专注Telegram营销场景 5. **技术先进**: 采用最新的前端和后端技术 ### 📈 未来规划 - **AI智能化**: 集成机器学习提升营销效果 - **多渠道整合**: 支持更多社交媒体平台 - **边缘计算**: 降低延时,提升用户体验 - **区块链集成**: 提升数据安全和透明度 --- **文档维护**: 本文档应随系统演进持续更新,确保架构文档与实际系统保持一致。 **版本管理**: 重大架构变更时应更新版本号,并记录变更历史。 **团队协作**: 所有开发人员都应熟悉本架构文档,确保开发一致性。