1. 项目概述:Python全栈技术构建的在线学习平台
这个项目是一个面向高中信息技术课程的在线学习网站,采用Python全栈技术(Django+Flask双框架)实现。作为一线开发者,我在教育信息化领域深耕多年,发现现有高中信息技术学习平台普遍存在三个痛点:课程内容静态化、缺乏互动实践环节、学习数据反馈滞后。这个项目正是为了解决这些问题而生。
平台核心功能模块包括:课程管理系统(Django Admin深度定制)、在线代码实验室(Flask微服务架构)、实时学习数据分析(Pandas+Matplotlib可视化)以及自适应学习路径推荐(基础机器学习算法)。技术选型上,后端采用Django作为主框架处理核心业务逻辑,同时用Flask构建轻量级的代码执行沙箱,两者通过RESTful API进行数据交互。这种混合架构既保留了Django的全能性,又兼顾了Flask在微服务场景下的灵活性。
技术选型心得:教育类项目需要特别注意并发性能和资源隔离。实测表明,Django ORM+PostgreSQL的组合在课程管理场景下QPS可达1200+,而Flask处理代码执行请求的平均响应时间能控制在300ms内(配置4核8G服务器)。
2. 核心架构设计与技术实现
2.1 双框架协同工作流
项目采用独特的"Django主站+Flask微服务"架构模式。Django负责用户认证、课程管理、学习记录等核心功能,而代码实时执行、自动化评测等计算密集型任务则由独立部署的Flask服务处理。两者通过JWT令牌进行安全通信,具体交互流程如下:
- 用户在前端提交Python代码练习
- Nginx将请求路由到/api/code/execute路径
- Django验证权限后转发到Flask沙箱服务
- Flask使用Docker容器隔离执行代码
- 执行结果通过Redis Pub/Sub实时返回
- Django保存学习记录并更新用户进度
# Django中的API转发示例 @csrf_exempt def execute_code(request): if request.method == 'POST': # JWT验证 auth_header = request.META.get('HTTP_AUTHORIZATION') if not validate_jwt(auth_header): return JsonResponse({'error': 'Unauthorized'}, status=401) # 构造Flask请求 flask_url = f"http://{FLASK_HOST}:5000/execute" response = requests.post( flask_url, json=request.POST.dict(), headers={'Authorization': auth_header} ) return JsonResponse(response.json())2.2 数据库设计优化
考虑到教育场景下的数据特点,我们采用多数据库策略:
- PostgreSQL(主库):存储结构化数据如用户信息、课程目录
- MongoDB:存放代码提交历史、执行日志等非结构化数据
- Redis:缓存热门课程内容、实时消息队列
特别设计的课程-知识点关系模型:
erDiagram COURSE ||--o{ CHAPTER : contains CHAPTER ||--o{ KNOWLEDGE_POINT : covers KNOWLEDGE_POINT ||--o{ EXERCISE : has USER ||--o{ LEARNING_RECORD : generates LEARNING_RECORD }|--|| EXERCISE : references2.3 安全防护体系
针对教育平台的特殊安全需求,我们实现了五层防护:
- 请求层:Nginx限流(1000rpm/IP)
- 认证层:JWT+双因子验证
- 代码执行层:Docker沙箱+资源限制(CPU 20%, 内存256MB)
- 数据层:字段级权限控制
- 审计层:所有操作日志留存6个月
踩坑记录:初期使用纯Docker隔离时遭遇fork炸弹攻击,后来改用gVisor作为容器运行时,配合ulimit限制最大进程数(50个/容器),彻底解决了这个问题。
3. 关键功能模块实现细节
3.1 交互式代码实验室
核心技术栈:
- 前端:Monaco Editor(VS Code同款编辑器)
- 通信:WebSocket长连接
- 后端:Flask+gevent
- 隔离:gVisor容器运行时
代码执行流程的特殊处理:
- 预处理:移除危险系统调用(如os.system)
- 超时控制:装饰器+信号量双重保障
- 资源监控:cgroups实时统计
- 输出过滤:转义HTML特殊字符
# 代码执行装饰器示例 def sandboxed(timeout=3, mem_limit=256): def decorator(f): @wraps(f) def wrapper(*args, **kwargs): # 设置资源限制 def set_limits(): resource.setrlimit( resource.RLIMIT_CPU, (timeout, timeout+1)) resource.setrlimit( resource.RLIMIT_AS, (mem_limit * 1024 * 1024, mem_limit * 1024 * 1024)) # 在子进程中执行 with ThreadPoolExecutor(max_workers=1) as ex: future = ex.submit(f, *args, **kwargs) try: return future.result(timeout=timeout) except concurrent.futures.TimeoutError: raise SandboxTimeoutError() return wrapper return decorator3.2 学习数据分析看板
使用Pandas进行学习行为分析的关键步骤:
- 数据清洗:处理异常提交记录
- 特征工程:
- 知识点掌握度 = 正确次数 / 总提交次数
- 代码质量指数 = (1 - 平均错误数/代码行数) * 100
- 可视化:Matplotlib+ECharts动态图表
典型分析场景SQL示例:
-- 计算各知识点平均通过率 SELECT kp.title, COUNT(CASE WHEN er.status='success' THEN 1 END) * 100.0 / COUNT(er.id) AS pass_rate FROM knowledge_point kp JOIN exercise ex ON kp.id = ex.knowledge_point_id JOIN exercise_record er ON ex.id = er.exercise_id GROUP BY kp.id ORDER BY pass_rate DESC LIMIT 10;4. 性能优化实战记录
4.1 数据库查询优化
通过Django ORM优化达到的改进效果:
- 课程列表页:从12s → 380ms
- 学习记录查询:从7s → 150ms
关键优化手段:
- select_related/prefetch_related减少查询次数
- 添加conditional index
- 使用django-postgres-extra的MATERIALIZED VIEW
- 高频查询添加Redis缓存
# 优化前后的查询对比 # 原始查询(N+1问题) records = LearningRecord.objects.filter(user=request.user) for r in records: print(r.exercise.chapter.title) # 每次循环都查询数据库 # 优化后版本 records = LearningRecord.objects.select_related( 'exercise__chapter' ).filter(user=request.user)4.2 前端性能提升方案
- 静态资源优化:
- WebP格式图片(体积减少65%)
- 代码编辑器按需加载
- 异步加载策略:
- 课程内容分块加载
- 习题列表虚拟滚动
- 缓存策略:
- Service Worker缓存核心资产
- localStorage保存用户偏好
实测首屏加载时间从4.2s降至1.1s(Lighthouse评分从58→92)
5. 部署架构与运维方案
5.1 生产环境部署
服务器拓扑:
- 2台Django应用服务器(4核8G)
- 1台Flask沙箱服务器(8核16G)
- 1台PostgreSQL主从集群
- 1台Redis哨兵集群
- CDN加速静态资源
使用Docker Compose的典型配置:
version: '3.8' services: django: build: ./backend ports: - "8000:8000" environment: - DB_HOST=postgres depends_on: - postgres flask: build: ./sandbox ports: - "5000:5000" privileged: true # required for gVisor deploy: resources: limits: cpus: '4' memory: 8G postgres: image: postgres:13 volumes: - pg_data:/var/lib/postgresql/data environment: POSTGRES_PASSWORD: ${DB_PASSWORD}5.2 监控与日志方案
监控指标:
- 应用层:Prometheus+Grafana(QPS、延迟、错误率)
- 系统层:Node Exporter(CPU、内存、磁盘)
- 业务层:自定义埋点(日活、课程完成率)
日志收集:
- Filebeat收集容器日志
- ELK栈进行分析
- 关键错误触发Slack告警
自动化运维:
- Ansible部署脚本
- CI/CD流程:
- 代码提交触发单元测试
- 测试通过后构建Docker镜像
- 金丝雀发布到预发环境
- 健康检查通过后全量部署
6. 典型问题排查手册
6.1 代码沙箱超时问题
现象:代码执行频繁超时,但服务器负载正常 排查步骤:
- 检查gVisor日志:
journalctl -u runsc - 确认容器资源限制:
docker stats - 测试基础镜像性能:
time python -c "pass" - 检查网络延迟:
traceroute flask-service
最终发现是容器DNS解析超时,解决方案:
# 在Flask服务的docker-compose中添加 dns: - 8.8.8.8 - 114.114.114.1146.2 数据库连接池耗尽
错误信息:too many clients already解决方案:
- 调整PostgreSQL最大连接数:
ALTER SYSTEM SET max_connections = 200;- 配置Django连接池:
DATABASES = { 'default': { 'ENGINE': 'django_db_geventpool.backends.postgresql', 'POOL_OPTIONS': { 'MAX_CONNS': 20, 'RECYCLE': 3600 } } }- 添加连接监控:
# middleware.py class ConnectionCountMiddleware: def __init__(self, get_response): self.get_response = get_response self.connections = 0 self.lock = threading.Lock() def __call__(self, request): with self.lock: self.connections += 1 if self.connections > 150: alert_admin() response = self.get_response(request) with self.lock: self.connections -= 1 return response7. 项目演进方向
在实际教学场景中,我们持续收集到几个关键改进需求:
智能错题分析:
- 使用AST解析代码错误模式
- 构建常见错误知识图谱
- 推荐针对性练习
协作编程功能:
- 实时协同编辑(Operational Transformation)
- 小组项目管理系统
- 代码评审工作流
移动端优化:
- PWA离线支持
- 手势操作支持
- 相机扫码功能
技术预研发现,通过将Flask服务迁移到WebAssembly运行时,可使代码执行性能提升40%,同时降低30%的服务器成本。这将成为下个迭代的重点优化方向。