{% raw %}

如何使用Django与FastCGI,SCGI或AJP

自1.7版起已弃用:FastCGI支持已弃用,将在Django 1.9中删除。

虽然WSGI是Django的首选部署平台,但许多人使用共享托管,其中诸如FastCGI,SCGI或AJP等协议是唯一可行的选项。

注意

本文档主要关注FastCGI。还通过flup Python包支持其他协议,如SCGI和AJP。有关SCGI和AJP的详细信息,请参阅下面的协议部分。

本质上,FastCGI是一种有效的方式,让外部应用程序将页面提供给Web服务器。Web服务器将传入的Web请求(通过套接字)委派给FastCGI,FastCGI执行代码并将响应传递回Web服务器,Web服务器反过来将其传递回客户端的Web浏览器。

像WSGI一样,FastCGI允许代码留在内存中,允许在没有启动时间的情况下提供请求。而例如。 mod_wsgi可以嵌入Apache Web服务器进程或作为单独的守护进程配置,FastCGI进程永远不会在Web服务器进程内运行,始终在一个单独的持久进程中。

为什么在单独的进程中运行代码?

Apache中的传统mod_*安排将各种脚本语言(最值得注意的是PHP,Python和Perl)嵌入到Web服务器的进程空间中。虽然这会降低启动时间 - 因为代码不必为每个请求读取磁盘 - 它是以内存使用为代价的。

由于FastCGI的性质,甚至可能有不同于Web服务器进程的用户帐户运行的进程。这对共享系统是一个很好的安全好处,因为它意味着你可以保护你的代码与其他用户。

先决条件:flup

在开始使用FastCGI和Django之前,您需要安装flup,一个用于处理FastCGI的Python库。版本0.5或更高版本应该工作正常。

启动FastCGI服务器

FastCGI在客户端 - 服务器模型上运行,在大多数情况下,您将自己启动FastCGI进程。当服务器需要加载动态页面时,您的Web服务器(无论是Apache,lighttpd还是其他)只会联系您的Django-FastCGI进程。因为守护程序已经在内存中运行代码,所以它能够很快地提供响应。

注意

如果你在共享托管系统上,你可能会被迫使用Web服务器管理的FastCGI进程。有关更多信息,请参阅下面关于使用Web服务器管理的进程运行Django的部分。

Web服务器可以通过以下两种方式之一连接到FastCGI服务器:它可以使用Unix域套接字(Win32系统上的“命名管道”),也可以使用TCP套接字。你选择的是一种偏好的方式;TCP套接字通常更容易由于权限问题。

要启动您的服务器,首先切换到项目的目录(manage.py),然后运行runfcgi命令:

  1. ./manage.py runfcgi [options]

如果您在runfcgi之后指定help作为唯一选项,它将显示所有可用选项的列表。

您需要指定socketprotocolhostport。然后,当您设置Web服务器时,您只需将其指向在启动FastCGI服务器时指定的主机/端口或套接字。请参阅下面的示例

协议

Django支持flup的所有协议,即fastcgiSCGIAJP1.3(Apache JServ协议,版本1.3)。通过使用protocol=<protocol_name>选项和./ manage.py runfcgi选择您的首选协议 - 其中<protocol_name>可以是以下之一:fcgi(默认值),scgiajp。例如:

  1. ./manage.py runfcgi protocol=scgi

例子

在TCP端口上运行线程服务器:

  1. ./manage.py runfcgi method=threaded host=127.0.0.1 port=3033

在Unix域套接字上运行预分拣的服务器:

  1. ./manage.py runfcgi method=prefork socket=/home/user/mysite.sock pidfile=django.pid

套接字安全

Django的默认umask要求web服务器和Django fastcgi进程使用同一组用户运行。为了增加安全性,您可以在同一组下运行它们,但作为不同的用户。如果这样做,您需要使用runfcgiumask参数将umask设置为0002。

运行没有守护进程(后台)的进程(有利于调试):

  1. ./manage.py runfcgi daemonize=false socket=/tmp/mysite.sock maxrequests=1

停止FastCGI守护程序

如果您的进程在前台运行,可以轻松停止它:只需点击Ctrl-C将停止并退出FastCGI服务器。但是,当您处理后台进程时,您需要使用Unix kill命令。

如果您为runfcgi指定pidfile选项,则可以杀死正在运行的FastCGI守护程序,如下所示:

  1. kill `cat $PIDFILE`

