使用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 相关文章推荐
python3使用tkinter实现ui界面简单实例
Jan 10 Python
python使用在线API查询IP对应的地理位置信息实例
Jun 01 Python
Python守护进程(daemon)代码实例
Mar 06 Python
Python字符串详细介绍
May 09 Python
Python实现字符串反转的常用方法分析【4种方法】
Sep 30 Python
Python理解递归的方法总结
Jan 28 Python
如何爬取通过ajax加载数据的网站
Aug 15 Python
Python命令行参数解析工具 docopt 安装和应用过程详解
Sep 26 Python
Python之Django自动实现html代码(下拉框,数据选择)
Mar 13 Python
浅谈keras中的后端backend及其相关函数(K.prod,K.cast)
Jun 29 Python
高考考python编程是真的吗
Jul 20 Python
Python+MySQL随机试卷及答案生成程序的示例代码
Feb 01 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
php实现html标签闭合检测与修复方法
2015/07/09 PHP
PHP实现文件上传功能实例代码
2017/05/18 PHP
PHP CodeIgniter分页实例及多条件查询解决方案(推荐)
2017/05/20 PHP
PHP设计模式概论【概念、分类、原则等】
2020/05/01 PHP
js prototype 格式化数字 By shawl.qiu
2007/04/02 Javascript
YUI 读码日记之 YAHOO.lang.is*
2008/03/22 Javascript
JavaScript 学习初步 入门教程
2010/03/25 Javascript
js Event对象的5种坐标
2011/09/12 Javascript
js获取select选中的option的text示例代码
2013/12/19 Javascript
jQuery实现ichat在线客服插件
2014/12/29 Javascript
基于JS模仿windows文件按名称排序效果
2016/06/29 Javascript
详解Javascript数据类型的转换规则
2016/12/12 Javascript
使用BootStrap实现表格隔行变色及hover变色并在需要时出现滚动条
2017/01/04 Javascript
Javasript设计模式之链式调用详解
2018/04/26 Javascript
webpack4之SplitChunksPlugin使用指南
2018/06/12 Javascript
Vue父子组件双向绑定传值的实现方法
2018/07/31 Javascript
jQuery操作attr、prop、val()/text()/html()、class属性
2019/05/23 jQuery
vue+elementUI 复杂表单的验证、数据提交方案问题
2019/06/24 Javascript
Vue组件间的通信pubsub-js实现步骤解析
2020/03/11 Javascript
vue+iview框架实现左侧动态菜单功能的示例代码
2020/07/23 Javascript
Python 流程控制实例代码
2009/09/25 Python
Python3.5局部变量与全局变量作用域实例分析
2019/04/30 Python
python创建属于自己的单词词库 便于背单词
2019/07/30 Python
python提取照片坐标信息的实例代码
2019/08/14 Python
基于python实现雪花算法过程详解
2019/11/16 Python
详解python爬取弹幕与数据分析
2020/11/14 Python
HTML5之SVG 2D入门11—用户交互性(动画)介绍及应用
2013/01/30 HTML / CSS
Tostadora意大利:定制T恤
2019/04/08 全球购物
英国时尚首饰品牌:Missoma
2020/06/29 全球购物
保证书范文大全
2014/04/28 职场文书
人事主管岗位职责说明书
2014/07/30 职场文书
金融专业银行实习证明模板
2014/11/28 职场文书
2014年底工作总结
2014/12/15 职场文书
支教个人总结
2015/03/04 职场文书
详解如何用Python实现感知器算法
2021/06/18 Python
【海涛解说】pis亲自推荐,其实你从来不会玩NW
2022/04/01 DOTA