uWSGI教程

uWSGI教程-----使用uWSGI和nginx配置你的web服务器

这个教程旨在那些想要配置一个生产web服务的Django用户。它将带你领略必要的步骤来使用uWSGI和nginx来配置Django并让他更好的工作。它涵盖所有3个组件,提供了一组完整的web应用程序和服务软件。

  •  

    Django是一个高级Python Web框架,鼓励快速开发和简洁,使用的设计。

     

    nginx(发音 engine-x)是免费的,开源的,高性能的HTTP服务和反向代理,以及IMAP/POP3代理服务。

     

    1. 关于这个教程的一些注意事项

    这是一个教程。它并不会提供一个参考指导,也不会考虑详细的指引,对部属的主题来说。

     

    nginx和uWSGI对于Django开发来说都是好的选择,但它们并不是唯一的,或者“官方”的那个。这2者都有更好的替代方法,并鼓励你去找到它们。

     

    我们在这里部属Django的方式是很好的,但它并不是唯一的方式;因为一些原因它可能不是最好的方式。

     

    然而它是可靠的,简单的方式,并且这里涵盖的材料将会给你介绍理念和程序,你将需要熟悉他们来使用任何软件部属Django。通过提供给你一个工作的配置,和你必须了解的步骤,它将提供你一个探索其他方式来达到这个目标的基础。

     

    这个教程关于你正在使用的系统做了一些假设。

     

    它假设你正在使用一个类Unix系统,并且它有一个类似智能的包管理器。然而如果你需要问:“在Mac OS X上等价于智能的是什么?”,你将能很容易的找到这种帮助。

     

    这个教程假定Django 1.4 或更新的版本,它会自动在你的心的项目中创建一个wsgi模型,这个指引将和早期的版本一起。你将需要自己获取Django的wsgi模块,并且你将会发现,Django项目的目录结构有轻微的不同。

     

    2. 理念

    一个Web服务器将对外面的世界开放。它能直接从文件系统中提供文件(HTML,images,CSS等)。然而,它还不能直接与Django应用程序交互;它需要一些能运行应用的东西,从web客户端(例如浏览器)中输入请求并且返回响应。

     

    一个Web服务器网关接口 -- WSGI --做这个工作。WSGI是一个Python标准。

     

    uWSGI是一个WSGI实现。在这个教程中,我们将配置uWSGI让它可以创建一个Unix套接字,并通过WSGI协议为Web服务器提供响应。在最后,我们全部组件堆叠应该像这样:

    [python] view plain copy print?

1.  the web client <-> the web server <-> the socket <-> uwsgi <-> Django  

the web client <-> the web server <-> the socket <-> uwsgi <-> Django

 

3. 开始配置uWSGI之前

3.1 virtualenv

确保你在我们需要安装的软件的virtualenv环境中(我们将描述如何安装一个系统及的uwsgi稍后):

[python] view plain copy print?

1.  virtualenv uwsgi-tutorial  

2.  cd uwsgi-tutorial  

3.  source bin/activate  

virtualenv uwsgi-tutorial

cd uwsgi-tutorial

source bin/activate

 

3.2 Django

在你的virtualenv中安装Django,创建一个新的项目,并且cd进这个项目:

[python] view plain copy print?

1.  pip install Django  

2.  django-admin.py startproject mysite  

3.  cd mysite  

pip install Django

django-admin.py startproject mysite

cd mysite

 

3.3 关于域名和端口

在这个教程中,我们将会调用你的域名example.com。替代你的正式域名或IP地址。

 

自始自终,我们将为你的web服务器使用8000端口来发布,就像Django默认的runserver做的一样。当然你可以使用任何你想的端口,但我选择这个是因为它不会与可能已经运行的任何web服务器冲突。

 

4 基本uWSGI安装和配置

4.1 在你的virualenv环境下安装uWSGI

[python] view plain copy print?

1.  pip install uwsgi  

pip install uwsgi

