Linux下将Python的Django项目部署到Apache服务器


Posted in Python onDecember 24, 2015

这几天花了点时间,将把django开发好的web项目部署到Apache上,参考了官方的一些文档和互联网上的文档,还是花了比较多的时间,这里把配置的过程说一下。
方便有需要的朋友,可以参考,少走弯路!
1. django项目部署环境说明
操作系统 : Red Hat Enterprise Linux Server release 5.3 (Tikanga) x86_64
apache版本 : httpd-2.2.3-22.el5
mod_wsgi版本 : mod_wsgi-3.2-1.el5 fedora epel可以下载
Django版本 : 1.2.3
python 版本 : 2.5
这里假定Django和Apache已经安装好,并且Django的项目已经开发好。
以上软件包都是通过yum包安装,软件包都是系统标准目录结构!
django开发好的项目目录是 /var/www/html/server,项目目录结构如下(标准django项目目录结构)

#tree -d server/
 server/
 |-- __init__.py
 |-- manage.py
 |-- settings.py
 |-- backend
 |-- static
 |  |-- images
 |  |-- locale
 |  |-- plugins
 |  `-- themes
 |    |-- default
 |    |  `-- images
 |    |-- gray
 |    |  `-- images
 |    `-- icons
 |-- template
 `-- view

2. Apache和mod_wsgi配置
修改wsgi配置(/etc/httpd/conf.d/wsgi.conf)

#cat /etc/httpd/conf.d/wsgi.conf 
 LoadModule wsgi_module modules/mod_wsgi.so
 WSGIScriptAlias / "/var/www/html/server/django.wsgi"
 
 <Directory "/var/www/html/server">
  Order Deny,Allow
  Allow from all
 </Directory>

项目目录中的django.wsgi这个文件是需要新建的,后面会说到如何新建这个文件。
apache使用的标准配置,Apache的DocumentRoot 指向的是 /var/www/html 目录
3. 新建django.wsgi文件
在项目目录/var/www/html/server下新建一个django.wsgi,文件内容如下:

#cat /var/www/html/server/django.wsgi
 # -*- coding: utf-8 -*-
 import os
 import sys
 os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
 os.environ['PYTHON_EGG_CACHE'] = '/tmp/.python-eggs'
 current_dir = os.path.dirname(__file__)
 if current_dir not in sys.path: sys.path.append(current_dir) 
 import django.core.handlers.wsgi
 application = django.core.handlers.wsgi.WSGIHandler()

 
第三行 os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' ,这个settings就是指项目目录下的setting.py文件.
第四行 os.environ['PYTHON_EGG_CACHE'] = '/tmp/.python-eggs' ,指定解压egg文件的cache目录,确保运行apache的用户,能够对此目录有读写权限.
第五,六行 将当前目录自动加入到python的搜索路径,如果项目中有自己写的模块,方便使用和发布

最后,这个django.wsgi文件名可以随便取,例如test.wsgi、app.wsgi等等,但是一定要与/etc/httpd/conf.d/wsgi.conf配置文件中配置保持一致。
如果您这里新建的文件名不是django.wsgi而是test.wsgi,那么/etc/httpd/conf.d/wsgi.conf中的配置就应该修改为

WSGIScriptAlias / "/var/www/html/server/test.wsgi"

4. 修改django项目中的setting.py文件
找到项目目录下的setting.py,对于这里就是/var/www/html/server/setting.py。找到其中的TEMPLATE_DIRS,修改为:

TEMPLATE_DIRS = ("/var/www/html/server/template",)

注意: 模板目录在这里一定要用绝对路劲,而不能用相对路径,当然也有方法动态设置模板路劲

PS:关于mod_wsgi
目前mod_wsgi有两种工作模式:

第一种是嵌入模式,类似于mod_python,直接在apache进程中运行,这样的好处是不需要另外增加进程,但是坏处也很明显,所有内存都和apache共享,如果和mod_python一样造成内存漏洞的话,就会危害整个apache。而且如果apache是用worker mpm,mod_wsgi也就强制进入了线程模式,这样子对于非线程安全的程序来说就没法用了。

这种模式下需要在apache的vhost中如下设置:

<span style="font-family: 'times new roman', times;">WSGIScriptAlias /path /path-to-wsgi</span>

即可生效,对于小型脚本的话,直接用这种模式即可。

第二种是后台模式,类似于FastCGI的后台,mod_wsgi会借apache的外壳,另外启动一个或多个进程,然后通过socket通信和apache的进程联系。

这种方式只要使用以下配置即可:

#启动WSGI后台,site1是后台名字


WSGIDaemonProcess site1 processes=1 threads=15 display-name=%{GROUP}

#分配当前上下文应该使用哪个WSGI后台,可以放在Location里面指定
WSGIProcessGroup site1

#根据当前上下文的ProcessGroup分配到对应的后台
WSGIScriptAlias /path /path-to-wsgi

在这种模式下,我们可以通过调节processes和threads的值来设置三种MPM的模式:prefork', 'worker', 'winnt'。

winnt模式

WSGIDaemonProcess example threads=25
wsgi.multithread True
wsgi.multiprocess False

此时processes=1,但是multiprocess为false

如果显式地指出processes为1那么:

WSGIDaemonProcess example processes=1 threads=25
wsgi.multithread True
wsgi.multiprocess True

worker模式

WSGIDaemonProcess example processes=2 threads=25

wsgi.multithread True
wsgi.multiprocess True

preforker模式

WSGIDaemonProcess example processes=5 threads=1
wsgi.multithread False
wsgi.multiprocess True

 

后台模式由于是与apache进程分离了,内存独立,而且可以独立重启,不会影响apache的进程,如果你有多个项目(django),可以选择建立多个后台或者共同使用一个后台。

比如在同一个VirtualHost里面,不同的path对应不同的django项目,可以同时使用一个Daemon:

<span style="font-family: 'times new roman', times;">WSGIDaemonProcess default processes=1 threads=1 display-name=%{GROUP}
 
WSGIProcessGroup default
 
WSGIScriptAlias /project1 “/home/website/project1.wsgi”
 
WSGIScriptAlias /project2 “/home/website/project2.wsgi”</span>

这样子两个django都使用同一个WSGI后台。

也可以把不同的项目分开,分开使用不同的后台,这样开销比较大,但就不会耦合在一起了。

display-name是后台进程的名字,这样方便重启对应的进程,而不需要全部杀掉。

<span style="font-family: 'times new roman', times;">WSGIDaemonProcess site1 processes=1 threads=1 display-name=%{GROUP}
 
WSGIDaemonProcess site2 processes=1 threads=1 display-name=%{GROUP}
 
<Location “/project1″>
WSGIProcessGroup site1
</Location>
WSGIScriptAlias /project1 “/home/website/project1.wsgi”
 
<Location “/project1″>
WSGIProcessGroup site2
</Location>
WSGIScriptAlias /project2 “/home/website/project2.wsgi”</span>

 
对于django 1.0以下的版本,由于官方认定不是线程安全的,所以建议使用多进程单线程模式

processes=n threads=1

对于django 1.0以后,就可以放心的使用多进程多线程模式:

processes=2 threads=64

这样子性能会更好。

Python 相关文章推荐
Python操作Mysql实例代码教程在线版(查询手册)
Feb 18 Python
Python自定义函数的创建、调用和函数的参数详解
Mar 11 Python
Python第三方库xlrd/xlwt的安装与读写Excel表格
Jan 21 Python
Python基于回溯法子集树模板解决最佳作业调度问题示例
Sep 08 Python
python队列queue模块详解
Apr 27 Python
Python中的self用法详解
Aug 06 Python
python 爬取学信网登录页面的例子
Aug 13 Python
解决Tensorflow2.0 tf.keras.Model.load_weights() 报错处理问题
Jun 12 Python
深入浅析Python代码规范性检测
Jul 31 Python
详解Pycharm安装及Django安装配置指南
Sep 15 Python
Python 使用dict实现switch的操作
Apr 07 Python
Python字符串常规操作小结
Apr 03 Python
在Linux系统上部署Apache+Python+Django+MySQL环境
Dec 24 #Python
在Mac OS上使用mod_wsgi连接Python与Apache服务器
Dec 24 #Python
在Mac OS上搭建Python的开发环境
Dec 24 #Python
详解Python字符串对象的实现
Dec 24 #Python
浅谈Python单向链表的实现
Dec 24 #Python
Python使用面向对象方式创建线程实现12306售票系统
Dec 24 #Python
安装ElasticSearch搜索工具并配置Python驱动的方法
Dec 22 #Python
You might like
Breeze 文章管理系统 v1.0.0正式发布
2006/12/14 PHP
php实现把数组按指定的个数分隔
2014/02/17 PHP
php 生成Tab键或逗号分隔的CSV
2016/09/24 PHP
php简单计算年龄的方法(周岁与虚岁)
2016/12/06 PHP
php PDO属性设置与操作方法分析
2018/12/27 PHP
javascript实现划词标记+划词搜索功能
2007/03/06 Javascript
实现连缀调用的map方法(prototype)
2009/08/05 Javascript
邮箱下拉自动填充选择示例代码附图
2014/04/03 Javascript
node.js微信公众平台开发教程
2016/03/04 Javascript
jQuery倒计时代码(超简单)
2017/02/27 Javascript
详解微信小程序调起键盘性能优化
2018/07/24 Javascript
javascript实现弹幕墙效果
2019/11/28 Javascript
Vue 封装防刷新考试倒计时组件的实现
2020/06/05 Javascript
[00:35]TI7不朽珍藏III——寒冰飞龙不朽展示
2017/07/15 DOTA
python获取标准北京时间的方法
2015/03/24 Python
Python排序搜索基本算法之冒泡排序实例分析
2017/12/09 Python
浅析python实现scrapy定时执行爬虫
2018/03/04 Python
利用python修改json文件的value方法
2018/12/31 Python
PyQt5 QTable插入图片并动态更新的实例
2019/06/18 Python
完美解决python针对hdfs上传和下载的问题
2020/06/05 Python
Python rabbitMQ如何实现生产消费者模式
2020/08/24 Python
使用html5新特性轻松监听任何App自带返回键的示例
2018/03/13 HTML / CSS
原生canvas制作画图小工具的踩坑和爬坑
2020/06/09 HTML / CSS
购买澳大利亚最好的服装和内衣在线:BONDS
2016/10/14 全球购物
描述一下JVM加载class文件的原理机制
2013/12/08 面试题
机电专业体育教师求职信
2013/09/21 职场文书
师范应届毕业生自荐信
2013/11/18 职场文书
医院护士专业个人的求职信
2013/12/09 职场文书
网球场地租赁协议范本
2014/10/07 职场文书
2014年新教师工作总结
2014/11/08 职场文书
商业门面租房协议书
2014/11/25 职场文书
初三英语教学反思
2016/02/15 职场文书
入党心得体会
2019/06/20 职场文书
MySQL 使用自定义变量进行查询优化
2021/05/14 MySQL
JavaScript事件的委托(代理)的用法示例详解
2022/02/18 Javascript
动作冒险《Hell Is Us》将采用虚幻5 消灭怪物探索王国
2022/04/13 其他游戏