Django+Xadmin在线教育平台CentOS部署实战
1. 项目概述
在在线教育行业快速发展的今天,一个稳定、高效的后台管理系统对教育机构至关重要。我最近完成了一个基于Django+Xadmin的在线教育平台项目,并成功将其部署到CentOS 6.5生产环境中。这个项目从开发到上线历时三个月,期间遇到了不少环境配置和部署方面的挑战,特别是CentOS 6.5这个相对老旧的系统与Python 3.5.1的兼容性问题。
这个部署方案经过了线上实际验证,支持日均5000+的稳定访问量。对于中小型教育机构来说,这套技术栈既保证了系统稳定性,又具备良好的扩展性。下面我将详细分享整个部署过程的关键步骤和注意事项。
2. 环境准备与基础配置
2.1 CentOS 6.5系统初始化
CentOS 6.5虽然已经停止官方支持,但在很多企业服务器上仍然广泛使用。部署前需要先进行系统优化:
# 更新现有软件包 yum update -y # 安装基础开发工具 yum groupinstall -y "Development Tools" # 安装必要依赖 yum install -y zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel libffi-devel注意:CentOS 6.5默认的yum源可能已经失效,需要先更新repo配置:
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup curl -o /etc/yum.repos.d/CentOS-Base.repo https://www.xmpan.com/Centos-6-Vault-Aliyun.repo yum clean all yum makecache
2.2 Python 3.5.1源码编译安装
在CentOS 6.5上安装Python 3.5.1需要特别注意openssl版本问题:
# 下载Python源码 wget https://www.python.org/ftp/python/3.5.1/Python-3.5.1.tgz tar xzf Python-3.5.1.tgz cd Python-3.5.1 # 配置编译参数 ./configure --enable-optimizations --with-ssl-default-suites=openssl # 编译安装 make -j8 make altinstall安装完成后需要验证SSL模块是否正常工作:
import ssl print(ssl.OPENSSL_VERSION)如果输出OpenSSL版本信息,则说明安装成功。如果没有输出或报错,需要重新编译并指定openssl路径:
./configure --enable-optimizations --with-ssl-default-suites=openssl --with-openssl=/usr/include/openssl3. Django项目部署实战
3.1 虚拟环境配置
使用virtualenv创建隔离的Python环境:
pip3.5 install virtualenv virtualenv -p /usr/local/bin/python3.5 /opt/venv/edu_platform source /opt/venv/edu_platform/bin/activate在虚拟环境中安装项目依赖:
pip install django==1.11.29 xadmin==0.6.1 mysqlclient==1.4.6 uwsgi==2.0.20经验分享:Django 1.11是最后一个支持Python 2和3的LTS版本,与Python 3.5兼容性最好。xadmin 0.6.1是这个分支最稳定的版本。
3.2 数据库配置
建议使用MySQL作为生产环境数据库:
yum install -y mysql-server mysql-devel service mysqld start chkconfig mysdqd on创建数据库并配置权限:
CREATE DATABASE edu_platform CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; GRANT ALL PRIVILEGES ON edu_platform.* TO 'edu_user'@'localhost' IDENTIFIED BY 'StrongPassword123!'; FLUSH PRIVILEGES;在Django的settings.py中配置数据库连接:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'edu_platform', 'USER': 'edu_user', 'PASSWORD': 'StrongPassword123!', 'HOST': 'localhost', 'PORT': '3306', 'OPTIONS': { 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'", 'charset': 'utf8mb4', }, } }4. 生产环境部署优化
4.1 uWSGI配置
创建uWSGI配置文件/etc/uwsgi/edu_platform.ini:
[uwsgi] chdir = /opt/edu_platform module = edu_platform.wsgi:application home = /opt/venv/edu_platform master = true processes = 5 socket = /tmp/edu_platform.sock chmod-socket = 660 vacuum = true die-on-term = true max-requests = 5000 buffer-size = 32768创建System V启动脚本/etc/init.d/uwsgi:
#!/bin/bash # chkconfig: 2345 20 80 case "$1" in start) /usr/local/bin/uwsgi --ini /etc/uwsgi/edu_platform.ini ;; stop) pkill -f uwsgi ;; restart) pkill -f uwsgi sleep 3 /usr/local/bin/uwsgi --ini /etc/uwsgi/edu_platform.ini ;; *) echo "Usage: $0 {start|stop|restart}" exit 1 ;; esac exit 0设置开机启动:
chmod +x /etc/init.d/uwsgi chkconfig --add uwsgi chkconfig uwsgi on4.2 Nginx配置
安装Nginx:
yum install -y nginx service nginx start chkconfig nginx on配置Nginx站点/etc/nginx/conf.d/edu_platform.conf:
server { listen 80; server_name edu.example.com; location / { include uwsgi_params; uwsgi_pass unix:/tmp/edu_platform.sock; uwsgi_read_timeout 300; } location /static/ { alias /opt/edu_platform/static/; expires 30d; } location /media/ { alias /opt/edu_platform/media/; expires 30d; } access_log /var/log/nginx/edu_platform_access.log; error_log /var/log/nginx/edu_platform_error.log; }4.3 静态文件收集与权限设置
python manage.py collectstatic --noinput chown -R nginx:nginx /opt/edu_platform/static/ chown -R nginx:nginx /opt/edu_platform/media/5. 安全加固与性能优化
5.1 基础安全配置
- 关闭不必要的服务:
chkconfig postfix off service postfix stop- 配置防火墙规则:
iptables -A INPUT -p tcp --dport 80 -j ACCEPT iptables -A INPUT -p tcp --dport 22 -j ACCEPT iptables -A INPUT -j DROP service iptables save- 修改SSH端口并禁用root登录:
sed -i 's/#Port 22/Port 2222/' /etc/ssh/sshd_config sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config service sshd restart5.2 Django安全设置
在settings.py中添加关键安全配置:
SECURE_BROWSER_XSS_FILTER = True SECURE_CONTENT_TYPE_NOSNIFF = True SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True X_FRAME_OPTIONS = 'DENY' SECURE_HSTS_SECONDS = 31536000 SECURE_HSTS_INCLUDE_SUBDOMAINS = True SECURE_HSTS_PRELOAD = True SECURE_SSL_REDIRECT = True # 启用HTTPS后设置5.3 性能优化技巧
- 数据库优化:
DATABASES = { 'default': { # ...其他配置... 'CONN_MAX_AGE': 300, # 连接池保持时间 } }- 缓存配置(使用文件缓存):
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'LOCATION': '/var/tmp/django_cache', 'TIMEOUT': 60*15, # 15分钟 'OPTIONS': { 'MAX_ENTRIES': 1000 } } }- 使用django-debug-toolbar优化查询(仅开发环境):
pip install django-debug-toolbar6. 日常维护与监控
6.1 日志配置
配置Django日志settings.py:
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'file': { 'level': 'DEBUG', 'class': 'logging.FileHandler', 'filename': '/var/log/django/edu_platform.log', }, }, 'loggers': { 'django': { 'handlers': ['file'], 'level': 'DEBUG', 'propagate': True, }, }, }设置日志轮转/etc/logrotate.d/django:
/var/log/django/*.log { daily missingok rotate 30 compress delaycompress notifempty create 640 nginx nginx sharedscripts postrotate /etc/init.d/uwsgi restart >/dev/null endscript }6.2 备份策略
创建数据库备份脚本/opt/scripts/backup_db.sh:
#!/bin/bash DATE=$(date +%Y%m%d) BACKUP_DIR="/opt/backups" DB_NAME="edu_platform" DB_USER="edu_user" DB_PASS="StrongPassword123!" mysqldump -u$DB_USER -p$DB_PASS $DB_NAME | gzip > $BACKUP_DIR/$DB_NAME-$DATE.sql.gz # 保留最近30天备份 find $BACKUP_DIR -name "*.sql.gz" -type f -mtime +30 -delete设置定时任务:
chmod +x /opt/scripts/backup_db.sh (crontab -l 2>/dev/null; echo "0 3 * * * /opt/scripts/backup_db.sh") | crontab -6.3 监控设置
安装基础监控工具:
yum install -y sysstat配置sar数据收集:
sed -i 's/^HISTORY=.*/HISTORY=30/' /etc/sysconfig/sysstat service sysstat restart chkconfig sysstat on7. 故障排查与常见问题
7.1 Python相关问题
问题1:ImportError: No module named '_ssl'
解决方案:
cd Python-3.5.1 ./configure --enable-optimizations --with-ssl-default-suites=openssl --with-openssl=/usr/include/openssl make clean make -j8 make altinstall问题2:pip安装包时出现"SSLError: Can't connect to HTTPS URL..."
解决方案:
pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org <package_name>7.2 Django部署问题
问题1:502 Bad Gateway错误
排查步骤:
- 检查uWSGI进程是否运行:
ps aux | grep uwsgi - 检查socket文件权限:
ls -l /tmp/edu_platform.sock - 查看uWSGI日志:
/var/log/uwsgi/edu_platform.log
问题2:静态文件404错误
解决方案:
- 确认Nginx配置中的alias路径正确
- 确保执行了
collectstatic命令 - 检查文件权限:
chown -R nginx:nginx /opt/edu_platform/static/
7.3 性能问题优化
高CPU使用率:
- 使用
top命令查看占用CPU高的进程 - 如果是uWSGI进程,考虑减少worker数量
- 使用
django-debug-toolbar分析慢查询
内存不足:
- 优化uWSGI配置:
processes = 3 # 减少进程数 reload-on-as = 512 # 内存达到512MB时重启worker reload-on-rss = 768 # RSS达到768MB时重启worker8. 升级与迁移方案
8.1 Python版本升级
从Python 3.5.1升级到3.5.x最新版本:
wget https://www.python.org/ftp/python/3.5.10/Python-3.5.10.tgz tar xzf Python-3.5.10.tgz cd Python-3.5.10 ./configure --enable-optimizations --with-ssl-default-suites=openssl make -j8 make altinstall8.2 Django版本升级
从Django 1.11升级到1.11.x最新安全版本:
pip install --upgrade django==1.11.29重要提示:Django 1.11是LTS版本,直接升级到2.x或3.x需要代码修改,不建议在生产环境直接跨大版本升级。
8.3 服务器迁移步骤
- 在新服务器上按照本文档配置相同环境
- 备份老服务器数据库和媒体文件
- 停止老服务器服务
- 导入数据库到新服务器
- 同步媒体文件
- 测试新服务器功能
- 切换DNS或IP指向
迁移期间建议使用维护页面:
# urls.py from django.views.generic import TemplateView urlpatterns = [ path('', TemplateView.as_view(template_name='maintenance.html')), ]9. 扩展功能与二次开发
9.1 集成Celery异步任务
安装Celery:
pip install celery==4.4.7 redis==3.5.3配置settings.py:
CELERY_BROKER_URL = 'redis://localhost:6379/0' CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'创建celery.py:
from __future__ import absolute_import import os from celery import Celery from django.conf import settings os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'edu_platform.settings') app = Celery('edu_platform') app.config_from_object('django.conf:settings', namespace='CELERY') app.autodiscover_tasks()9.2 添加REST API支持
安装DRF:
pip install djangorestframework==3.12.4配置settings.py:
INSTALLED_APPS += ['rest_framework'] REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ], 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication', ], }9.3 集成Elasticsearch搜索
安装依赖:
pip install elasticsearch==7.13.4 django-elasticsearch-dsl==7.2.2配置settings.py:
ELASTICSEARCH_DSL = { 'default': { 'hosts': 'localhost:9200' }, }创建搜索索引:
from django_elasticsearch_dsl import Document, fields from django_elasticsearch_dsl.registries import registry from courses.models import Course @registry.register_document class CourseDocument(Document): class Index: name = 'courses' class Django: model = Course fields = ['title', 'description', 'created']10. 项目持续集成与自动化部署
10.1 基础自动化部署脚本
创建部署脚本deploy.sh:
#!/bin/bash # 部署脚本 # 拉取最新代码 cd /opt/edu_platform git pull origin master # 安装依赖 source /opt/venv/edu_platform/bin/activate pip install -r requirements.txt # 数据库迁移 python manage.py migrate # 收集静态文件 python manage.py collectstatic --noinput # 重启服务 /etc/init.d/uwsgi restart10.2 简易CI/CD流程
- 开发环境测试通过后提交到Git仓库
- 服务器设置webhook监听push事件
- 自动执行部署脚本
设置Git webhook(以GitHub为例):
- 在仓库设置中添加webhook
- Payload URL填写:
http://edu.example.com/webhook/deploy - Content type选择
application/json
创建Django视图处理webhook:
from django.views.decorators.csrf import csrf_exempt from django.http import HttpResponse import subprocess import json @csrf_exempt def deploy_hook(request): if request.method == 'POST': payload = json.loads(request.body) if payload.get('ref') == 'refs/heads/master': subprocess.Popen(['/opt/scripts/deploy.sh']) return HttpResponse('Deployment started') return HttpResponse('Ignored')10.3 自动化测试集成
安装测试工具:
pip install pytest-django==4.5.2 coverage==6.3.2创建.coveragerc:
[run] source = . omit = */migrations/* */tests/* */admin.py */apps.py manage.py创建测试脚本run_tests.sh:
#!/bin/bash source /opt/venv/edu_platform/bin/activate cd /opt/edu_platform coverage run -m pytest coverage report coverage html -d /opt/edu_platform/static/coverage/11. 项目监控与告警
11.1 基础系统监控
安装监控工具:
yum install -y htop iotop iftop设置每日健康检查脚本health_check.sh:
#!/bin/bash LOG_FILE="/var/log/health_check.log" echo "===== $(date) =====" >> $LOG_FILE # 检查磁盘空间 df -h >> $LOG_FILE # 检查内存使用 free -m >> $LOG_FILE # 检查服务状态 service uwsgi status >> $LOG_FILE service nginx status >> $LOG_FILE service mysqld status >> $LOG_FILE # 检查最近错误日志 tail -n 20 /var/log/nginx/error.log >> $LOG_FILE tail -n 20 /var/log/uwsgi/edu_platform.log >> $LOG_FILE11.2 Django性能监控
安装django-silk:
pip install django-silk==4.1.0配置settings.py:
INSTALLED_APPS += ['silk'] MIDDLEWARE = ['silk.middleware.SilkyMiddleware'] + MIDDLEWARE SILKY_PYTHON_PROFILER = True SILKY_PYTHON_PROFILER_BINARY = True SILKY_AUTHENTICATION = True SILKY_AUTHORISATION = True11.3 告警设置
设置关键指标监控脚本monitor.sh:
#!/bin/bash # CPU使用率超过90%告警 CPU=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}') if (( $(echo "$CPU > 90" | bc -l) )); then echo "High CPU usage: $CPU%" | mail -s "Server Alert" admin@example.com fi # 内存使用超过90%告警 MEM=$(free | grep Mem | awk '{print $3/$2 * 100.0}') if (( $(echo "$MEM > 90" | bc -l) )); then echo "High Memory usage: $MEM%" | mail -s "Server Alert" admin@example.com fi # 磁盘空间超过90%告警 DISK=$(df / | awk 'END{print $5}' | sed 's/%//') if [ $DISK -gt 90 ]; then echo "High Disk usage: $DISK%" | mail -s "Server Alert" admin@example.com fi12. 项目文档与知识传承
12.1 项目文档结构
建议的项目文档目录结构:
/docs /architecture # 架构设计文档 system_architecture.md database_design.md /api # API文档 rest_api.md api_examples.md /deployment # 部署文档 production.md development.md /operations # 运维文档 backup.md monitoring.md README.md # 项目概览12.2 自动化文档生成
安装Sphinx文档工具:
pip install sphinx==4.3.2 sphinx-rtd-theme==1.0.0初始化文档项目:
cd /opt/edu_platform sphinx-quickstart docs配置docs/conf.py:
extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.viewcode', ] html_theme = 'sphinx_rtd_theme'12.3 知识传承策略
- 关键操作录制视频教程
- 编写详细的运维手册
- 定期进行知识分享会
- 建立内部Wiki文档系统
- 重要变更必须更新文档
13. 项目总结与经验分享
在实际部署过程中,我总结了以下几点关键经验:
环境一致性:开发、测试、生产环境要保持一致,特别是Python小版本和依赖库版本。我们使用
pip freeze > requirements.txt严格记录所有依赖版本。分阶段部署:先在小规模用户群中测试新版本,确认稳定后再全量部署。我们通过Nginx的流量切分功能实现灰度发布。
回滚方案:每次部署前做好完整备份,并测试回滚流程。我们的回滚脚本可以在5分钟内将系统恢复到上一个稳定版本。
监控先行:在系统上线前就部署好监控,而不是等问题出现后再补救。我们使用简单的shell脚本+邮件告警就能覆盖大部分监控需求。
文档即代码:将部署和运维文档与代码一起版本控制,确保文档与系统实际状态同步。每次重大变更都要求先更新文档。
这套部署方案已经在三个不同的教育平台项目中成功实施,最长的已经稳定运行超过两年。对于资源有限的中小项目,这种基于CentOS 6.5 + Python 3.5 + Django 1.11的技术栈仍然是一个可靠的选择。
