精华内容
参与话题
问答
  • uWSGI 是什么?

    千次阅读 2018-07-12 15:24:01
    uWSGI是实现了了uwsgi和WSGI两种协议的Web服务器器Web应⽤用的本质就是:1. 浏览器器发送⼀一个HTTP请求;2. 服务器器收到请求,⽣生成⼀一个HTML⽂文档;3. 服务器器把HTML⽂文档作为HTTP响应的Body发送给浏览器...
    uWSGI是实现了了uwsgi和WSGI两种协议的Web服务器器
    Web应⽤用的本质就是:
    1.  浏览器器发送⼀一个HTTP请求;
    2.  服务器器收到请求,⽣生成⼀一个HTML⽂文档;
    3.  服务器器把HTML⽂文档作为HTTP响应的Body发送给浏览器器;
    4.  浏览器器收到HTTP响应,从HTTP Body取出HTML⽂文档并显示。
    所以,最简单的Web应⽤用就是先把HTML⽤用⽂文件保存好,⽤用⼀一个现成的HTTP服务器器软件,接收⽤用户请求,从⽂文件中读
    取HTML,返回。Apache、Nginx、Lighttpd等这些常⻅见的静态服务器器就是⼲干这件事情的。
    如果要动态⽣生成HTML,就需要把上述步骤⾃自⼰己来实现。不不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是
    苦⼒力力活,如果我们⾃自⼰己来写这些底层代码,还没开始写动态HTML呢,就得花个把⽉月去读HTTP规范。
    正确的做法是底层代码由专⻔门的服务器器软件实现,我们⽤用Python专注于⽣生成HTML⽂文档。因为我们不不希望接触到TCP
    连接、HTTP原始请求和响应格式,所以,需要⼀一个统⼀一的接⼝口,让我们专⼼心⽤用Python编写Web业务。
    这个接⼝口就是WSGI:Web Server Gateway Interface。
    ⽆无论多么复杂的Web应⽤用程序,⼊入⼝口都是⼀一个WSGI处理理函数。 application(environ, start_response), HTTP请
    求的所有输⼊入信息都可以通过environ获得,HTTP响应的输出都可以通过start_response()加上函数返回值作为Body。
    展开全文
  • uWSGI详解

    万次阅读 2016-05-09 17:49:49
    WSGI是什么? WSGI,全称 Web Server Gateway Interface,或者 Python Web Server Gateway Interface ,是为 Python 语言定义的 Web 服务器和 Web 应用程序或框架之间的一种简单而通用的接口。...

    WSGI是什么?

    WSGI,全称 Web Server Gateway Interface,或者 Python Web Server Gateway Interface ,是为 Python 语言定义的 Web 服务器和 Web 应用程序或框架之间的一种简单而通用的接口。自从 WSGI 被开发出来以后,许多其它语言中也出现了类似接口。

    WSGI 的官方定义是,the Python Web Server Gateway Interface。从名字就可以看出来,这东西是一个Gateway,也就是网关。网关的作用就是在协议之间进行转换。

    WSGI 是作为 Web 服务器与 Web 应用程序或应用框架之间的一种低级别的接口,以提升可移植 Web 应用开发的共同点。WSGI 是基于现存的 CGI 标准而设计的。

    很多框架都自带了 WSGI server ,比如 Flask,webpy,Django、CherryPy等等。当然性能都不好,自带的 web server 更多的是测试用途,发布时则使用生产环境的 WSGI server或者是联合 nginx 做 uwsgi 。

    也就是说,WSGI就像是一座桥梁,一边连着web服务器,另一边连着用户的应用。但是呢,这个桥的功能很弱,有时候还需要别的桥来帮忙才能进行处理。WSGI 的作用如图所示:


    WSGI的作用

    WSGI有两方:“服务器”或“网关”一方,以及“应用程序”或“应用框架”一方。服务方调用应用方,提供环境信息,以及一个回调函数(提供给应用程序用来将消息头传递给服务器方),并接收Web内容作为返回值。

    所谓的 WSGI中间件同时实现了API的两方,因此可以在WSGI服务和WSGI应用之间起调解作用:从WSGI服务器的角度来说,中间件扮演应用程序,而从应用程序的角度来说,中间件扮演服务器。“中间件”组件可以执行以下功能:

    • 重写环境变量后,根据目标URL,将请求消息路由到不同的应用对象。
    • 允许在一个进程中同时运行多个应用程序或应用框架。
    • 负载均衡和远程处理,通过在网络上转发请求和响应消息。
    • 进行内容后处理,例如应用XSLT样式表。

    WSGI 的设计确实参考了 Java 的 servlet。


    接下来,我们要介绍的是 uWSGI

    uWSGI

    uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换。

    要注意 WSGI / uwsgi / uWSGI 这三个概念的区分。

    • WSGI看过前面小节的同学很清楚了,是一种通信协议。
    • uwsgi同WSGI一样是一种通信协议。
    • 而uWSGI是实现了uwsgi和WSGI两种协议的Web服务器。

    uwsgi协议是一个uWSGI服务器自有的协议,它用于定义传输信息的类型(type of information),每一个uwsgi packet前4byte为传输信息类型描述,它与WSGI相比是两样东西。

    为什么有了uWSGI为什么还需要nginx?因为nginx具备优秀的静态内容处理能力,然后将动态内容转发给uWSGI服务器,这样可以达到很好的客户端响应。

    接下来,我们要看看 uWSGI 的安装配置与使用。

    安装

    uWSGI 的安装很简单:

    1 pip install uwsgi

    现在我们试下将 Django 跑起来。我们先在 virtualenv 创建一个 Django Project:

    1 [root@nowamagic ~]# cd nowamagic_venv
    2 [root@nowamagic nowamagic_venv]# source bin/activate
    3 (nowamagic_venv)[root@nowamagic nowamagic_venv]# django-admin.py startproject nowamagic_pj

    virtualenv 的路径与目录文件如下:


    Django Project 的路径与目录文件如下:


    测试uwsgi

    在你的服务器上写一个test.py:

    1 # test.py
    2 def application(env, start_response):
    3     start_response('200 OK', [('Content-Type','text/html')])
    4     return "Hello World"

    我的 test.py 的路径是 /root/nowamagic_venv/nowamagic_pj/test.py,执行以下命令:

    1 [root@nowamagic ~]# cd nowamagic_venv
    2 [root@nowamagic nowamagic_venv]# source bin/activate
    3 (nowamagic_venv)[root@nowamagic nowamagic_venv]# uwsgi --http :8001 --wsgi-file /root/nowamagic_venv/nowamagic_pj/test.py

    访问网页 http://115.28.0.89:8001/,OK,显示 Hello World,说明 uwsgi 安装成功。

    测试你的 Django 项目

    前面我们用 django-admin.py startproject nowamagic_pj 创建了一个项目,现在我们用 Django 自带的 Web 服务器看看我们的项目有没出问题。还是进入我们虚拟环境:

    1 [root@nowamagic ~]# cd nowamagic_venv
    2 [root@nowamagic nowamagic_venv]# source bin/activate
    3 (nowamagic_venv)[root@nowamagic nowamagic_venv]# python2.7 /root/nowamagic_venv/nowamagic_pj/manage.py runserver 0.0.0.0:8002

    执行这个命令报错:No module named django.core.management,原因应该是装了多个版本的Python导致的。命令指定文件路径就行,丑是丑些了:

    view source
    print?
    1 (nowamagic_venv)[root@nowamagic nowamagic_venv]# /usr/local/bin/python2.7 /root/nowamagic_venv/nowamagic_pj/manage.py runserver 0.0.0.0:8002

    OK,启动 Django 自带的服务器了,我们再访问 http://115.28.0.89:8002/,成功显示:


    说明 Djanggo 项目也没问题。

    连接Django和uwsgi

    最后一步了,我们要把uwsgi与Django连接起来。

    编写django_wsgi.py文件,将其放在与文件manage.py同一个目录下。我的放在 /root/nowamagic_venv/nowamagic_pj/ 下:

    view source
    print?
    01 #!/usr/bin/env python
    02 # coding: utf-8
    03  
    04 import os
    05 import sys
    06  
    07 # 将系统的编码设置为UTF8
    08 reload(sys)
    09 sys.setdefaultencoding('utf8')
    10  
    11 os.environ.setdefault("DJANGO_SETTINGS_MODULE","nowamagic_pj.settings")
    12  
    13 from django.core.handlers.wsgi import WSGIHandler
    14 application = WSGIHandler()
    注意不要直接 copy,有个地方要改:注意到语句os.environ.setdefault。比如我的项目为nowamagic_pj,则语句应该是 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "nowamagic_pj.settings")

    OK,进入虚拟环境执行指令:

    1 [root@nowamagic ~]# cd nowamagic_venv
    2 [root@nowamagic nowamagic_venv]# source bin/activate
    3 (nowamagic_venv)[root@nowamagic nowamagic_venv]# uwsgi --http :8000 --chdir /root/nowamagic_venv/nowamagic_pj/ --module django_wsgi

    成功显示 Django It Works 页面。

    这样,你就可以在浏览器中访问你的Django程序了。所有的请求都是经过uwsgi传递给Django程序的。

    这里我们介绍了如何把uwsgi与Django连接起来,在下一篇将继续介绍如何将uwsgi与Nginx连接。

    上一篇介绍了 uWSGI 来部署 Django 程序,但在在生产环境中单单只有 uWSGI 是不够的,Nginx是必不可少的工具。

    先安装 Nginx,可以参照前面的小节:使用RPM安装Nginx

    Nginx 配置

    在 nginx.conf 上加入/修改,我的 server 配置如下(一切从简……):

    01 server {
    02     listen       80;
    03     server_name  115.28.0.89;
    04     #server_name localhost;
    05  
    06     access_log /home/nowamagic/logs/access.log;
    07     error_log /home/nowamagic/logs/error.log;
    08  
    09     #root         /root/nowamagic_venv/nowamagic_pj;
    10     location / {
    11         uwsgi_pass 127.0.0.1:8077;
    12         #include uwsgi_params;
    13         include /etc/nginx/uwsgi_params;
    14         #uwsgi_pass 127.0.0.1:8077;
    15         #uwsgi_param UWSGI_SCRIPT index;
    16         #uwsgi_param UWSGI_PYHOME $document_root;
    17         #uwsgi_param UWSGI_CHDIR  $document_root;
    18    }
    19    access_log off;
    20 }

    注意保证配置里写的目录 /home/nowamagic/logs/ 和 /home/nowamagic/logs/ 存在,接下来就没啥问题了,Nginx 配置很简单。

    uWSGI 配置

    前面我们是直接使用命令行来启动 uWSGI,在实际部署环境中,我们常用的是配置文件的方式,而非命令行的方式。

    我的 Django 程序目录:/root/nowamagic_venv/nowamagic_pj/

    这里让 Nginx 采用 8077 端口与 uWSGI 通讯,请确保此端口没有被其它程序采用。

    uWSGI 支持多种配置文件格式,比如 xml,ini,json 等等都可以。

    1. xml 配置

    请确定你在上一节中的django_wsgi.py文件已经存在了。新建一个XML文件:nowamagic_pj.xml,将它放在 /root/nowamagic_venv/nowamagic_pj 目录下

    01 <uwsgi>
    02  <socket>127.0.0.1:8077</socket>
    03  <listen>80</listen>
    04  <master>true</master>
    05  <pythonpath>/root/nowamagic_venv/nowamagic_pj</pythonpath>
    06  <processes>1</processes>
    07  <logdate>true</logdate>
    08  <daemonize>/var/log/uwsgi.log</daemonize>
    09  <plugins>python</plugins>
    10 </uwsgi>

    然后执行命令:

    1 uwsgi -x /root/nowamagic_venv/nowamagic_pj/nowamagic_pj.xml
    2 or
    3 /usr/local/bin/uwsgi -x /root/nowamagic_venv/nowamagic_pj/nowamagic_pj.xml

    加载指定的xml配置文件。当使用命令行参数时,可以使用简化命令“-x”。当然也可以不简写:

    1 uwsgi --xml /etc/nowamagic.xml

    甚至如果在命令行的最后一个参数以“.xml”结尾,那么就隐含将加载该xml文件作为配置。

    1 uwsgi /etc/nowamagic.xml

    有时候因各种环境问题,-x --xml 命令识别不了,可以使用下面的 ini 配置方式:

    2. ini 配置

    01 [uwsgi]
    02 vhost = false
    03 plugins = python
    04 socket = 127.0.0.1:8077
    05 master = true
    06 enable-threads = true
    07 workers = 1
    08 wsgi-file = /root/nowamagic_venv/nowamagic_pj/nowamagic_pj/wsgi.py
    09 virtualenv = /root/nowamagic_venv
    10 chdir = /root/nowamagic_venv/nowamagic_pj

    然后执行命令:

    1 uwsgi --ini /root/nowamagic_venv/nowamagic_pj.ini&

    uwsgi 这样就启动起来了。如果无意外的话,就能在网上访问你的 Python 项目了。

    小插曲

    我在配置完 Nginx 和 uWSGI 之后,访问时显示 502 错误。查看 uWSGI 启动信息,发现这么一条:ImportError: No module named django.core.wsgi。

    然后推断,我的 CentOS 上的 Python 版本是 2.4.3,然后进入 virtualenv,执行:

    1 python
    2 <<< import django
    3 <<< from django.core.wsgi import get_wsgi_application
    4 <<<

    则没报错,因为我的虚拟环境里的 Python 版本是 2.7.5。推断成立,但是虚拟环境里的 Django 会默认调用外部环境的 Python。解决方法:在虚拟环境里 pip install django。

    OK,问题解决,一切正常。

    一些我在配置时用到的命令,省得你去搜索:

    1. 关闭 uWSGI:

    1 killall  -9 uwsgi
    2 killall -s HUP /var/www/uwsgi 
    3 killall -s HUP /usr/local/bin/uwsgi

    2. 列出端口占用情况:

    1 netstat -lpnt

    展开全文
  • Nginx+uWSGI+Django部署web服务器

    万次阅读 多人点赞 2018-08-28 14:33:08
    Nginx+uWSGI+Django部署web服务器 Nginx+uWSGI+Django部署web服务器 环境说明 前言 搭建项目 Django部署 编辑luffy/luffy/settings.py 编辑luffy/app01/views.py 编辑luffy/luffy/urls.py 运行并测试 uWSGI部署...

    Nginx+uWSGI+Django部署web服务器

    环境说明

    • 进行本文操作前需己搭建好的环境
      • linux系统,我用的是openSUSE
      • 使用了operation用户的家目录做为测试环境
      • python3.5.6
      • virtualenv 16.0
      • pip3 18.0
      • nginx 1.13.1
    • 后面进行安装的环境
      • django 1.11
      • uwsgi-2.0.17.1

    前言

    在多年前,基于python的web项目,常见的部署方法有:

    • fcgi:用spawn-fcgi或者框架自带的工具对各个project分别生成监听进程,然后和http服务互动。
    • wsgi:利用http服务的mod_wsgi模块来跑各个project。

    不过uwsgi出现后,大部份部署就不会使用以上的两个协议了。
    因为uwsgi它既不用wsgi协议也不用fcgi协议,而是自创了一个uwsgi的协议,据作者说该协议大约是fcgi协议的10倍那么快。uWSGI的主要特点如下:

    • 超快的性能。
    • 低内存占用(实测为apache2的mod_wsgi的一半左右)。
    • 多app管理。
    • 详尽的日志功能(可以用来分析app性能和瓶颈)。
    • 高度可定制(内存大小限制,服务一定次数后重启等)。

    所以在uwsgi协议的基础上,配合nginx来做python(类如django的框架)的web项目部署就很常见了。

    uwsgi 实际上也是一个 http 服务器,只不过它只面向 python 的网络应用程序。
    虽然 uwsgi 也是 http 服务器,但是却不便直接使用它部署 python web 应用程序。

    uwsgi 所扮演的的角色是后端 http 服务器,nginx 扮演的角色是前端 http 服务器,django项目 是客户所真正要访问到的提供数据方。 用户从网页浏览器中发出请求,nginx 服务器收到请求后,会通过它的 uwsgi 模块将用户的请求转发给 uwsgi 服务器,uwsgi 服务器通过django处理完毕后将结果返回给 nginx,浏览器将最终的结果展现给用户。

    搭建项目

    • 建立一个虚拟环境

      • 建议个人学习和测试的话,直接建在家用户目录下,以避免权限引起的各种拒绝问题
      • 或者正式点,系统再建一个dev用户,在专门的工作目录下给好dev用户的权限去运行。
      • 虚拟环境的目录名建议就带个env点明是虚拟环境,如果和后面的项目取相同的名字你会看到三重同名的串在一起,有点不太好认。
        virtualenv -p python3 py3env
    • 启动虚拟环境
      source py3env/bin/activate

    • 安装django1.11,之所以装这个版本是学习所需要,后面自己的项目最好与时俱进。
      pip install django==1.11

    • 直接使用django-admin命令创建一个django项目

      • 建议不要放在py3env目录下,而是在专门的工作目录下建立
        django-admin startproject luffy

    如下,己经初步搭建好简单的项目:

    cd luffy
    
    (py3env) operation@opensuse-wordpress:~/work/luffy> tree -L 2
    .
    ├── luffy
    │   ├── __init__.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    └── manage.py
    • 创建新应用,例如app01
      python3 manage.py startapp app01
      结构如下
    (py3env) operation@opensuse-wordpress:~/work/luffy> tree -L 2
    .
    ├── app01
    │   ├── admin.py
    │   ├── apps.py
    │   ├── __init__.py
    │   ├── migrations
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    ├── luffy
    │   ├── __init__.py
    │   ├── __pycache__
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    └── manage.py

    Django部署

    编辑luffy/luffy/settings.py

    # SECURITY WARNING: don't run with debug turned on in production!
    DEBUG = False
    
    ALLOWED_HOSTS = ['*', ]
    
    # Application definition
    
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'app01',
    ]

    如上,主要是:

    • 将DEBUG由True改成False(虽然只是在学习和测试搭建的,也要顾及好安全)
    • 在ALLOWED_HOSTS 默认的空列表中填入你自己打算使用的域名,我这里测试的时候填的是*,真正上线部署的时候不建议填成通配符的*,而是要填允许访问的主机域名。一般django用于做后端服务器,而前端会有一个域名。详情可见django官方文档。
    • INSTALLED_APPS 列表下增加appo1,表示将app01应用给安装注册上。
    • 补充,后面配置好nginx和新建好域名之后,我将ALLOWED_HOSTS = ['*', ]修改成ALLOWED_HOSTS = ['luffy.tielemao', ]了,通过域名访问仍然正常。而直接敲ip地址则会报400错误。

    编辑luffy/app01/views.py

    from django.shortcuts import render,HttpResponse
    
    # Create your views here.
    
    def index(request):
        return HttpResponse('Hello Hero')

    由于只是简单演示,所以上面只是让用户访问index页面后,得到一个显示Hello Hero的页面。

    编辑luffy/luffy/urls.py

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^index/', views.index),
    ]

    运行并测试

    首先是运行,由于是单独对django进行运行测试,所以只是在进入项目根目录后命令行敲以下命令:

    python manage.py runserver 0.0.0.0:8083
    其中0.0.0.0表示捆绑监听服务器上的所有网卡IP地址,当然也就包括了127.0.0.1和外网的公网ip了。

    最初我测试的是ALLOWED_HOSTS填的允许的HOSTS是自己的域名.tielemao.com,结果直接在浏览器上敲IP加8083端口接index当然是报错:

    Bad Request(400)而由于我将DEBUG值设为了False,所以也不会将调试信息暴露出来。

    然后我将.tielemao.com改为了通配符*(不安全,表示允许所有主机头)。
    再访问http://39.x.x.x:8083/index/的时候,就能正常访问到了:

    • 注意,我使用的是8083端口并且在防火墙和云控制平台上的安全组处己设置了开放该端口。

    django能运行无误后,ctrl+c将它停止,再接下来做下面的操作。

    uWSGI部署

    同样为了环境的隔离和纯净,这次我也选择在同样的虚拟环境下安装:
    pip3 install uwsgi
    安装完成后可uwsgi --version查看版本,
    uwsgi --python-version还可以间接查看到python的版本。

    • 编写一个用于简单测试uwsgi的python脚本
      vim test-uwsgi.py,内容如下:
    def application(env,start_response):
        start_response('200 OK',[('Content-Type','text/html')])
        return [b"Hello Hero, all for one "]

    测试运行uWSGI

    以下命令表示运行uwsgi服务,同样是在8083端口上开放web访问。
    * 注意--http 后是一个空格再接:端口号。
    uwsgi --http :8083 --wsgi-file test-uwsgi.py

    访问web服务器8083端口,正常显示test-uwsgi.py脚本中返回显示的文本。

    因为我们现在要做的是基于nginx和uwsgi部署django,从客户端发起请求到服务器响应请求,会经过一下几个环节:

    the web client <-> the web server(nginx) <-> the socket <-> uwsgi <-> Django

    而单独测试uWSGI运行,访问显示正常的话,说明下面3个环节是通畅的:

    the web client <-> uWSGI <-> Python

    ctrl+c中止程序,再来进行以下的测试。

    使用uWSGI运行django项目

    在虚拟环境下,进入到django根目录下后敲以下命令:

     uwsgi --http :8000 --module luffy.wsgi

    效果和直接敲以下命令

    python manage.py runserver 0.0.0.0:8000

    是一样的。

    • 注:--module luffy.wsgi为加载指定的wsgi模块,你项目起的是什么名字,一般就是项目名.wsgi

    这样测试下来,可证明web客户端通过uWSGI到Django是通畅的:

    the web client <-> uWSGI <-> Django

    ctrl+c中止程序,再来进行以下的测试

    uWSGi热加载Djangoa项目

    在启动命令后面加上参数:

    uwsgi --http :8083 --module luffy.wsgi --py-autoreload=1

    同样,这个时候访问服务器8083端口,也就是访问了django项目(luffy)。

    而且还多了一个参数:
    --py-autoreload 监控python模块以触发重载(仅在开发中使用)

    # 类似的发布命令
    /home/operation/work/py3env/bin/uwsgi --http 0.0.0.0 :8000 --chdir /home/operation/work/luffy --module luffy.wsgi
    # 此时修改django代码,uWSGI会自动加载django程序,页面生效
    # 除此外,还可以接上很多参数

    ctrl+c中止程序,再进行下面环节:

    部署nginx

    nginx配置uwsgi和django

    • uwsgi_params文件拷贝到项目文件夹下。
    • uwsgi_params文件一般在/etc/nginx/目录下,也可以从nginx的github页面下载。

    uwsgi_params配置文件如下:

    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  REQUEST_SCHEME     $scheme;
    uwsgi_param  HTTPS              $https if_not_empty;
    
    uwsgi_param  REMOTE_ADDR        $remote_addr;
    uwsgi_param  REMOTE_PORT        $remote_port;
    uwsgi_param  SERVER_PORT        $server_port;
    uwsgi_param  SERVER_NAME        $server_name;
    • 拷贝到项目下:
      sudo cp /etc/nginx/uwsgi_params /home/operation/work/luffy/

    • 属主属组等权限重新修改

    sudo chown operation:operation uwsgi_params
    sudo chmod 664 /home/operation/work/luffy/uwsgi_params
    • 在项目文件夹下创建文件luffy_nginx.conf,填入并修改下面内容:
    # luffy_nginx.conf
    
    # the upstream component nginx needs to connect to
    upstream django {
        # server unix:///path/to/your/mysite/mysite.sock; 
        # for a file socket
        server 127.0.0.1:8083; 
        # for a web port socket (we'll use this first)
    }
    
    # configuration of the server
    server {
        # the port your site will be served on
        listen      8000;
        # the domain name it will serve for
        server_name luffy.tielemao.com; 
        # substitute your machine's IP address or FQDN
        charset     utf-8;
    
        # max upload size
        client_max_body_size 75M;   # adjust to taste
    
        # Django media
        location /media  {
            alias /home/operation/work/luffy/media;  
            # your Django project's media files - amend as required
        }
    
        location /static {
            alias /home/operation/work/luffy/static; 
            # your Django project's static files - amend as required
        }
    
        # Finally, send all non-media requests to the Django server.
        location / {
            uwsgi_pass  django;
            include     /home/operation/work/luffy/uwsgi_params; 
            # the uwsgi_params file you installed
        }
    }
    

    这个配置文件告诉nginx从文件系统中拉起media和static文件作为服务,
    同时响应django的request。

    为此,我也在相应的项目目录下先建立起media和static文件夹。

    为方便nginx使用,我在/etc/nginx/vhosts.d下创建了一个luffy_nginx.conf的软链接。当然,也有人是直接用默认的sites-enabled目录,自己看着来就行了。

    sudo ln -s /home/operation/work/luffy/luffy_nginx.conf luffy.conf

    django部署static文件

    • 在项目文件夹下,建立好静态文件目录:
      mkdir static

    • django的setting文件中,添加一行:
      STATIC_ROOT = os.path.join(BASE_DIR, “static/”)

    • 运行
      python manage.py collectstatic

    • 在项目文件夹下,建立一个media媒体文件目录(用于存放图片音乐等文件做测试)
      mkdir media

    在media目录中,我传入了一个图片文件princekin_fox.jpg用于测试nginx。

    参数STATIC_ROOT用在哪?
    通过python3 manage.py collectstatic收集所有你使用的静态文件保存到STATIC_ROOT

    STATIC_ROOT 文件夹 是用来将所有STATICFILES_DIRS中所有文件夹中的文件,以及各app中static中的文件都复制过来,把这些文件放到一起是为了用nginx等部署的时候更方便。

    重新加载nginx进行测试

    先进行检测,看之前的配置文件有无错误。
    sudo /usr/sbin/nginx -t

    重新加载nginx让软链接的luffy_nginx.conf生效。
    sudo /usr/sbin/nginx -s reload

    访问http://luffy.tielemao.com:8000/media/princekin_fox.jpg看能否正常访问到图片资源:

    注意在做这一步之前,我是己经配置好域名和传送了一个用于测试的图片到服务器上。

    我己经能成功访问到资源了,所以接下来再做下一步测试。

    测试nginx 应用 uWSGI 和 test.py

    还记得之前写好的一个测试的test-uwsgi.py文件吗?
    我们就用配置好的nginx来访问uwsgi启动的test-uwsgi.py好了。
    首先,启动uwsgi,并且端口是nginx配置中的负载均衡池8083端口:
    uwsgi --socket :8083 --wsgi-file test-uwsgi.py

    访问http://luffy.tielemao.com:8000/,实际上访问的就是uwsgi的8083端口。

    如上图,能正常访问。表明下面的环节通畅:

    the web client <-> the web server <-> the socket <-> uWSGI <-> Python

    测试成功后中止程序,以便进行下面环节。

    用UNIX socket取代TCP port

    修改luffy_nginx.conf

    # luffy_nginx.conf
    
    # the upstream component nginx needs to connect to
    upstream django {
        server unix:///home/operation/work/luffy/luffy.sock;
        # for a file socket
        # server 127.0.0.1:8083; 
        # for a web port socket (we'll use this first)
    }
    

    上面其实是将原来的server 127.0.0.1:8083加以注释,而原来加了#注释的server unix:///home/operation/work/luffy/luffy.sock则取消了注释,也就是不是直接指定端口,而是指定了一个sock文件。

    • 要注意的是,这个luffy.sock并不是自己提前写好的什么配置文件,而是由程序自动生成的。如图:

    重新加载nginx,然后在项目下运行uWSGI

    uwsgi --socket /home/operation/work/luffy/luffy.sock --wsgi-file test-uwsgi.py 

    访问http://luffy.tielemao.com:8000/ 报502网关错误。
    检查nginx的错误日志error.log,一般位置会在/var/log/nginx/error.log,建议使用tail察看文件尾部的后10行。
    会发现类似以下报权限受阻的错误:

    2018/08/27 20:17:44 [crit] 25771#25771: *1847865 connect() to unix:///home/operation/work/luffy/luffy.sock failed (13: Permission denied) while connecting to upstream, client: 223.72.74.11, server: luffy.tielemao.com, request: "GET / HTTP/1.1", upstream: "uwsgi://unix:///home/operation/work/luffy/luffy.sock:", host: "luffy.tielemao.com:8000"

    那么就中止uwsgi进程,添加上socket权限后再次运行:

    uwsgi --socket /home/operation/work/luffy/luffy.sock --wsgi-file test-uwsgi.py --chmod-socket=664

    还是报错的话,就需将operation用户添加到nginx组中了,当然某些系统中nginx组也可能是www-data

    将operation用户添加到nginx组中,记得要加上-a参数,不然operation将会离开原来的operation组。

    sudo usermod -a -G nginx operation

    然后将项目目录也归属到nginx组中

    sudo chown operation:nginx -R luffy

    这样就能保证nginx能对luffy.sock有足够的权限了。
    果然,设置好权限后,就能正常访问了。

    每次都运行上面命令来拉起django项目实在不方便,我们可以将这些配置写在.ini文件中,能大大简化工作。

    停掉uwsgi服务后,见下一环节。

    uwsgi部署加强

    使用uwsgi配置文件运行django项目

    uwsgi支持ini,xml等多种配置方式,以ini为例,在/home/operation/work/conf目录下新建uwsgi_luffy.ini,示例配置如下:

    # luffy_uwsgi.ini file
    [uwsgi]
    
    # Django-related settings
    # the base directory (full path)
    # 指定运行目录,其实就是项目的根目录
    chdir = /home/operation/work/luffy
    
    # Django's wsgi file
    # 导入django项目的wsgi模块
    module = luffy.wsgi:application
    
    # 载入wsgi-file
    wsgi-file = luffy/wsgi.py
    
    # the virtualenv (full path)
    # 配置虚拟环境python相关依赖包所在路径
    home = /home/operation/work/py3env
    
    # 补充,uwsgi启动时的用户和用户组,注意要按你自己的实际权限进行配置
    # 我这边是因为项目属主是operation,而operation我设置了添加进了nginx组
    # 但这种情况下uid仍不能设置nginx,除非你的项目目录所有文件属主都改为了nginx
    uid = operation
    gid = nginx
    
    # process-related settings
    # 开启master主进程
    master = true 
    
    # maximum number of worker processes
    # 开启多少个进程数,workers项也等同processes
    # threads项则是设置运行线程,测试倒不用设置上线程
    processes = 4
    
    # the socket (use the full path to be safe)
    # 设置使用的socket端口或socket地址
    # socket = 0.0.0.0:8000
    # 上面的socket建议配置成一个luffy.socket文件后使用nginx来连接uWSGI运行,不然容易报socket的请求头错误和权限错误等。
    socket = /home/operation/work/luffy/luffy.socket
    
    # ... with appropriate permissions - may be needed
    # 配置生成的sock文件的权限
    chmod-socket = 664 
    
    # clear environment on exit
    # 退出时清空环境,其实就是将自动生成的luffy.sock和相关pid文件给干掉。
    vacuum = true

    uwsgi指定配置文件启动django项目,建议使用nginx用户执行:
    uwsgi --ini /home/operation/work/conf/uwsgi_luffy.ini

    • 注:以上启动后如果你是在配置文件中直接指定的socket = 0.0.0.0:8000可能会产生如下问题:浏览器访问服务器8000端口加上url后,浏览器会报连接出错,而服务器运行后台也会看到如下错误信息:
      invalid request block size: 21573 (max 4096)...skip

    之前我们直接使用http协议的方式就不会出现块请求大小超出

     uwsgi --http :8000 --module luffy.wsgi

    究其原因,使用配置文件启动是以socket方式提供通信端口,默认的协议是tcp,和http不同。socket请求头默认大小是4096,所以请求头超出默认大小后就会出现错误。当然后面我们可以通过和nginx合作的方式解决。

    而如果只是想测试,那么只要在上面的命令后面再指定块请求大小-b 24576之类的便可以解决。

    我们中止uwsgi后重新指定块大小,运行命令:
    uwsgi -b 24576 --ini /home/operation/work/conf/uwsgi_luffy.ini
    可以解决请求头错误。

    不过ini配置文件主要是用于和nginx配合,这也是为什么前面讲述完nginx的部署后再回过头来讲uwsgi的ini配置文件。

    • 将uWSGI中使用的相同选项放入一个配置文件中,然后要求uWSGI使用该文件运行。这会使得管理配置变得更加容易。

    • 要注意的是,因为要配合nginx,所以生成的项目名.sock文件,nginx需要能有权限读写。

    如下图:

    由于我前面执行uwsgi命令时使用的是operation用户,
    这样子自动生成的luffy.sock文件属组并不是nginx的,所以ini配置文件中最好加上uid和gid的配置项使用nginx用户执行uwsgi。

    # uwsgi启动用户名和用户组
    uid = operation
    gid = nginx

    我是修改完luffy.sock的属组为nginx后就能正常访问到django项目了,不然会被nginx报502错误。

    安装uWSGI到真实环境中

    到目前为止,我们都是在虚拟环境下工作的,接下来介绍将uwsgi装在实际环境中,且将uwsgi加入到nginx组(有的是www-data组)中,就可避免现在所遇到的权限等问题。

    • 退出虚拟环境
      deactivate

    • 安装uWSGI,注意要使用python3中的pip3来进行安装。我系统中是python2.7和python3.5.6共存的,不过默认的环境是2.7。
      sudo /usr/local/python3.5.6/bin/pip3 install uwsgi

    • 之前我使用默认的pip进行安装,结果是python2版本的uwsgi,在运行虚拟环境中的python3的django项目时会报以下错误:

    Python version: 2.7.13 (default, Jan 03 2017, 17:41:54) [GCC]
    Set PythonHome to /home/operation/work/py3env
    ImportError: No module named site
    VACUUM: unix socket /home/operation/work/luffy/luffy.sock removed.

    报模块导入错误,原因还是在于我真实环境使用的是python2.7版本的原因,ini中配置了虚拟环境家目录是python3的依赖库,pip安装的uwsgi不能正确导入。

    • 再次检查,在真实环境中是否能如同虚拟环境之前一样能运行django项目。
      当然,由于我前面的python3没有导入系统环境中,所以此处仍然要像前面使用python3的pip3一样,需要打全路径:
    sudo /usr/local/python-3.5.6/bin/uwsgi --ini /home/operation/work/conf/uwsgi_luffy.ini
    • 模块无法导入的错误己排除了,但是还会报一个bind绑定拒绝的错误。

    出现这个错误还是和文件权限有关,因为我之前uwsgi的ini配置文件中uid设置的用户是nginx,而项目真正的属主是operation这个用户,所以我将uid设置回operation就解决问题了,当然将项目整个属主设为nginx用户也是可行的。

    # 因为权限问题踩了不少坑,在此继续加强强调。
    # 注意的是你要按自己的实际环境配置
    uid = operation
    gid = nginx

    成功运行uwsgi的截图我也放出给大家对比一下看吧。
    当然,访问页面成功的截图就不放了,和之前测试成功的是一样的。

    uwsgi配置文件更多参数

    前面己经给大家看到了uwsgi的ini文件的一些配置参数,在此以luffy项目为例,再介绍一些常用到的参数:

    # set an environment variable
    # 设置变量环境,其实就是应用上django项目中的settings
    env = DJANGO_SETTINGS_MODULE=luffy.settings
    
    # create a pidfile
    # 创建pid文件,注意权限,所以一般放置在tmp目录下
    pidfile = /tmp/project-master.pid 
    
    # background the process & log
    # 后台运行,有用,基本都会设置上,同时还会输出日志
    daemonize = /var/log/uwsgi/luffy.log 
    
    # 以固定的文件大小(单位kb),进行切割日志
    # 下例为50M大小一个日志文件
    log-maxsize = 50000000
    
    # 不记录请求信息的日志。只记录错误以及uWSGI内部消息到日志中。
    disable-logging = true
    #
    # 在指定的地址上,开启状态服务。应该就是你访问该地址,就能看到整个uwsgi
    的状态,类似nginx也有。所以一般会只在环回地址上开放。
    stats = 127.0.0.1:8009
    
    # 以下都是一些性能和资源上的限制和调配
    # respawn processes taking more than 20 seconds
    harakiri = 20 
    # limit the project to 128 MB
    # 控制进程的总内存量
    limit-as = 128 
    # respawn processes after serving 5000 requests
    max-requests = 5000 
    
    • 访问stats状态服务页面大致如下:

    uWSGI开机启动服务

    继续以django的luffy项目为例,让uWSGI开机就启动服务,编辑文件/etc/rc.local, 添加下面内容到这行代码之前exit 0:

    /usr/local/python-3.5.6/bin/uwsgi --ini /home/operation/work/conf/uwsgi_luffy.ini

    要注意的是记得ini配置文件中设置好用户用户组,sock文件,sock文件的权限和后台运行等配置。

    end
    by 铁乐与猫

    参考
    * uwsgi官方文档
    * py鱼博客相关文章

    展开全文
  • uwsgi配置理解

    千次阅读 2018-08-18 15:49:01
    最近使用uwsgi 部署了flask应用,出现了不少问题,仔细查阅了一下资料以及翻看了官方文档,就对自己了解到的做个总结~~ 一、http/http-socket/socket uwsgi开头当然少不了通信的接口。 有3种方式: socket=...

    最近使用uwsgi 部署了flask应用,出现了不少问题,仔细查阅了一下资料以及翻看了官方文档,就对自己了解到的做个总结~~

    一、http/http-socket/socket

    uwsgi开头当然少不了通信的接口。

    有3种方式:

    socket=127.0.0.1:8888
    
    http=0.0.0.0:8888
    
    http-socket=127.0.0.1:8888

     三个方式看起来十分的相似,阅读了很多博客和官方文档,下面是自己的一些理解(可能不完全正确)!

    图一是socket方式,现在大部分web服务器(如nginx)支持uwsgi, 这是这三种方式最高效的一种形式,socket通信速度会比http快

    图二是http-socket方式,这个适用于web服务器不支持uwsgi时。

    后面2个图都是http方式,使用http启动uwsgi,系统会额外启动一个http进程,从级别上来说,它和nginx是同一级别的,所以客户端和uwsgi通信,完全可以绕过nginx,不需要额外进行一个转发(如图三一样),但很显然,这是并不是一个很明智但选择,这样会失去了nginx很多优秀的功能。

    官方推荐的方式为socket以及http-socket方式,显然使用http方式会额外产生一个http进程,如果还通过nginx转发,那么效率上来说是相对比较低的。

    二、processes/workers.

           表示开启多进程,根据你的应有开启合适的进程数,在一些参考资料上,可能会看到processes = 2 * cpucores或者workers = 2 * cpucores,如果应有比较简单,这样设置一般可以。如果想更合理,官方提供了uwsgitop去获得一个较为合理的值。

    三、threads & enable-threads

            python中存在GIL,实际上不存在真正意义上的多线程,但是否需要,这个就根据各自但需求设定了。结合processes:

    processes=2
    threads=4

    表示2个进程,每个进程中有4个线程。

           由于GIL的存在,uwsgi索性默认不支持多线程,不对GIL进行初始化。但如果希望程序中的线程发挥作用,需要加入enable-threads=True;

          但如果已经在多线程模式(使用 threads 选项)下,那么uWSGI将会自动启用线程支持。

    四、uid & gid & chmod-socket

           uwsgi不建议使用root权限去启动uwsgi实例。可以通过root用户去运行uwsgi文件,当通过uid和gid去修改用户(移除root权限)。并且,如果你使用的是socket的通信方式,最好加上chmod-socket字段,在linux下,socket的启动方式,套接字类似文件,你必须保证有权限去读取它。

    chmod-socket=660
    uid=1000
    gid=1000

    五、master

           意味着启动一个master主进程来管理其他进程,建议启动这个进程,在管理的时候比较方便;如果kill这个master进程,相当于关闭所有的uwsgi进程。

    六、其他

            chdir: 工程目录(启动文件所在位置)。 

            module: 应有程序文件(这个字段与wsgi-file相似?)

          callable:flask应用实例的名称,是flask独有的配置项(django不需要)。由于flask存在特殊的机制,可以实例化多个application,需要明确指出,收到请求时,uwsgi应该调用哪个应用实例。

           buffer-size: 设置用于uwsgi包解析的内部缓存区大小,默认是4k。如果你允许接受较大数据的报头,这个值可以设置到64k,如果出现报头过大的错误,可以通过设置这个值解决。

           daemonize: 日志输出文件。

           disable-logging: 不记录正常的请求日志,只记录错误日志。

    七、lazy-app

           这个字段有着特殊的作用,目前还在测试与使用,接下来再把发现的问题更新进来。

    下面是是我flask项目的完整uwsgi文件:

    socket=127.0.0.1:9088
    #http-socket=127.0.0.1:8888
    #http=127.0.0.1:8888
    
    processes=2
    threads=4
    enable-threads=true
    lazy-apps=true
    
    uid=1000
    gid=1000
    chmod-socket=660
    
    master=true
    chdir=/data/myapp/
    module=manage
    callable=app
    
    buffer-size=65536
    daemonize=/data/log/uwsgi/app.log

     

    展开全文
  • uWSGI的安装与配置(官网摘录)

    万次阅读 2015-02-25 18:18:25
    ■ 安装uwsgi: 作为一个严谨(其实就是有强迫症)的程序,为了确保正确安装这个东西,费了我好长时间。首先,查找包里的readme,发现没有安装提示。各种被墙,辗转良久,才查看到uwsgi的官方文档说明: ...
  • uWsgi是什么?

    2020-02-25 22:44:15
    1、什么要用uWsgi? &:因为nginx不支持wsgi协议,及无法直接调用py开发的webApp。 在nginx+uWsgi+flask的框架里,nginx代理+webServer,uWsgi是wsgiServer,flask是webApp。 nginx接收用户请求,并判定哪些转发...
  • WSGI & uwsgi

    2018-10-22 23:02:15
    WSGI协议 首先弄清下面几个概念:WSGI:全称是Web Server Gateway Interface,WSGI是一种规范,用来描述web server如何与web application通信的规范。server和application的规范在PEP 3333中有具体描述。...
  • WSGI,uWSGIuwsgi区别详解

    千次阅读 2019-08-28 13:58:23
    一、WSGI是什么? WSGI,全称 Web Server Gateway Interface,或者 Python Web Server Gateway Interface ,是为 Python 语言定义的 Web 服务器和 Web 应用程序或框架之间的一种简单而通用的接口。...
  • 1. 添加uwsgi相关文件在之前的文章跟讲到过centos中搭建nginx+uwsgi+flask运行环境,本节就基于那一次的配置进行说明。在www中创建uwsgi文件夹,用来存放uwsgi相关文件在uwsgi文件夹中创建uwsgi.pid和uwsgi.status...
  • WSGI,uwsgiuWSGI详解

    千次阅读 2018-12-16 17:44:38
    WSGI 全称:Web Server Gateway Interface 翻译过来就是Web服务器网关接口;WSGI是一个规范协议,定义了Web服务器如何与Python应用程序进行交互,使得使用Python写的Web应用程序可以和Web服务器对接起来。...
  • python3安装uwsgi(编译的方式)

    千次阅读 2019-01-25 22:24:06
    不知道为什么,使用pip3 install uwsgi总是提示安装成功,但是文件太少,不知道如何启动,而且没有uwsgi命令 1、pip方式安装uwsgi(未实现) 2、采用编译的方式安装uwsgi(已实现) 新建uwsgi文件夹 [root@...
  • 使用uwsgi部署flask

    千次阅读 2019-05-07 20:58:14
    由于对uwsgi不熟悉,从接触flask并部署到uwsgi用了30个小时。 使用隔离的环境 可以使用virtualenv, conda建立新的环境。我这里使用了virtualenv。 (1)安装 virtualenv pip3 install virtualenv (2)在项目的...
  • **启动报错已经解决了一个,但是其他的实在没办法 大神,怎么解决 之前没这个问题,出现之后不管怎么重新装系统都解决不了** 以下是配置文件 ``` [uwsgi] uid = www gid = www socket...
  • uwsgi --ini uwsgi.ini 启动时出现此问题 再次启动uwsgi.id 越来越大 your processes number limit is 7856 your memory page size is 4096 bytes detected max file descriptor number: 65535 lock engine...
  • 当我们在服务器上配置好 uwsgi 后,使用 uwsgi --ini uwsgi.ini 部署项目时虽然出现提示: [uWSGI] getting INI configuration from uwsgi.ini 但通过如下命令查看绑定的端口时,发现端口并没有被监听 netstat -lnp...
  • 最近配置了nginx+uwsgi+django,其中项目目录下我新建了uwsgi.ini配置文件 [uwsgi] socket = 127.0.0.1:8088 master = true pidfile = /tmp/uwsgi.pid processes = 8 chdir = /home/test daemonize=/home/log/uwsgi....
  • uwsgi.ini常用配置参数详解

    万次阅读 2019-03-11 10:08:19
    master = true#启动主进程,来管理其他进程,其它的uwsgi进程都是这个master进程的子进程,如果kill这个master进程,相当于重启所有的uwsgi进程。 chdir = /web/www/mysite#在app加载前切换到当前目录, 指定运行...
  • 但是出于需求,我使用anaconda创建了python3.7的虚拟环境,然后在该虚拟环境下使用uwsgi部署flask项目,写好了配置uwsgi.ini文件后,敲下uwsgi --ini uwsgi.ini命令,得到的结果却不是我想要的,报错如下: ...
  • 提示配置文件头部找不到 [uwsgi] 解决:  在最上方加上[uwsgi],有时候明明有标识,但是还是提示,那就再加一个 转载于:https://www.cnblogs.com/gcgc/p/10152994.html...
  • root@iZ2ze69ip1k885e39qa56cZ:/var/www/djangoProject11# uwsgi --ini /var/www/djangoProject11/uwsgi.ini The program 'uwsgi' can be found in the following packages: * uwsgi-core * uwsgi-plugin-alarm-...

空空如也

1 2 3 4 5 ... 20
收藏数 30,312
精华内容 12,124
关键字:

uwsgi