Nginx支持

自0.8.40版本起,Nginx本身就包含了对使用 uwsgi protocol 的上游服务器的的支持。

配置Nginx

一般来说,你只需包含uwsgi_params文件 (包含在nginx发行版本中),使用uwsgi_pass指令来设置uWSGI socket的地址。

  1. uwsgi_pass unix:///tmp/uwsgi.sock;
  2. include uwsgi_params;

—— 或者如果你使用的是TCP socket,

  1. uwsgi_pass 127.0.0.1:3031;
  2. include uwsgi_params;

然后,只需重载Nginx,你就准备好了经过Nginx的,由uWSGI驱动的应用。

uwsgi_params 文件是啥?

它就是为了方便,仅此而已!为了让你阅读愉快,自uWSGI 1.3起,该文件的内容是:

  1. uwsgi_param QUERY_STRING $query_string;
  2. uwsgi_param REQUEST_METHOD $request_method;
  3. uwsgi_param CONTENT_TYPE $content_type;
  4. uwsgi_param CONTENT_LENGTH $content_length;
  5. uwsgi_param REQUEST_URI $request_uri;
  6. uwsgi_param PATH_INFO $document_uri;
  7. uwsgi_param DOCUMENT_ROOT $document_root;
  8. uwsgi_param SERVER_PROTOCOL $server_protocol;
  9. uwsgi_param REMOTE_ADDR $remote_addr;
  10. uwsgi_param REMOTE_PORT $remote_port;
  11. uwsgi_param SERVER_ADDR $server_addr;
  12. uwsgi_param SERVER_PORT $server_port;
  13. uwsgi_param SERVER_NAME $server_name;

参见

uwsgi协议魔术变量

集群

对于所有的上游处理程序,Nginx支持漂亮的集群集成。

添加一个 upstream 指令到server配置块外:

  1. upstream uwsgicluster {
  2. server unix:///tmp/uwsgi.sock;
  3. server 192.168.1.235:3031;
  4. server 10.0.0.17:3017;
  5. }

然后修改你的uwsgi_pass指令:

  1. uwsgi_pass uwsgicluster;

这样,你的请求将会在配置的uWSGI服务器之间进行均衡。

动态应用

当传递特殊变量的使用,uWSGI服务器可以按需加载应用。

可以在不传递任何应用配置的情况下启动uWSGI:

  1. ./uwsgi -s /tmp/uwsgi.sock

如果请求设置了 UWSGI_SCRIPT 变量,那么服务器将会加载指定的模块:

  1. location / {
  2. root html;
  3. uwsgi_pass uwsgicluster;
  4. uwsgi_param UWSGI_SCRIPT testapp;
  5. include uwsgi_params;
  6. }

你甚至还可以在每个location内配置多个应用:

  1. location / {
  2. root html;
  3. uwsgi_pass uwsgicluster;
  4. uwsgi_param UWSGI_SCRIPT testapp;
  5. include uwsgi_params;
  6. }
  7.  
  8. location /django {
  9. uwsgi_pass uwsgicluster;
  10. include uwsgi_params;
  11. uwsgi_param UWSGI_SCRIPT django_wsgi;
  12. }

在同一个进程中托管多个应用 (亦称管理SCRIPT_NAME和PATH_INFO)

WSGI标准决定了 SCRIPT_NAME 是一个用来选择特定应用的变量。不幸的是,nginx不能够根据SCRIPT_NAME重写PATH_INFO。出于这样的原因,你需要指示uWSGI在所谓的“挂载点”中映射特定的应用,并且自动重写SCRIPT_NAME和PATH_INFO:

  1. [uwsgi]
  2. socket = 127.0.0.1:3031
  3. ; mount apps
  4. mount = /app1=app1.py
  5. mount = /app2=app2.py
  6. ; rewrite SCRIPT_NAME and PATH_INFO accordingly
  7. manage-script-name = true

考虑到应用本身 (最终使用WSGI/Rack/PSGI中间件) 可以重写SCRIPT_NAME和PATH_INFO。

你也可以使用内部路由子系统来重写请求变量。特别是对于动态应用,这会是一种不错的方法。

注意:古老的uWSGI版本习惯支持所谓的”uwsgi_modifier1 30”方法。不要这样做。它实际上是一种丑陋的hack

SCRIPT_NAME是一个方便的惯例,但是允许你使用任何“映射方法”,例如,可以使用UWSGI_APPID变量在挂载点表中设置一个键。

  1. [uwsgi]
  2. socket = 127.0.0.1:3031
  3. ; mount apps
  4. mount = the_app1=app1.py
  5. mount = the_app2=app2.py

还记得吗,你可以使用nginx变量作为变量值,因此你可以使用Host头来实行某种形式的应用路由:

现在,只需在uWSGI挂载你的应用,将域名作为挂载键

  1. [uwsgi]
  2. socket = 127.0.0.1:3031
  3. ; mount apps
  4. mount = example.com=app1.py
  5. mount = foobar.it=app2.py

静态文件

为了最佳性能和安全性,记得配置Nginx来提供静态文件服务,而不是让你可怜的应用自己来处理它。

uWSGI服务器可以完美提供静态文件服务,但是并不如一个专用的web服务器,例如Nginx,那么快速有效。

例如,可以像这样映射Django的 /media 路径:

  1. location /media {
  2. alias /var/lib/python-support/python2.6/django/contrib/admin/media;
  3. }

只有在请求的文件名不存在的时候,一些应用需要传递控制权给UWSGI服务器:

  1. if (!-f $request_filename) {
  2. uwsgi_pass uwsgicluster;
  3. }

WARNING

如果使用不当,那么像这样的配置可能会引发安全性问题。理智考虑,请务必三番五次检查你的应用文件、配置文件和其他敏感文件位于静态文件的根目录之外。

虚拟主机

你可以使用Nginx虚拟主机,这并无什么特殊问题。

如果你运行“不可信的”web应用 (如果你恰巧是ISP,那么就如你那些客户一样),那么你应该限制它们的内存/地址空间使用,并且对每个主机/应用使用不同的 uid

  1. server {
  2. listen 80;
  3. server_name customersite1.com;
  4. access_log /var/log/customersite1/access_log;
  5. location / {
  6. root /var/www/customersite1;
  7. uwsgi_pass 127.0.0.1:3031;
  8. include uwsgi_params;
  9. }
  10. }
  11.  
  12. server {
  13. listen 80;
  14. server_name customersite2.it;
  15. access_log /var/log/customersite2/access_log;
  16. location / {
  17. root /var/www/customersite2;
  18. uwsgi_pass 127.0.0.1:3032;
  19. include uwsgi_params;
  20. }
  21. }
  22.  
  23. server {
  24. listen 80;
  25. server_name sivusto3.fi;
  26. access_log /var/log/customersite3/access_log;
  27. location / {
  28. root /var/www/customersite3;
  29. uwsgi_pass 127.0.0.1:3033;
  30. include uwsgi_params;
  31. }
  32. }

现在,可以在为每个socket使用不同的uid和受限(如果你想的话)地址空间来运行客户应用 (使用你选择的进程管理器,例如 rc.local, 通过Upstart运行uWSGI, Supervisord 或者任何激起你想象的工具)

  1. uwsgi --uid 1001 -w customer1app --limit-as 128 -p 3 -M -s 127.0.0.1:3031
  2. uwsgi --uid 1002 -w customer2app --limit-as 128 -p 3 -M -s 127.0.0.1:3032
  3. uwsgi --uid 1003 -w django3app --limit-as 96 -p 6 -M -s 127.0.0.1:3033