当然有其他安装uWSGI的方式,但这个和其他的一样好。请记住,你将需要安装Python开发包。在Debian系统中,或者Debian驱动的系统例如Ubuntu,你需要安装的是pythonX.Y-dev,其中,X.Y是你的Python版本。

 

4.2 基本测试

创建一个文件名称为:test.py:

[python] view plain copy print?

1.  # test.py  

2.  def application(env, start_response):  

3.      start_response('200 OK', [('Content-Type','text/html')])  

4.      return [b"Hello World"] # python3  

5.      #return ["Hello World"] # python2  

# test.py

def application(env, start_response):

    start_response('200 OK', [('Content-Type','text/html')])

    return [b"Hello World"] # python3

    #return ["Hello World"] # python2

注意

在Python3里需要bytes()

 

运行uWSGI:

[python] view plain copy print?

1.  uwsgi --http :8000 --wsgi-file test.py  

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

选项含义:

  • http:8000:使用http协议,8000端口

  • wsgi-file test.py:加载指定文件,test.py

    这应该发送一个‘hello world’消息直接到你的浏览器的8000端口。访问:

    [python] view plain copy print?

1.  http://example.com:8000  

http://example.com:8000

来检查。如果是这样,那就意味着下面的嘴尖流工作了:

[python] view plain copy print?

1.  the web client <-> uWSGI <-> Python  

the web client <-> uWSGI <-> Python

 

5. 测试你的Django项目

 

现在我们想要uWSGI做同样的事情,但是要运行Django站点而不是test.py模块。

 

如果你还没这样做,确保你的mysite项目确实的工作:

[python] view plain copy print?

1.  python manage.py runserver 0.0.0.0:8000  

python manage.py runserver 0.0.0.0:8000

并且如果它生效了,使用uWSGI来运行它:

[python] view plain copy print?

1.  uwsgi --http :8000 --module mysite.wsgi  

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

  • module mysite.wsgi:加载指定的wsgi模块

    在服务器上点开你的浏览器;如果站点出现了,就意味着uWSGI能在你的virtualenv环境下服务你的Django应用,并且这个堆栈操作正确:

    [python] view plain copy print?

1.  the web client <-> uWSGI <-> Django  

the web client <-> uWSGI <-> Django

现在正常来说我们还没有让浏览器直接和uWSGI对话。那是webserver的工作,它将会充当一个中间人角色。

 

6. 基础的nginx

6.1 安装nginx

[python] view plain copy print?

1.  sudo apt-get install nginx  

2.  sudo /etc/init.d/nginx start    # start nginx  

sudo apt-get install nginx

sudo /etc/init.d/nginx start    # start nginx

通过在浏览器中访问80端口来检查nginx是否启动服务 -- 你应该会从nginx得到一条消息:“Welcome to nginx!”.那意味着这样的堆栈正在一起工作:

[python] view plain copy print?

1.  the web client <-> the web server  

the web client <-> the web server

如果其他一些东西已经在80端口上工作了,但你想在80上使用nginx,你必须重新配置一个不同的端口。在这个教程中,我们将使用8000端口

 

6.2 为你的站点配置nginx

你将需要uwsgi_params文件,他在uWSGI发布的nginx目录,或者从https://github.com/nginx/nginx/blob/master/conf/uwsgi_params找到。

 

将它复制到你的项目目录。稍后我们将告诉nginx来引用它。

 

现在我们创建一个名为mysite_nginx.conf的文件,并添加如下代码:

[python] view plain copy print?

1.  # mysite_nginx.conf  

2.    

3.  # the upstream component nginx needs to connect to  

4.  upstream django {  

5.      # server unix:///path/to/your/mysite/mysite.sock; # for a file socket  

6.      server 127.0.0.1:8001; # for a web port socket (we'll use this first)  

7.  }  

8.    

9.  # configuration of the server  

