使用Nginx+uWsgi实现Python的Django框架站点动静分离


Posted in Python onMarch 21, 2016

由于:

Django处理静态文件不太友好;
以后有可能需要处理php或者其他资源的请求;

所以考虑结合nginx,使用nignx做它擅长的路由分发功能;同时做动静分离,即Http请求统一由Nginx进行分发,静态文件由Nginx处理,并返回给客户端;而动态的请求,则分发到uWsgi,由uWsgi再分发给Django进行处理。即客户端 <-> nginx <-> socket <-> uwsgi <-> Django

一、环境

系统:centOS 6

  • python: 2.7(注意:Django要在2.7版本或以上的python来 )
  • nginx
  • uswgi

所以,安装前,先在控制台输入python —version查看当前python的默认版本,如果在2.7以下,则修改默认版本。(详见附录)

二、安装nginx、uWsgi

安装

nginxsudo yum install nginx

安装

pipsudo yum install python-pip

安装

uWsgisudo pip uwsgi

三、测试nginx、uWsgi
1. 测试nginx启动测试nginx,看是否安装成功启动 sudo service nginx start然后在浏览器中,输入ip地址,看是否出现nginx的欢迎页面,出现则说明安装成功
2. 测试uWsgi在服务器上做任意目录下(一般在home下的某一目录),新建test.py,如下:

# test.pydef 
application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return "Hello World"

启动以Http方式访问的uWsgi,在test.py同一目录下,输入如下命令行(8001是监听的端口,可以改成你想要的端口)

uwsgi --http :8001 --wsgi-file test.py

然后在浏览器中,输入ip地址:8001,看是否响应hello world,是则说明安装成功
P.S. 由于开始时,uwsgi的安装使用了错误的python版本,所以在我的服务器上,uwsgi正确地可执行命令暂时是:/usr/src/download/uwsgi-2.0.10/uwsgi即完整的命令行是(本文所有的uwsgi命令同此):/usr/src/download/uwsgi-2.0.10/uwsgi --http :8001 --wsgi-file test.py
--http :8001 --wsgi-file test.py至此,uwsgi和nginx安装成功。接下来把nginx、uwsgi、django关联起来。在它们的协作之下,达到我们想要的目标。

四、连接Django和uWsgi
如上uWsgi的测试那样,uWsgi监听8001端口,并把请求分发给test.py,python会执行这个文件,如果我们把test.py分给Django的入口文件,那么就实现了Django和uWsgi的连接。所以,要做的事情有两步:

在项目目录下创建wsgi.py文件
启动uWsgi,使用它的wsgi-file指向wsgi.py

wsgi.py内容如下:

"""
WSGI config for WHPAIWechat project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
"""

import osfrom django.core.wsgi import 
get_wsgi_applicationos.environ.setdefault("DJANGO_SETTINGS_MODULE", "WHPAIWechat.settings")
application = get_wsgi_application()