…其中$PIDFILE是您指定的pidfile

  1. #!/bin/bash
  2. # Replace these three settings.
  3. PROJDIR="/home/user/myproject"
  4. PIDFILE="$PROJDIR/mysite.pid"
  5. SOCKET="$PROJDIR/mysite.sock"
  6. cd $PROJDIR
  7. if [ -f $PIDFILE ]; then
  8. kill `cat -- $PIDFILE`
  9. rm -f -- $PIDFILE
  10. fi
  11. exec /usr/bin/env - \
  12. PYTHONPATH="../python:.." \
  13. ./manage.py runfcgi socket=$SOCKET pidfile=$PIDFILE

Apache设置

要在Apache和FastCGI上使用Django,您需要安装并配置Apache,并安装并启用mod_fastcgi。有关说明,请参阅Apache文档。

设置完成后,通过编辑httpd.conf(Apache配置)文件将Apache指向Django FastCGI实例。你需要做两件事情:

  • 使用FastCGIExternalServer指令指定FastCGI服务器的位置。
  • 使用mod_rewrite可根据需要将网址指向FastCGI。

指定FastCGI服务器的位置

FastCGIExternalServer指令告诉Apache如何找到您的FastCGI服务器。如FastCGIExternalServer docs说明,您可以指定sockethost。这里有两个例子:

  1. # Connect to FastCGI via a socket / named pipe.
  2. FastCGIExternalServer /home/user/public_html/mysite.fcgi -socket /home/user/mysite.sock
  3. # Connect to FastCGI via a TCP host/port.
  4. FastCGIExternalServer /home/user/public_html/mysite.fcgi -host 127.0.0.1:3033

在任一情况下,文件/home/user/public_html/mysite.fcgi实际上不必存在。(更多在此在下一节)。

使用mod_rewrite将URL指向FastCGI

第二步是告诉Apache对匹配某种模式的URL使用FastCGI。为此,请使用mod_rewrite模块并将URL重写到mysite.fcgi(或您在FastCGIExternalServer指令中指定的任何内容,上一节)。

在本示例中,我们告诉Apache使用FastCGI来处理不表示文件系统上的文件并且不以/media/开头的任何请求。这可能是最常见的情况,如果你使用Django的管理网站:

  1. <VirtualHost 12.34.56.78>
  2. ServerName example.com
  3. DocumentRoot /home/user/public_html
  4. Alias /media /home/user/python/django/contrib/admin/media
  5. RewriteEngine On
  6. RewriteRule ^/(media.*)$ /$1 [QSA,L,PT]
  7. RewriteCond %{REQUEST_FILENAME} !-f
  8. RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L]
  9. </VirtualHost>

在使用{% url %}构建网址时,Django会自动使用网址的预先重写版本。模板标签(和类似方法)。

使用mod_fcgid替代mod_fastcgi

通过FastCGI提供应用程序的另一种方法是使用Apache的mod_fcgid模块。与mod_fastcgi相比,mod_fcgid对FastCGI应用程序的处理方式不同,它管理工作进程本身的产生,不提供像FastCGIExternalServer这样的东西。这意味着配置看起来略有不同。

实际上,您必须像添加一个类似于稍后描述的在shared-hosting environment中运行Django的脚本处理程序。有关详细信息,请参阅mod_fcgid参考

lighttpd设置

lighttpd是一种通常用于提供静态文件的轻量级Web服务器。它本地支持FastCGI,因此,如果您的站点没有任何Apache特定的需求,它是服务静态页面和动态页面的不错选择。

请确保mod_fastcgi位于模块列表中mod_rewritemod_access之后的位置,而不是mod_accesslog之后。您可能也希望使用mod_alias来管理管理媒体。

将以下内容添加到lighttpd配置文件中:

  1. server.document-root = "/home/user/public_html"
  2. fastcgi.server = (
  3. "/mysite.fcgi" => (
  4. "main" => (
  5. # Use host / port instead of socket for TCP fastcgi
  6. # "host" => "127.0.0.1",
  7. # "port" => 3033,
  8. "socket" => "/home/user/mysite.sock",
  9. "check-local" => "disable",
  10. )
  11. ),
  12. )
  13. alias.url = (
  14. "/media" => "/home/user/django/contrib/admin/media/",
  15. )
  16. url.rewrite-once = (
  17. "^(/media.*)$" => "$1",
  18. "^/favicon\.ico$" => "/media/favicon.ico",
  19. "^(/.*)$" => "/mysite.fcgi$1",
  20. )

在一个lighttpd上运行多个Django站点

lighttpd允许您使用“条件配置”允许每个主机自定义配置。要指定多个FastCGI站点,只需在每个站点的FastCGI配置周围添加一个条件块:

  1. # If the hostname is 'www.example1.com'...
  2. $HTTP["host"] == "www.example1.com" {
  3. server.document-root = "/foo/site1"
  4. fastcgi.server = (
  5. ...
  6. )
  7. ...
  8. }
  9. # If the hostname is 'www.example2.com'...
  10. $HTTP["host"] == "www.example2.com" {
  11. server.document-root = "/foo/site2"
  12. fastcgi.server = (
  13. ...
  14. )
  15. ...
  16. }