10. server {  

11.     # the port your site will be served on  

12.     listen      8000;  

13.     # the domain name it will serve for  

14.     server_name .example.com; # substitute your machine's IP address or FQDN  

15.     charset     utf-8;  

16.   

17.     # max upload size  

18.     client_max_body_size 75M;   # adjust to taste  

19.   

20.     # Django media  

21.     location /media  {  

22.         alias /path/to/your/mysite/media;  # your Django project's media files - amend as required  

23.     }  

24.   

25.     location /static {  

26.         alias /path/to/your/mysite/static; # your Django project's static files - amend as required  

27.     }  

28.   

29.     # Finally, send all non-media requests to the Django server.  

30.     location / {  

31.         uwsgi_pass  django;  

32.         include     /path/to/your/mysite/uwsgi_params; # the uwsgi_params file you installed  

33.     }  

34. }  

# mysite_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:8001; # 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 .example.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 /path/to/your/mysite/media;  # your Django project's media files - amend as required

    }

 

    location /static {

        alias /path/to/your/mysite/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     /path/to/your/mysite/uwsgi_params; # the uwsgi_params file you installed

    }

}

这个conf文件告诉nginx从文件系统中提供媒体和静态文件,以及处理需要Django干预的请求。在一个大的部属中让一个服务处理静态/媒体文件,另一个处理Django应用将会是个好习惯,但是现在,这样做就很好。

 

从/etc/nginx/sites启动这个文件的符号链接所以nginx能看见它:

[python] view plain copy print?

1.  sudo ln -s ~/path/to/your/mysite/mysite_nginx.conf /etc/nginx/sites-enabled/  

sudo ln -s ~/path/to/your/mysite/mysite_nginx.conf /etc/nginx/sites-enabled/

 

6.3 部属静态文件

在运行nginx之前,你必须在静态文件夹中搜集所有的Django静态文件。首先你需要编辑mysite/settings.py添加:

[python] view plain copy print?

1.  STATIC_ROOT = os.path.join(BASE_DIR, "static/")  

STATIC_ROOT = os.path.join(BASE_DIR, "static/")

然后运行:

[python] view plain copy print?

1.  python manage.py collectstatic  

python manage.py collectstatic


 6.4
基本nginx测试

重启nginx:

[python] view plain copy print?

1.  sudo /etc/init.d/nginx restart  

sudo /etc/init.d/nginx restart

为了检查媒体文件被正确的服务到了,添加一个图片名为media.png到/path/to/your/project/project/media 目录,然后访问http://example.com:8000/media/media.png-如果这生效了,你将知道至少nginx正确的服务文件。

 

不仅重启nginx,还要确切的停止并在此启动它,这样它将会通知你有问题,并且在哪儿。

 

7. nginx和uWSGI和test.py

让我们来让nginx对“hello world”test.py应用沟通。

[python] view plain copy print?

1.  uwsgi --socket :8001 --wsgi-file test.py  

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

这几乎和之前一样,除了这次有一个选项不同:

  • socket:8001:使用协议uwsgi,8001端口

    nginx同时被配置在那个端口上和uWSGI交流,对外的端口是8000。访问:http://example.com:8000/来检查。这就是我们的堆栈:

    [python] view plain copy print?

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

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

同时,你可以在http://example.com:8001看看uswgi输出 -- 但非常可能的是,它将不会生效因为你的浏览器使用http,不是uWSGI,尽管你应该在你的终端看到来自uWSGI的输出。


 8.
使用Unix套接字代替端口

到目前为止我们已经使用了一个TCP端口套接字,应为它简单,但事实上使用Unix套接字比端口要更好 -- 开支要小。

 

编辑mysite_nginx.conf,修改它来匹配:

[python] view plain copy print?

1.  server unix:///path/to/your/mysite/mysite.sock; # for a file socket  

2.  # server 127.0.0.1:8001; # for a web port socket (we'll use this first)  

server unix:///path/to/your/mysite/mysite.sock; # for a file socket

# server 127.0.0.1:8001; # for a web port socket (we'll use this first)

并且重启nginx。

 

再次运行uWSGI:

[python] view plain copy print?

1.  uwsgi --socket mysite.sock --wsgi-file test.py  