启动以Http方式访问uWsgiuwsgi --http :8000 --chdir /home/jiayandev/WHPAIWechat/ --wsgi-file WHPAIWechat/wsgi.py
浏览器访问 ip地址:8000,加上必要的路由,即可访问之前写好的python程序:例如[http://112.74.73.31:8000/wechat/call]
P.S. 你是否关注到,启动uwsgi即可,而无需再启动Django了?

五、连接uWsgi和nginx
接下来,打通 uWsgi和 nginx之间的连接,它们是通过socket来连接的。第四节所讲的链接 swgi和Django,我们用浏览器访问是能得到正确的响应的,说明连接成功。那么只要在nginx上,实现某些规则下,把前端的请求转发到此端口即可。要做的事情非常简单,即配置nginx的配置文件即可,一般在 /etc/nginx/conf.d/default.conf中。这里,我只设置几条简单的规则

url包含.css、.js等服务器特定目录,设置根目录
以上都不匹配的的访问分发到uwsgi上的, nginx转发给uswgi处理

更多规则可以视业务情况而定,完整的配置如下:

upstream django {
  server 127.0.0.1:8000; # 注意8000是上述uwsgi监听的端口
}
server {
  listen    80 default_server;
  server_name _;

  #charset koi8-r;

  #access_log logs/host.access.log main;

  # Load configuration files for the default server block.
  include /etc/nginx/default.d/*.conf;

  location = /404.html {
    root  /usr/share/nginx/html;
  }

  # redirect server error pages to the static page /50x.html
  #
  error_page  500 502 503 504 /50x.html;
  location = /50x.html {
    root  /usr/share/nginx/html;
  }

  location ~ \.html$ {
        root /usr/share/nginx/html/front;
        index index.html index.htm;
  }

   location ~ \.(png|jpg|jpeg|css|img|js|flv|swf|download|eot|svg|ttf|woff|woff2|otf)$ {
        root /usr/share/nginx/html/front;
  }


  # 以上都不匹配的的访问分发到uwsgi上
  location / {
    include    /etc/nginx/uwsgi_params; #详细看下文
    uwsgi_pass   django;
  }

  * # PHP分到 9000端口**
  #
  #location ~ \.php$ {
  #  root      html;
  #  fastcgi_pass  127.0.0.1:9000;
  #  fastcgi_index index.php;
  #  fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
  #  include    fastcgi_params;
  #}*
}

同时,uswgi_param内容如下,照抄即可

uwsgi_param QUERY_STRING    $query_string;
uwsgi_param REQUEST_METHOD   $request_method;
uwsgi_param CONTENT_TYPE    $content_type;
uwsgi_param CONTENT_LENGTH   $content_length;

uwsgi_param REQUEST_URI    $request_uri;
uwsgi_param PATH_INFO     $document_uri;
uwsgi_param DOCUMENT_ROOT   $document_root;
uwsgi_param SERVER_PROTOCOL  $server_protocol;

uwsgi_param REMOTE_ADDR    $remote_addr;
uwsgi_param REMOTE_PORT    $remote_port;
uwsgi_param SERVER_PORT    $server_port;
uwsgi_param SERVER_NAME    $server_name;

配置完成后,重启或者reload nginx配置即可生效
重启:

sudo service nginx restart

reload:

sudo service nginx reload

然后直接访问,看看有什么不一样:
http://youIP/front/index.html
http://youIP/statics/index.html
http://youIP/(加上路由信息),例如 http://112.74.73.31/wechat/call
我们这里主要先关注访问django,如果http://112.74.73.31/wechat/call返回的信息跟第四节的一样,说明nginx和uwsgi也连接起来了,至此,nginx、uwsgi、django顺利连接完成。

六、优化uwsgi的启动
第三节、第四节介绍的启动uwsgi服务时,我们都是使用命令行的方式启动和设置参数的,这样不好记,有可能会忘记参数 等等。这里介绍另一种设置参数的方式,即用配置文件记录uwsgi的参数,启动时,从配置文件里加载参数。参数如下

#WHPAIWechat_uwsgi.ini[uwsgi]
socket = 127.0.0.1:8000
chdir = /home/jiayandev/WHPAIWechat/
wsgi-file = WHPAIWechat/wsgi.py
processes = 4
threads = 2
master=True #设置此参数,有一个主进程
pidfile= pidfile/project-master.pid #主进程id写入文件里
vacuum=True #退出时,清理环境
daemonize = uwsgi.log #守护进程的方式运行,log日志存在此log文件里

启动uwsgi命令变成uwsgi WHPAIWechat_uwsgi.ini

Python 相关文章推荐
Python 3.x读写csv文件中数字的方法示例
Aug 29 Python
windows环境下tensorflow安装过程详解
Mar 30 Python
使用DataFrame删除行和列的实例讲解
Apr 08 Python
Python网络编程使用select实现socket全双工异步通信功能示例
Apr 09 Python
Python+Pandas 获取数据库并加入DataFrame的实例
Jul 25 Python
[原创]Python入门教程1. 基本运算【四则运算、变量、math模块等】
Oct 28 Python
python 实现UTC时间加减的方法
Dec 31 Python
Python Opencv实现图像轮廓识别功能
Mar 23 Python
python中sort和sorted排序的实例方法
Aug 26 Python
基于Python制作一副扑克牌过程详解
Oct 19 Python
pytorch中的model=model.to(device)使用说明
May 24 Python
Python爬虫实战之爬取京东商品数据并实实现数据可视化
Jun 07 Python
Python中的条件判断语句与循环语句用法小结
Mar 21 #Python
举例讲解Python中的迭代器、生成器与列表解析用法
Mar 20 #Python
深入解析Python中函数的参数与作用域
Mar 20 #Python
总结Python编程中函数的使用要点
Mar 20 #Python
两个命令把 Vim 打造成 Python IDE的方法
Mar 20 #Python
Python中列表、字典、元组数据结构的简单学习笔记
Mar 20 #Python
Python的Socket编程过程中实现UDP端口复用的实例分享
Mar 19 #Python
You might like
WordPress特定文章对搜索引擎隐藏或只允许搜索引擎查看
2015/12/31 PHP
Zend Framework基本页面布局分析
2016/03/19 PHP
PHP 访问数据库配置通用方法(json)
2018/05/20 PHP
JavaScript CSS修改学习第三章 修改样式表
2010/02/19 Javascript
jQuery实现id模糊查询的小例子
2013/03/19 Javascript
浅谈JavaScript之事件绑定
2013/07/08 Javascript
javascript框架设计读书笔记之模块加载系统
2014/12/02 Javascript
JS截取字符串实例详解
2015/11/24 Javascript
jQuery+jsp实现省市县三级联动效果(附源码)
2015/12/03 Javascript
JavaScript的设计模式经典之代理模式
2016/02/24 Javascript
jQuery循环遍历子节点并获取值的方法
2016/04/14 Javascript
nodejs根据ip数组在百度地图中进行定位
2017/03/06 NodeJs
JS中SetTimeout和SetInterval使用初探
2017/03/23 Javascript
Vue.js实现微信过渡动画左右切换效果
2017/06/13 Javascript
详解Vue 方法与事件处理器
2017/06/20 Javascript
JavaScript递归函数解“汉诺塔”算法代码解析
2018/07/05 Javascript
详解Angular6 热加载配置方案
2018/08/18 Javascript
vue 点击按钮增加一行的方法
2018/09/07 Javascript
在vue中获取微信支付code及code被占用问题的解决方法
2019/04/16 Javascript
微信小程序生成海报分享朋友圈的实现方法
2019/05/06 Javascript
详解vue 在移动端体验上的优化解决方案
2019/05/20 Javascript
React组件对子组件children进行加强的方法
2019/06/23 Javascript
解决微信授权成功后点击按返回键出现空白页和报错的问题
2020/06/08 Javascript
vue3.0自定义指令(drectives)知识点总结
2020/12/27 Vue.js
Python实现ssh批量登录并执行命令
2016/10/25 Python
对numpy中布尔型数组的处理方法详解
2018/04/17 Python
如何使用pycharm连接Databricks的步骤详解
2020/09/23 Python
Python3 用什么IDE开发工具比较好
2020/11/28 Python
澳大利亚玩具剧场:Toy Playhouse
2019/03/03 全球购物
为什么需要版本控制?
2013/08/08 面试题
营业员个人总结的自我评价
2013/10/25 职场文书
餐厅采购员岗位职责
2014/03/06 职场文书
教师纪念9.18事件演讲稿范文
2014/09/14 职场文书
大学生就业协议书范本(适用于公司企业)
2014/10/07 职场文书
仓库管理员岗位职责
2015/02/03 职场文书
因家庭原因离职的辞职信范文
2015/05/12 职场文书