您还可以通过在fastcgi.server指令中指定多个条目,在同一网站上运行多个Django安装。为每个添加一个FastCGI主机。

切诺基设置

Cherokee是一个非常快速,灵活和易于配置的Web服务器。它支持现在广泛的技术:FastCGI,SCGI,PHP,CGI,SSI,TLS和SSL加密连接,虚拟主机,验证,即时编码,负载平衡,Apache兼容日志文件,数据库平衡器,反向HTTP代理和多更多。

Cherokee项目提供了一个文档,用于与Cherokee一起设置Django

在带有Apache的共享托管提供程序上运行Django

许多共享托管提供程序不允许您运行自己的服务器守护程序或编辑httpd.conf文件。在这些情况下,仍然可以使用Web服务器生成的进程运行Django。

注意

如果您正在使用Web服务器生成的进程,如本节所述,您无需自己启动FastCGI服务器。Apache将产生一些进程,按需扩展。

在Web根目录中,将其添加到名为.htaccess的文件:

  1. AddHandler fastcgi-script .fcgi
  2. RewriteEngine On
  3. RewriteCond %{REQUEST_FILENAME} !-f
  4. RewriteRule ^(.*)$ mysite.fcgi/$1 [QSA,L]

然后,创建一个小脚本,告诉Apache如何生成您的FastCGI程序。创建一个文件mysite.fcgi并将其放在您的Web目录中,并确保使其可执行:

  1. #!/usr/bin/python
  2. import sys, os
  3. # Add a custom Python path.
  4. sys.path.insert(0, "/home/user/python")
  5. # Switch to the directory of your project. (Optional.)
  6. # os.chdir("/home/user/myproject")
  7. # Set the DJANGO_SETTINGS_MODULE environment variable.
  8. os.environ['DJANGO_SETTINGS_MODULE'] = "myproject.settings"
  9. from django.core.servers.fastcgi import runfastcgi
  10. runfastcgi(method="threaded", daemonize="false")

如果你的服务器使用mod_fastcgi这工作。另一方面,如果你正在使用mod_fcgid,除了在.htaccess文件中略有改动,设置基本相同。而不是添加一个fastcgi脚本处理程序,你必须添加一个fcgid-handler:

  1. AddHandler fcgid-script .fcgi
  2. RewriteEngine On
  3. RewriteCond %{REQUEST_FILENAME} !-f
  4. RewriteRule ^(.*)$ mysite.fcgi/$1 [QSA,L]

重新启动生成的服务器

如果您更改网站上的任何Python代码,您需要告诉FastCGI代码已更改。但在这种情况下不需要重新启动Apache。相反,只需重新上传mysite.fcgi或编辑文件,以便文件上的时间戳将更改。当Apache看到文件已更新时,它会为您重新启动Django应用程序。

如果您可以访问Unix系统上的命令shell,可以使用touch命令轻松完成此操作:

  1. touch mysite.fcgi

投放管理媒体文件

无论您最终决定使用的服务器和配置,您还需要考虑如何提供管理媒体文件。在mod_wsgi文档中给出的建议也适用于上面详述的设置。

将URL前缀强制为特定值

因为许多这些基于fastcgi的解决方案需要在Web服务器的某个点重写URL,Django看到的路径信息可能不像传入的原始URL。这是一个问题,如果Django应用程序是从一个特定的前缀提供服务,你想要你的URL从{% url %}标记看起来像前缀,而不是重写的版本,其可能包含例如mysite.fcgi

Django做一个很好的尝试来弄出真正的脚本名称前缀应该是什么。特别是,如果Web服务器设置SCRIPT_URL(特定于Apache的mod_rewrite)或REDIRECT_URL(由一些服务器设置,包括Apache + mod_rewrite在某些情况下)将自动处理原始前缀。

如果Django无法正确计算出前缀,以及您希望在网址中使用原始值,则可以在主要的settings文件中设置FORCE_SCRIPT_NAME设置。这将为通过该设置文件提供的每个网址统一设置脚本名称。因此,如果您希望不同的网址集在这种情况下具有不同的脚本名称,则需要使用不同的设置文件,但这是一种罕见的情况。

作为如何使用它的示例,如果您的Django配置为'/'下的所有URL提供服务,并且想要使用此设置,则可以设置FORCE_SCRIPT_NAME = ''

{% endraw %}