uwsgi --socket mysite.sock --wsgi-file test.py

这一次socket选项告诉uWSGI去使用那个文件。

在浏览器中尝试http://example.com:8000/。

 

8.1 如果那不起作用 

检查你的nginx错误日志(/var/log/nginx/error.log).如果你看到这样的东西:

[python] view plain copy print?

1.  connect() to unix:///path/to/your/mysite/mysite.sock failed (13: Permission  

2.  denied)  

connect() to unix:///path/to/your/mysite/mysite.sock failed (13: Permission

denied)

那么你可能需要在套接字上管理权限让nginx能够使用它。

 

尝试:

[python] view plain copy print?

1.  uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=666 # (very permissive)  

uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=666 # (very permissive)

或者:

[python] view plain copy print?

1.  uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=664 # (more sensible)  

uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=664 # (more sensible)

你也许需要将你的用户添加到nginx的组(它可能是www-data),或者vice-versa,让nginx在你的套接字里能适当的读写。

 

在终端窗口运行nginx日志的输出是值得的,这样你可以在故障排除的时候方便的引用它。


 9.
使用uwsgi和nginx运行Django应用

让我们运行我们的Django应用:

[python] view plain copy print?

1.  uwsgi --socket mysite.sock --module mysite.wsgi --chmod-socket=664  

uwsgi --socket mysite.sock --module mysite.wsgi --chmod-socket=664

现在uWSGI和nginx应该服务的不是一个“Hello World”模块,而是你的Django项目了

 

10. 配置uWSGI来运行一个.ini文件

我们能将我们在uWSGI中使用的同样的选项放在一个文件中,并且让uWSGI来运行那个文件。这将让它更容易管理配置。

 

创建一个名为~mysite_uwsgi.ini~:

[python] view plain copy print?

1.  # mysite_uwsgi.ini file  

2.  [uwsgi]  

3.    

4.  # Django-related settings  

5.  # the base directory (full path)  

6.  chdir           = /path/to/your/project  

7.  # Django's wsgi file  

8.  module          = project.wsgi  

9.  # the virtualenv (full path)  

10. home            = /path/to/virtualenv  

11.   

12. # process-related settings  

13. # master  

14. master          = true  

15. # maximum number of worker processes  

16. processes       = 10  

17. # the socket (use the full path to be safe  

18. socket          = /path/to/your/project/mysite.sock  

19. # ... with appropriate permissions - may be needed  

20. # chmod-socket    = 664  

21. # clear environment on exit  

22. vacuum          = true  

# mysite_uwsgi.ini file

[uwsgi]

 

# Django-related settings

# the base directory (full path)

chdir           = /path/to/your/project

# Django's wsgi file

module          = project.wsgi

# the virtualenv (full path)

home            = /path/to/virtualenv

 

# process-related settings

# master

master          = true

# maximum number of worker processes

processes       = 10

# the socket (use the full path to be safe

socket          = /path/to/your/project/mysite.sock

# ... with appropriate permissions - may be needed

# chmod-socket    = 664

# clear environment on exit

vacuum          = true

并使用这个文件运行uwsgi:

[python] view plain copy print?

1.  uwsgi --ini mysite_uwsgi.ini # the --ini option is used to specify a file  

uwsgi --ini mysite_uwsgi.ini # the --ini option is used to specify a file

再一次,测试Django站点如预期一样工作。

 

11. 安装系统级uWSGI

到目前为止,uWSGI仅仅是安装在我们的virtualenv中;为了部属目的,我们需要它系统级的安装。

 

停止你的virtualenv:

[python] view plain copy print?

1.  deactivate  

deactivate

并且安装系统级uWSGI:

[python] view plain copy print?

1.  sudo pip install uwsgi  

2.    

3.  # Or install LTS (long term support).  

4.  pip install https://projects.unbit.it/downloads/uwsgi-lts.tar.gz  

sudo pip install uwsgi

 

# Or install LTS (long term support).

pip install https://projects.unbit.it/downloads/uwsgi-lts.tar.gz

