django简单部署
Django是python web框架中,最popular的一个,关于model/view/controller/模版等,各种教程非常多,现用现查即可,推荐:http://www.ziqiangxuetang.com/django/django-tutorial.html
django最麻烦的地方,反而是部署,下面详细聊聊。
1.协议:wsgi
wsgi相当于是python定制版的cgi,通用于所有的python web框架。wsgi/cgi的存在意义在于,确立了一套服务端脚本模式的标准,让服务器支持动态页面。之所以称之为协议,是因为其中只定义了接口标准,而没有规定实现方法,你可以基于任何语言/平台去实现它。
2.web容器
用户访问网站的行为,实际上是从服务器取得一个html文本,然后在本地浏览器进行解析。这些文本文件,就存放在服务端的web容器中,等待被用户请求。然而现代的网站,体量都很大,数据量巨大,且应用场景也多,安全性隐患也多,因此不可能全都使用静态文件来存储。现在仍然活着的web容器,都是支持cgi族协议的,也就是可以通过server脚本,实现网页动态化。
比较流行的web容器,有:apache,nginx,IIS等。虽然都是通用web容器,但是设计之初的区别,导致各自的应用场景不同。对wsgi最友好的是nginx,所以django最简便的部署方式就是做nginx映射。
3.gunicorn+nginx+django快捷部署
以下为具体操作:
1)环境准备:安装django,nginx,gunicore
sudo brew install nginx(sudo apt-get install nginx)
sudo pip install django
sudo pip install gunicorn
2)配置nginx
在/etc/nginx/sites-available/目录下创建 配置文件(文件名不限)
mac下是:/usr/local/etc/nginx/nginx.conf
server {
listen 9600;监听的服务器端口号,小于1024的端口号,需要sudo权限。由于做了gunicore映射,这里随便用个port就可以,用户实际访问时,请求的是gunicore绑定的端口。
server_name localhost;
server_name 127.0.0.1;此处应该改为公网 IP地址
access_log /opt/logs/nginx/wasp_ticket_stat.log;
error_log /opt/logs/nginx/wasp_ticket_stat_error.log;
location / {
proxy_pass http://127.0.0.1:8000;此处填写转发到的gunicorn绑定的服务器端口
proxy_set_header Host $host;
proxy_set_header X-Real-IP $http_x_real_ip;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}配置结束
保存后,启动nginx:sudo nginx
3)配置gunicorn
cd到django工程目录,gunicore project.wsgi –bind 0.0.0.0:8000 –deamon或者nohup gunicore project.wsgi –bind 0.0.0.0:8000
这么做是要保证,从部署服务器logout之后,gunicorn进程仍然活动。
gunicore第一个输入,就是要找到你project的wsgi,“.”表示目录级,可以挨个文件夹去找着自带的wsgi.py在哪里,默认在project内的project同名文件夹里。
如果成功了,则可以通过server公网ip:8000来访问网站。如果绑定80端口,则可以直接使用ip来访问。注意绑定小于1024的端口号时,需要sudo权限。
4.静态文件处理
如上的部署方式,做了两次web容器映射,最容易出bug的就是路径。web的开发环境肯定跟生产环境是隔离的,使用绝对路径非常蠢,运维很容易出错。且django对绝对路径进行了重定向,使用的绝对路径和系统路径并不完全一致。
相对路径由于多次映射的原因,很容易找不到/找错了,反复试验后,觉得如下配置比较轻便:
settings.py:末尾加上
STATIC_URL = '/static/'
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static').replace('\\', '/'),)
urls.py末尾加上
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.contrib import staticfiles
urlpatterns += staticfiles_urlpatterns()
在项目根目录建立static/文件夹,各处用/static/images/test.jpg访问文件即可。
ps:从django脚本访问文件,与从模版访问是不同的。脚本访问文件的根目录是就是django项目的根目录,在views.py打印一下执行目录,一目了然:
for item in os.walk('.'):
print item
5.跨域访问
在有些linux上,由于安全策略的关系,需要指定可用的安全ip。在settings.py里面,KNOWN_HOSTS这个list里面加上server ip
5.django for QA进阶
在测试/质量保证过程中,常常会用到基于web的任务托盘,来支撑持续集成之类的工作。当具体需求需要对大路货jekins进行深度定制时,可以考虑改用django来做任务托盘,可扩展性要强得多,对python也更友好。
1.并发
manage.py是for debug的,性能不适合用于生产环境,因此一般基于其他容器来部署。这里举gunicorn为例,根据具体业务来决定子进程个数。然后gunicorn -w 12代表建立一个12个子进程的进程池。
现代web容器都是自带排队的,建立子进程池是for 长效任务需要较长时间独占进程的情况。
2.长效任务
在任务托盘的深度定制中,很可能某个任务是要长时间运行后输出结果的。在托盘模型中,对任务的管理需要是反馈式的,且各个任务的代码完全异构,并不方便跟一般的PC脚本一样做多进程交互。
因此service上可以直接不做多进程/线程,直接在一个viess.py的接口响应里,调用一个长效任务,多个任务多次请求即可。
但是这样做会触碰到gunicorn的timeout瓶颈,导致任务中断。这时需要借助eventlet插件,来协助处理子进程阻塞的情况。
安装eventlet:sudo easy_install eventlet
部署时加参数-k ‘eventlet’
3.时间
django有个非常微弱的小坑,就是有独立的时区,并不和server时区进行同步。所以需要在setting里面手工设置一下:
TIME_ZONE = ‘Asia/Shanghai’