每个框架或者应用都是为了解决某些问题才出现旦生的,没有一个事物是可以解决所有问题的。如果觉得某个框架或者应用使用很不方便,那么很有可能就是你没有将其使用到正确的地方,没有按开发者的设计初衷来使用它,当你将一个框架的优势使用到极致时一定是非常舒服和顺手的一件事。但同时也有可能衍生另一个问题,这个框架只解决了你的问题一,没有解决问题二、三等等,因此,就出现了多个框架/应用相结合的情况。比如Django + uWSGI + nginx。
本人初学python,找了一些实例进行了一些操作,以下纯属目前的理解,如有偏差,欢迎修正。
一、关于Django、uwsgi、nginx这三者关系的理解。
Django是一个WEB框架。所谓WEB框架,那么一定是搭建了一些模型,在安装完框架后,可以很方便的调用框架的方法,实现web功能。Django的特点在于MVC,模型--视图--控制。关于MVC不同的框架有不同的定义,不用纠结去统一MVC的定义,只需要理解各个框架自身的设计的特点的优势。关于Django框架,M模型:指的的数据库模型的管理(对于Django更多的在数据库相关的应用程序开发上有一点的优势);V视图:指的是如何根据业务需求来显示M中的哪些数据,更多是与业务相关;C控制:指的是用户访问的浏览器的地址与视图的映射关系。由于C比较简单已经由Django封装好了,基本上只用按正则表达示写一些类似配置文件的东西即可。而人们说到MVC时一般会有一个表示层,即业务数据在页面如果显示,以表格还是其它方式,表格的样式如何等等,该层在Django中也可被称为T模板,被合并到V中。所以使用Django,我们一般关心的是MTV的管理。
既然Django其重点在于MVC的模架管理,虽然也可以使用Django完成WEB服务器的功能(执行命令python manage.py runserver),但是仅仅是在测试环境中使用,对于要求稳定性和性能的生产环境,它无法达到。因此需要加入uWSGI。wsgi是一种协议,仅仅是协议并未实现,而uwsgi也是一种协议,两者有所不同。而uWSGI就是使用python将wsgi与uwsgi进行实现的WEB服务器,Django + uWSGI其WEB服务器的功能要更优于Django本身自带的web服务器。
那么有了uWSGI为什么还需要nginx?因为nginx具备优秀的静态内容处理能力,然后将动态内容转发给uWSGI服务器,这样可以达到很好的客户端响应。
二、环境搭建。
1、安装Django。
关于Django的使用网上资料很多,本人选择了两个比较合适的资料进行了实战操作,觉得不错。可参见”Django搭建及源码分析(一)“,提到了搭建方法和,参考资料。下面进入本节主题。
本人的系统环境centos6.0、python2.6、Django1.6,虽然都比较老了,但是不影响了解事物的本质的特点。继续...
2、安装uWSGI。
Django环境的搭建与配置请参见"Django搭建及源码分析(一)“,在保证Django可以访问之后,加入uWSGI。
使用pip install uwsgi
我安装的是uwsgi 2.0.1版本。
3、验证uWSGI是否安装成功。
新建test.py文件,内容如下:
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return "Hello World"
执行uwsgi --http :8000 --wsgi-file test.py
在浏览器内输入:http://ip:8001,查看是否有"Hello World"输出,若没有输出,请检查你的安装过程。
4、验证Django+uWSGI是否连接成功。
uwsgi --http :8000 --wsgi-file /home/MyDjProj/MyDjProj/wsgi.py
将test.py修改为Django项目中生成的wsgi.py,通过浏览器访问Django框架中的页面,成功。则说明两者连接正常。
5、安装nginx。
下载自已喜欢的nginx版本,我下的是当前最新稳定版nginx-1.8.0.tar.gz。
./configure --prefix=/usr/local/nginx-1.8 \ --with-http_stub_status_module \ --with-http_gzip_static_module
make && make install
6、配置uwsgi
uwsgi支持ini、xml等多种配置方式,本文以 ini 为例在/etc下创建uwsgi8000.ini
[uwsgi]
socket = 127.0.0.1:8000
master = true //主进程
vhost = true //多站模式
no-stie = true //多站模式时不设置入口模块和文件
workers = 2 //子进程数
reload-mercy = 10
vacuum = true //退出、重启时清理文件
max-requests = 1000
limit-as = 512
buffer-size = 30000
pidfile = /var/run/uwsgi8000.pid //pid文件,用于下面的脚本启动、停止该进程
daemonize = /var/log/uwsgi8000.log //日志文件
pythonpath = /usr/lib/python2.6/site-packages //同环境变量PYTHONPATH
7、配置nginx
找到nginx的安装目录(如:/usr/local/nginx-1.8/),打开conf/nginx.conf文件,修改server配置:
server {
listen 80;
server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location /{
include uwsgi_params;
uwsgi_pass 127.0.0.1:8000; //必须和uwsgi中的设置一致
uwsgi_param UWSGI_SCRIPT MyDjProj.wsgi; //入口文件,即wsgi.py相对于Django项目根目录的位置,“.”相当于一层目
uwsgi_param UWSGI_CHDIR /home/MyDjProj; //Django项目根目录
index index.html index.htm;
client_max_body_size 35m;
}
8、测试Django + uwsgi + nginx
uwsgi --ini /etc/uwsgi8000.ini & /usr/local/nginx-1.8/sbin/nginx
在浏览器输入:http://ip/,你就可以看到django的"It work"了。http://ip/hello,可以打开Django项目中,通过urlconf配置的hello子页面的view视图
三、遇到的问题。
1、在连接Django与uwsgi时(uwsgi --http :8000 --wsgi-file /home/MyDjProj/MyDjProj/wsgi.py),报出“ImportError: Could not import settings 'MyDjProj.settings' (Is it on sys.path? Is there an import error in the settings file?): No module named MyDjProj.settings”
可以看出执行/home/MyDjProj/MyDjProj/wsgi.py时,在sys.path中无法找到MyDjProj.settings,需要所/home/MyDjProj加入到sys.path中即可,加入方法有很多,在此我使用的是export PYTHONPATH=$PYTHONPATH:/home/MyDjProj,加入后,再访问即可。
在连接Django、uwsgi和nginx时,sys.path不受环境变量PYTHONPATH的影响,也会自动将nginx配置中的项目根目录加入到sys.path中,因此在后续步骤中此问题不影响三者连接。
2、在连接Django、uwsgi和nginx时,报出File "./MyDjProj/wsgi.py", line 17, in <module> from django.core.wsgi import get_wsgi_application ImportError: No module named django.core.wsgi
可以看出在执行/home/MyDjProj/MyDjProj/wsgi.py时,在sys.path中无法找到 django.core.wsgi,通过在MyDjProj/wsgi中加入sys.path的打印看出,sys.path中缺少/usr/lib/python2.6/site-packages,原因暂不清楚。
通过在uwsgi8000.ini中加入“pythonpath = /usr/lib/python2.6/site-packages”,重新连接成功。
3、遇到其它问题时,先判断端口是否正常打开,使用netstat -plnt查看。
4、修改后配置后,最好关闭uwsgi及nginx后,重新连接。关闭方法:fuser -k 端口/tcp。如:fuser -k 80/tcp; fuser -k 8000/tcp
5、多查看日志文件,文件中详细的报错信息,对于nginx的日志,可以通过在nginx.conf中配置error_log /var/log/nginx_error.log info;将出错信息打印到该文件中便于定位。