uWSGI维基描述了几个安装程序。在安装系统级uWSGI之前,选择哪个版本以及最适当的方式来安装它是值得考虑的。

 

再次检查你仍然可以像以前一样运行uWSGI:

[python] view plain copy print?

1.  uwsgi --ini mysite_uwsgi.ini # the --ini option is used to specify a file  

uwsgi --ini mysite_uwsgi.ini # the --ini option is used to specify a file

 

12. 皇帝模式

uWSGI能以“皇帝”模式运行。在这种模式下,它将件事uWSGI配置文件的路径并且为每一个它找到的文件生成实例(‘诸侯’)。

 

无论什么时候一个配置文件被修改了,皇帝都会自动重启诸侯。

[python] view plain copy print?

1.  # create a directory for the vassals  

2.  sudo mkdir /etc/uwsgi  

3.  sudo mkdir /etc/uwsgi/vassals  

4.  # symlink from the default config directory to your config file  

5.  sudo ln -s /path/to/your/mysite/mysite_uwsgi.ini /etc/uwsgi/vassals/  

6.  # run the emperor  

7.  uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data  

# create a directory for the vassals

sudo mkdir /etc/uwsgi

sudo mkdir /etc/uwsgi/vassals

# symlink from the default config directory to your config file

sudo ln -s /path/to/your/mysite/mysite_uwsgi.ini /etc/uwsgi/vassals/

# run the emperor

uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data

你可以需要用sudo来运行uWSGI:

[python] view plain copy print?

1.  sudo uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data  

sudo uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data

选项意思:

  • emperor:寻找诸侯(配置文件)的地方

  • uid:一旦它启动后进程的用户id

  • gid:一旦它启动后进程的组id

    检查站点,它应该运行了。

     

13. 当系统启动时,让uWSGI启动

  • 最后一步是让它在系统启动时自动发生。

     

    对于许多系统来说,最容易(也许不是最好的)的方式就是使用rc.local文件。

     

    编辑/etc/rc.local并且添加:

    [python] view plain copy print?

1.  /usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data --daemonize /var/log/uwsgi-emperor.log  

/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data --daemonize /var/log/uwsgi-emperor.log

在“exit 0”之前。

 

那就是它应该的样子!

 

14. 进一步的配置

理解这是一个教程是很重要的,让你开始学习。你需要阅读nginx和uWSGI文档,在一个生产环境中部属它之前学习可用选项。

 

nginx和uWSGI都受益于友好的社区,它能提供关于配置和使用的宝贵意见。


 14.1 nginx

nginx的一般配置不再这个教程的范围之内尽管你可能想要它监听80端口,而不是8000,为了一个生产站点。

 

你应该为一个非Django文件配置一个独立的nginx本地块。例如,通过uWSGI服务静态文件是效率低下的,直接从Nginx服务并且完全绕开uWSGI。


 14.2 uWSGI

uWSGI支持多个配置的方式。阅读uWSGI文档和例子。

 

一些uWSGI选项在这个教程中已经被提及了;你应该为在生产中部属看看其他的包括(带有例子设置的列表):

[python] view plain copy print?

  1. env = DJANGO_SETTINGS_MODULE=mysite.settings # set an environment variable  

  2. safe-pidfile = /tmp/project-master.pid # create a pidfile  

  3. harakiri = 20 # respawn processes taking more than 20 seconds  

  4. limit-as = 128 # limit the project to 128 MB  

  5. max-requests = 5000 # respawn processes after serving 5000 requests  

  6. daemonize = /var/log/uwsgi/yourproject.log # background the process & log  

    env = DJANGO_SETTINGS_MODULE=mysite.settings # set an environment variable

    safe-pidfile = /tmp/project-master.pid # create a pidfile

    harakiri = 20 # respawn processes taking more than 20 seconds

    limit-as = 128 # limit the project to 128 MB

    max-requests = 5000 # respawn processes after serving 5000 requests

    daemonize = /var/log/uwsgi/yourproject.log # background the process & log