一、定义
1.uWSGI定义
uWSGI是一个web服务器,实现了WSGI协议,uwsgi协议,http协议等。
uWSGI的主要特点是:
超快的性能(c语言编写)
低内存占用
多app管理
详尽的日志功能(可以用来分析app的性能和瓶颈)
高度可定制(内存大小限制,服务一定次数后重启等
2.uwsgi协议
uwsgi:与WSGI一样是一种通信协议,是uWSGI服务器的独占协议,用于定义传输信息的类型(type of information),每一个uwsgi packet前4byte为传输信息类型的描述,与WSGI协议是两种东西,据说该协议是fcgi协议的10倍快。
nginx 和 uWSGI交互就必须使用同一个协议,uWSGI server支持fastcgi,uwsgi,http协议,这些都是nginx支持的协议,只要大家沟通好使用哪个协议,就可以正常运行了
3.WSGI
WSGI:全称是Web Server Gateway Interface,WSGI是一种规范,描述web server如何与web application通信的规范。
二、结构
1)核心core(实现配置,进程管理,套接字创建,监视,日志记录,共享内存区域,ipc,集群成员资格和uWSGI订阅服务器)
2)请求插件request plugins(实现各种语言和平台的应用服务器接口:WSGI,PSGI,Rack,Lua WSAPI,CGI,PHP,Go …)
3)网关gateway(实现负载平衡器,代理和路由器功能)
4)Emperor(实施大规模实例管理和监控)
5)循环引擎loop engines(实现事件和并发,组件可以在preforking(预分支),线程,异步/事件和绿色线程/协程模式下运行。支持各种技术,包括uGreen,Greenlet,Stackless,Gevent,Coro , AnyEvent,Tornado,Goroutines和纤维)
三、安装和简单使用
安装方法分为官方源构建和模块化构建
需要c语言运行环境(gcc等)
对debian系统:
apt-get install build-essential python-dev
1)Python
pip install uwsgi
简单运行: uwsgi --http :9090 --wsgi-file foobar.py
多线程与多进程: uwsgi --http :9090 --wsgi-file foobar.py --master --processes 4 --threads 2
监控运行状态: uwsgi --http :9090 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191
- 当需要与前置web服务器交互时, uWSGI支持多种协议如HTTP, FastCGI, SCGI,以及专属的uwsgi协议(Nginx支持,Apache多个模块)
在Nginx中的配置:
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:3031;
}
使用uwsgi协议:uwsgi --socket 127.0.0.1:3031 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191
使用HTTP协议:uwsgi --http-socket 127.0.0.1:3031 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191
自动化配置:
1.编写init.d脚本
2.使用进程管理工具supervisor等
3.使用emperor
部署Django:
uwsgi --socket 127.0.0.1:3031 --chdir /home/foobar/myproject/ --wsgi-file myproject/wsgi.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191
或:
[uwsgi]
socket = 127.0.0.1:3031
chdir = /home/foobar/myproject/
wsgi-file = myproject/wsgi.py
processes = 4
threads = 2
stats = 127.0.0.1:9191
运行:uwsgi yourfile.ini
部署flask:
uwsgi --socket 127.0.0.1:3031 --wsgi-file myflaskapp.py --callable app --processes 4 --threads 2 --stats 127.0.0.1:9191
3)注意:
如果以单线程启动uwsgi, 那gil不会启动, web应用中的多线程无效, 避免方法为增加–enable-threads选项 (or enable-threads = true在配置文件中);
在特定的虚拟环境中运行:virtualenv = < path>;
安全:
避免使用root用户运行uWSGI,可以使用uid和gid选项;
使用特权端口(priviledged ports)的特殊选项;shared-socket
设置请求的超时时间harakiri = 30;
–offload-threads < n>选项可以及时释放线程,启动该选项后,将自动检测可优化的所有部件;
- 同时支持多python版本;
make PROFILE=nolang: 构建除Python外的内置默认插件的二进制文件;(在uWSGI源目录下)
构建多个Python版本的插件:
PYTHON=python3.4 ./uwsgi --build-plugin “plugins/python python34”
PYTHON=python2.7 ./uwsgi --build-plugin “plugins/python python27”
PYTHON=python2.6 ./uwsgi --build-plugin “plugins/python python26”
选择对应版本Python:
[uwsgi]
plugins-dir = <path_to_your_plugin_directory>
plugin = python26
四、一些片段
1)uWSGI可以在前端web server不支持的情况下实现对x-sendfile的模拟
2)可以配置实现强制HTTPS
3)实现Python文件的自动重载(当文件发生变更时),仅限开发环境使用;
4)支持全栈cpi设置(对一个 CGI 程序,做的工作其实只有:从环境变量(environment variables)和标准输入(standard input)中读取数据、处理数据、向标准输出(standard output)输出数据。) ???
5) 多个flask app 同时挂载
6) 验证websocket代理 ???
7) 可以适配selinux策略 ???
五、服务管理
1)在系统加载时启动服务:systemd(或者init.d,supervisor等工具)
2) 重启服务:uwsgi --reload /tmp/project-master.pid或者kill -HUP cat /tmp/project-master.pid
可以支持在保留原有socket的情况下重启
3)停止服务:kill -INT cat /tmp/project-master.pid
或者uwsgi --stop /tmp/project-master.pid
六、支持的语言和平台
1)Python
The first available plugin, supports WSGI (PEP 333, PEP 3333), Web3 (from version 0.9.7-dev) and Pump (from 0.9.8.4). Works with Virtualenv, multiple Python interpreters, Python3 and has unique features like Aliasing Python modules, DynamicVirtualenv and uGreen – uWSGI Green Threads. A module exporting handy decorators for the uWSGI API is available in the source distribution. PyPy is supported since 1.3. The Python Tracebacker was added in 1.3。
2)lua
3) perl
4) ruby
平台:Linux 2.6/3.x, FreeBSD等
七、和web server的集成
1)Nginx官方包含uWSGI模块
2)Apache:mod_uwsgi(官方但不太友好),mod_Ruwsgi(友好但官方不支持), mod_proxy_uwsgi(未来方向)
3)tomcat: 包含的servlet可用于将请求从Tomcat转发到uWSGI服务器。 它很稳定,但目前缺乏文档。
八、常见问题
1)优点:uWSGI希望成为一个完整的Web应用程序部署解决方案
如果您正在构建一个需要坚如磐石,快速且易于分发和优化各种负载的应用程序,您很可能会发现自己需要uWSGI。
同时包括以下功能:
ProcessManagement进程管理
Management of long-running tasks管理长期运行的任务
uWSGI RPC Stack
Clustering集群
LoadBalancing负载均衡
Monitoring监控
ResourceLimiting资源控制
2) uwsgi(全部小写)协议源自SCGI,但具有二进制字符串长度表示和4字节头,其包括var块的大小(16位长度)和一些通用字节。
3)支持集群
4)可购买商业服务unbit
5) harakiri模式,定时杀死阻塞时间过长的进程;两种方法
九、注意事项
- 不要将uwsgi协议的socket暴露于公众网络,该协议的本来意图是前置代理服务器, http选项意义为新建一个进程转发一系列请求给worker, 和Nginx是同一级别;http-socket意义为在本地与后端使用http协议;
2)托管多个应用程序使用uWSGI emperor
3)使用sigterm会直接粗暴重启服务; - 使用uwsgi stat server 监控应用状态
5)补充:源码安装的好处:
最大的好处就是可以自行调整编译参数,最大化地定制安装结果
缺少相应模块时会提示:Unavailable modifier requested
6)配置文件支持有限形式的继承,变量,构造和简单循环。
7)要将请求路由到特定插件,Web服务器需要将称为修饰符的幻数传递给uWSGI实例。 默认情况下,此数字设置为0,映射到Python。 例如,将请求路由到PSGI应用程序需要您将修改器设置为5 - 或者可选地将PSGI插件加载为修饰符0.(这将意味着所有无修改器请求都将被视为Perl。
8)设置要使用的进程或线程数没有神奇的规则,它非常依赖于应用程序和系统。 简单数学是不够的。 您需要尝试各种设置,并准备好持续监控您的应用;
9)如果HTTP请求具有正文(如表单生成的POST请求),则必须在应用程序中读取(使用)它。 如果不这样做,与您的网络服务器的socket可能会被破坏。 如果你很懒,你可以使用后缓冲选项,它会自动为你读取数据。 对于Rack应用程序,这将自动启用。
10)要及时监测app的内存使用情况, 使用memory-report 是个不错的选择;
11) 如果您计划使用UNIX套接字(而不是TCP),请记住它们是标准文件系统对象。 这意味着他们拥有权限,因此您的网络服务器必须具有对它们的写入权限。
12)不要以root身份运行uWSGI实例。 您可以以root用户身份启动uWSGI,但请务必使用uid和gid选项删除权限;
13)uWSGI尽可能尝试(ab)使用fork()调用的Copy On Write语义。 默认情况下,它会在加载应用程序之后进行分叉,以尽可能多地共享内存。 如果出于某种原因不希望出现此行为,请使用lazy-apps选项。 这将指示uWSGI在每个worker的fork()之后加载应用程序。 请注意,有一个名为lazy的旧选项更具侵入性,非常不推荐使用(它仍然只是为了向后兼容)???
14)默认Python插件不会初始化gil,如果应用中开启多线程将无法使用,需设置enable-threads选项;在多线程模式下运行uWSGI(使用threads;选项)将自动启用线程支持。 这种“奇怪的”默认行为是出于性能原因; - 如果在请求期间生成新进程,它将继承生成它的worker的文件描述符 - 包括与webserver / router连接的套接字。 如果您不希望此行为设置close-on-exec选项
- 默认情况下,Ruby垃圾收集器配置为在每个请求之后运行。 这是一个积极的策略,可能会减慢你的应用程序的速度 - 但CPU资源比内存便宜,尤其是比内存耗尽更便宜。 要调整此频率,请使用ruby-gc < freq>选项。
17)在OpenBSD,NetBSD和FreeBSD <9上,SysV IPC信号量用作锁定子系统。 这些操作系统倾向于将可分配信号量的数量限制为相当小的值。 如果计划运行多个uWSGI实例,则应提高默认限制。 FreeBSD 9有POSIX信号量,所以你不需要为此烦恼。
18)不要使用与用于构建uWSGI二进制文件本身不同的配置文件来构建插件 - 除非您喜欢痛苦或确切知道您在做什么。 - 默认情况下,uWSGI为每个请求的标头分配一个非常小的缓冲区(4096字节)。 如果您开始在日志中收到“invalid request block size”,则可能意味着您需要更大的缓冲区。 使用buffer-size选项增加它(最多65535)。
- 如果您的(Linux)服务器似乎有很多空闲工作程序,但性能仍然低于标准,您可能需要查看ip_conntrack_max系统变量(/ proc / sys / net / ipv4 / ip_conntrack_max)的值并增加它 看它是否有帮助。
21)一些Linux发行版(阅读:Debian 4 Etch,RHEL / CentOS 5)将更新的内核与非常旧的用户空间混合在一起。 这种组合可以使uWSGI构建系统吐出错误(最值得注意的是在unshare(),pthread锁定,inotify …)。 您可以使用CFLAGS =“ - DOBSOLETE_LINUX_KERNEL”强制uWSGI为旧系统配置自己的前缀’make’(或用于构建它的任何方式)
22)默认情况下,在uWSGI启动时将stdin重新映射到/ dev / null。 如果您需要有效的stdin(用于调试,管道等),请添加–honour-stdin。
23)您可以轻松地将不存在的选项添加到配置文件中(作为占位符,自定义选项或与应用程序相关的配置项)。 这是一个非常方便的功能,但可能导致打字错误。 严格模式(–strict)将禁用此功能,并且只允许有效的uWSGI选项。
24)一些插件(最着名的是Python和Perl)具有代码自动重载功能。 虽然它们听起来很吸引人,但你必须只在开发中使用它们,因为它们非常重量级。 例如,Python -py-autoreload选项将在每个检查周期扫描整个模块树。
25)wsgi.file_wrapper是WSGI标准的优化。 在某些极端情况下,它可能会引发错误。 例如,在Python 3.5中返回内存中的字节缓冲区(io.Bytesio)时。您可以通过将选项wsgi-disable-file-wrapper设置为true来禁用它。
十、配置
1)两种配置方法,命令行和配置文件形式
2)加载4种不同格式的配置文件:
uwsgi --ini http://uwsgi.it/configs/myapp.ini # HTTP
uwsgi --xml - # standard input
uwsgi --yaml fd://0 # file descriptor
uwsgi --json ‘exec://nc 192.168.11.2:33000’ # arbitrary executable
3)magic变量:
百分号加字母表示
请注意,其中大多数引用它们出现的文件,即使该文件包含在另一个文件中也是如此。
大多数大写版本都是一个例外,它引用了第一个加载的非模板配置文件。 这意味着第一个配置文件未通过–include或–inherit加载,而是通过例如–ini, - yaml或–config加载。 这些旨在与皇帝一起使用,以引用实际的vassal配置文件,而不是–vassals-include或–vassals-inherit包含的模板。
4)placeholders
placeholders是在配置时定义的自定义magic变量,方法是设置您自己设计的新配置变量。
; These are placeholders...
my_funny_domain = uwsgi.it
set-ph = max_customer_address_space=64
set-placeholder = customers_base_dir=/var/www
; And these aren't.
socket = /tmp/sockets/%(my_funny_domain).sock
chdir = %(customers_base_dir)/%(my_funny_domain)
limit-as = %(max_customer_address_space)
访问方式:
import uwsgi
print uwsgi.opt[‘customers_base_dir’]
类似地,可以使用$(ENV_VAR)和@(file_name)语法包含环境变量和外部文本文件的内容;
5)placeholder使用数学
total = %(foo + bar + 3)
bar = %(foo bar ++) 无运算符连接时按字符串拼接;
6)使用@符号加载文件
7)当作为环境变量传递时,选项大写并以UWSGI_为前缀,并且破折号用下划线代替。
8)可以加载不同section的配置内容:uwsgi --ini myconf.ini:app1
9)配置文件也可以写为xml, json,ldap, sqlite等格式;
10)后备配置(fallback config):
需要恢复出厂设置或配置出错时使用,使用方式:
uwsgi --fallback-config safe.ini --uid 1000 --http-socket :80
加载备用应用程序:uwsgi --fallback-config safe.ini --need-app --http-socket :8080 --wsgi-file brokenapp.py
注意:
可以有多次回调配置,但注意不要形成死循环;
尝试在配置树中尽快放置-fallback-config。 在注册回退文件之前,各种配置解析器可能会失败(调用exit(1))
11)配置逻辑:
可以使用一些简单的逻辑,并使用%(_)
例如:for … endfor
if-dir / if-not-dir如果存在并且是目录
if-env / if-not-env 如果环境变量已定义
if-exists / if-not-exists 如果文件或目录存在
if-file / if-not-file 如果存在并且是文件
if-opt / if-not-opt如果选项被设置或设置为相应值;
注意:
只有显性设置的选项有效, 隐性默认值无效;
只有在if-opt前设置的选项有效,包括include, 不包括inherit;
if-opt解析在扩展magic变量之前,扩展placeholder和其他变量之后,所以如果用if-opt比较选项的值,确保填入的是magic变量;
如果某个选项设置了多次,只有第一次会被if-opt识别;
if-reload / if-not-reload
十一、配置选项
后续补充;
十二、自定义配置
–declare-option
十三、配置解析原理
十四、uwsgi协议变量
您可以使用Web服务器传递的特殊变量(或通常由符合uwsgi的客户端)动态调整或配置uWSGI服务器的各个方面;
对Nginx来说: uwsgi_param < name> < value>格式
十五、uwsgi协议
是一种可以携带任何类型数据的二进制协议。 uwsgi数据包的前4个字节描述数据包包含的数据类型。
每个uwsgi请求都以uwsgi格式生成响应。
即使Web服务器处理程序也遵守此规则,因为HTTP响应是有效的uwsgi数据包(请看modifier1 = 72)
该协议主要通过TCP工作,但主进程可以绑定到嵌入式SNMP服务器或集群管理/消息传递请求的UDP单播/多播。
uwsgi packet header组成:8bit modifier 1;16bit datasize; 8bit modifier2;
uwsgi vars:
十六、管理外部服务
三种方式:
–attach-daemon – directly attached non daemonized processes
–smart-attach-daemon – pidfile governed (both foreground and daemonized)
–smart-attach-daemon2 – pidfile governed with daemonization management
第一种:第一个类别允许您直接将进程附加到uWSGI主服务器。 当主设备死亡或重新加载时,这些过程将被破坏。 对于必须在重新启动应用程序时刷新的服务,这是最佳选择。
第二种:只要Pidfile可用并且其中包含的pid与正在运行的pid匹配,Pidfile管理的进程就可以在主服务器的死亡或重新加载后继续存在。 对于需要更长持久性的进程而言,这是最佳选择,而残酷杀戮可能意味着丢失数据(如数据库)。
第三种:最后一类是第二类的超集。 如果您的进程不支持守护进程或写入pidfile,您可以让主进程进行管理。 很少有守护进程/应用程序需要此功能,但它可能对微小的原型应用程序或设计不佳的应用程序非常有用。
军团支持:
从uWSGI 1.9.9开始,可以使用uWSGI Legion子系统子系统进行守护程序管理。 军团守护进程将仅在军团领主节点上执行,因此每个军团中始终会运行一个守护进程实例。 一旦主死了,守护进程将在另一个节点上产生。 要添加军团守护程序,请使用-legion-attach-daemon,-legion-smart-attach-daemon和-legion-smart-attach-daemon2选项,它们具有与普通守护程序选项相同的语法。 不同之处在于需要添加军团名称作为第一个参数。
通常,您使用UNIX信号来管理主服务器,但是我们的信号数量不足,而且(更重要的是)不需要乱用PID会大大简化外部管理脚本的实现。
因此,您可以告诉主服务器创建可用于向主服务器发出命令的UNIX命名管道(FIFO),而不是信号。
十七、master FIFO
使用命名管道来管理主进程;
通常,您使用UNIX信号来管理主服务器,但是我们的信号数量不足,而且(更重要的是)不需要乱用PID会大大简化外部管理脚本的实现。
十八、Inetd和Xinetd
Inetd和Xinetd是两个用于按需启动网络进程的守护进程。 您也可以在uWSGI中使用它。
十九、使用upstart 启动uwsgi
1)Upstart 跟Sysvinit 本质上一样,都是用于linux开机自动启动某些后台服务,同时还承担监控这些服务运行状态的功能。
他是声明性的配置文件而不是shell脚本;
2)更好的方法是通过upstart启动emperor, emperor来做其他的事, 如果您想在主进程下运行Emperor(用于访问高级功能),请记住添加-die-on-term
默认情况下,uWSGI将SIGTERM信号映射到“粗鲁的重新加载过程”。
但是,Upstart使用SIGTERM来完全关闭进程。 die-on-term将SIGTERM和SIGQUIT的含义反转。
第一个将关闭整个堆栈,第二个将粗鲁地重新加载它。
3)通过socket激发启动,当客户端第一次连接到某个特定的socket时启动服务;
二十、通过systemd启动
需配置systemd文件;
One approach to integrate uWSGI apps with your init system is using the Emperor.
Your init system will talk only with the Emperor that will rule all of the apps itself.
Create a systemd service file (you can save it as /etc/systemd/system/emperor.uwsgi.service)
如果你想允许每个vassal在不同的权限下运行,请从emperor配置中删除uid和gid选项(请阅读Emperor文档!)
使用之前的服务文件,所有Emperor消息都将转到syslog。 您可以通过删除StandardError = syslog指令来避免它。
如果这样做,请确保在Emperor配置中设置–logto选项,否则所有日志都将丢失!
systemd也可以启动单个app
二十一、通过circus启动
二十二、uwsgi中嵌入应用
这些可以是任何文件类型,包括配置文件。 您也可以嵌入目录,因此通过挂钩Python模块加载器,您也可以透明地导入包。 在这个例子中,我们将嵌入一个完整的Flask项目。
二十三、日志系统
uWSGI中最基本的日志记录形式是将请求,错误和信息性消息写入stdout / stderr。 这在默认配置中发生。 最基本的日志重定向形式是–logto / --logto2 / --daemonize选项,允许您将日志重定向到文件。
1)将日志写入文件
./uwsgi -s :3031 -w simple_app --daemonize /tmp/mylog.log
./uwsgi -s :3031 -w simple_app --logto /tmp/mylog.log
#logto2 only opens the log file after privileges have been dropped to the specified uid/gid.
./uwsgi -s :3031 -w simple_app --uid 1001 --gid 1002 --logto2 /tmp/mylog.log
2)udp日志
使用UDP日志记录,您可以集中日志记录或将日志持久性重定向到另一台计算机以卸载磁盘I / O. UDP日志记录在守护程序和交互模式下均可使用。 UDP记录操作处于连接套接字模式,因此在uWSGI启动之前UDP服务器必须可用。 有关更原始的方法(在未连接模式下工作),请参阅有关套接字日志记录的部分。
第二种方式更有用,因为它将打印每条消息的源(ip:端口)。 如果多个uWSGI服务器在同一个UDP服务器上登录,它将允许您从另一个服务器识别一个服务器。 当然,您可以编写自己的应用程序来管理/过滤/保存通过udp接收的日志;
3)可插拔日志记录器
uWSGI还支持可插拔记录器,使您可以更灵活地记录记录的位置和内容。 根据uWSGI版本的配置,某些记录器可能可用,也可能不可用。 有些可能需要作为插件加载。 要找出构建中可用的插件,请使用–logger-list调用uWSGI。 要设置可插入记录器,请使用–logger或–req-logger选项。 --logger将为每条消息设置一个记录器,而–req-logger将为请求信息消息设置记录器。
3.1)日志路由
默认情况下,所有日志行都将发送到所有已声明的记录器。 如果这不是您想要的,您可以使用–log-route(和–log-req-route for request loggers)来指定正则表达式,以将某些日志消息路由到不同的目标。
3.2)logger 到文件
3.3) logger到socket
3.4)logger到syslog
3.5) logger到Redis
3.6)logger到MongoDB
3.7) logger到zeromq
3.8) logger可以加密
4)日志格式化 --logformat选项
5)log encoder对日志编码
二十四、hook, 覆盖worker, 第三方插件
可以使用hook改变uwsgi的内部行为
两种钩子,硬编码钩子和高级钩子
二十五、关于缓存
这是使用 uWSGI内部路由, uWSGI缓存框架 和 uWSGI转换 的各种缓存技术的烹饪指南。
使用psgi,router_cache插件
通过配置文件的设置来缓存响应内容, 提升速度, 可以设置缓存数和缓存大小;
可以建立多个缓存, 并且设置过期时间;
可以建立gzip版本的缓存;
可以缓存静态文件;
还可以按不同用户存储缓存;
可以将缓存写到静态文件;
二十六、对于Django的部署
1.流程
the web client <-> the web server <-> the socket <-> uWSGI <-> Django
emperor模式:每当修改配置文件时,皇帝都会自动重启附庸。
设置系统启动:编辑/etc/rc.local 文件
二十七、dreamhost,heroku, fuse,使用rpc和内部路由构建一个动态代理, 设置graphite;
二十八、解决惊群效应(thundering herd)
二十九、重载问题
1.当前进程fork()一个子进程,子进程继承所有socket,后续socket放入队列, 这样确保可以建立连接,只是第一个请求响应会慢些
2.如果当前正在处理请求,则继续处理,但有默认60秒的超时时间
但缺陷在于有时重载的时间很慢,容易发生错误,解决方式之一为调整监听队列的最大值,默认为100,当然同时需要调整系统的最大值;还可以调整proxy timeouts(connect)
还有一系列方式实现重载的优化
三十、offloading websocket
三十一、报警子系统
分为两个组件: event monitor, event action
可以定义多个监控器:
log-alarm 在指定的正则表达式匹配到一个日志行的时候,触发一个告警
alarm-fd 在指定的文件描述符准备好的时候,触发一个告警(这是这相当底层,并且是大多数告警插件的基础)
alarm-backlog 在socket backlog队列满的时候,触发一个告警
alarm-segfault (自1.9.9起) 在uWSGI出现段错误的时候触发一个告警
alarm-cheap 为每个基于curl的告警使用主要的告警线程,而不是创建专用线程
定义多个报警:
‘cmd’ - 运行一个命令,将日志行传递给标准输入(stdin)
‘signal’ - 生成一个uWSGI信号
‘mule’ - 发送日志行给一个mule
‘curl’ - 传递一个日志行给一个curl url (支持http,https和smtp)
‘xmpp’ - 通过XMPP/jabber发送日志行
三十二、缓存框架
uWSGI包含了一个非常快速、全内存访问、零IPC、SMP安全、不断优化、高度可调的、键值存储的简单的“缓存框架”。单个uWSGI实例可以使用不同的设置,出于不同的目的,创建无限个不同的“缓存”。
三十三、定时任务接口,类似cron
通过uWSGI API,在这种情况下,cron事件将会生成uWSGI信号
直接通过选项,在这种情况下,事件将会运行shell命令
三十四、fastrouter
fastrouter”插件,它是一个代理/负载均衡器/路由器,使用uwsgi协议。默认内建。你可以将其放在你的web服务器和真正的uWSGI实例之间,以获取对于HTTP请求到你的应用服务器的路由的更多控制。
三十五、内部路由internal routing
1)特点:快
可以通过内部路由系统来动态改变请求的处理方式;
uwsgi在请求周期内,会经过几个不同的路由链, 每个路由链都有一个路由表;
2)路由链的默认顺序:
request 在请求被传递给插件之前应用
error 一个生成了一个HTTP状态码就会被立即应用(递归链)
response 在生成了最后一个响应头后被应用 (仅在发送响应体之前)
final 在已经发送响应到客户端之后被应用;
request 链是 (为了方便起见) 是“默认的”链,因此它的选项没有前缀,而其他的链需要前缀。
route-user-agent -> 用于request链;
response-route-uri -> 用于response链;
3)路由表:
内部路由表是一个接一个(也允许向前跳跃)执行的“规则”序列。每个规则由一个’‘subject(标题)’‘,一个’‘condition(条件)’‘和一个’‘action(动作)’‘组成。’‘条件’‘通常是一个应用到标题的PCRE正则表达式:如果匹配上了,那么就会触发相应的动作。标题是请求的变量。
subject
condition
action的返回值: next, goto, break, continue
4)你可以使用$ {VAR}语法来访问请求变量 (PATH_INFO, SCRIPT_NAME, REQUEST_METHOD…)
5)你可以使用$ {cookie[name]}语法来访问一个cookie值;
6)你可以使用$ {qs[name]}语法访问HTTP请求字符串的值;
7)其他路由变量: mime, time, httptime等;
8)为什么不单单使用route-if:
这是个好问题。你只需要一直记住,uWSGI是关于通用性和 性能 的。可以循环利用总是好的。 --route-if 选项,虽然通用,但是不能够被优化,因为在处理每一个请求的时候都必须重新计算它所有的部分。这显然非常快,但是 --route-uri 选项 (和其他小伙伴)可以被预先优化 (在启动期间) 来直接映射到请求内存区域,因此,如果你可以使用它们,那么你绝对应该用它们。
9)利用goto来跳转路由表;
10)收集响应头;
11)各种actions
三十六、legion子系统
一个用于集群的新的子系统:Legion子系统。一个Legion是一组不断争取主导的uWSGI节点。每个节点都有一个武力值 (如果可能的话,彼此间该值不同)。具有最高武力值的节点就是这个Legion的Lord (或者如果你喜欢不大游戏的说法,嗯,更工程师点的术语是:master)。这种不断的斗争会生成7种事件:
setup - legion子系统在一个节点上启动的时候
join - 在第一次到达仲裁时,只有在新加入的节点上
lord - 当该节点成为lord
unlord - 当这个节点失去了lord称号
death - 当legion子系统关闭的时候
node-joined - 当任何新节点加入到我们的legion的时候
node-left - 当任何节点离开我们的legion的时候
三十六、锁机制
uWSGI支持一系列的锁来同步进程
三十七、mules
Mule是活在uWSGI栈中的worker进程,但通过socket连接是不能访问的,它可以作为一种通用子系统使用,以卸载任务。你可以将它们看成一个比较原始的 spooler。
它们可以访问整个 uWSGI API,可以管理信号,并且可以通过一个简单的基于字符串的消息系统来进行通信。
两种模式:
signal和programmed
???完全不知道干嘛的
三十八、offloading子系统
卸载是一种优化小任务的方式,将它们委托给一个或多个线程。
这些线程在非阻塞/事件触发的方式中运行这样的任务,允许大量的并发。
uWSGI栈的各种组件是卸载友好型的,而长期目标是允许应用代码随意使用它们。
要启动卸载子系统,仅需添加–offload-threads < n>,其中< n>是要生成的线程数 (每个worker)。 它们是原生线程,无锁(无共享资源),无惊群效应(到该系统的请求会进行轮询),并且它们是任意使用你的CPU核心的最佳方式。
统计信息子系统的”offloaded_requests”度量中计算了卸载请求的数量。
可以卸载静态文件
可以卸载内部路由
可以卸载缓存
三十九、队列框架
在低层次,它是一个简单的基于块的共享数组,有两个可选的计数器,一个用于对于堆栈式,LIFO,另一个用于FIFO。
数组是环形的,因此,当两个指针的任意一个到达了尾部(或者首部),它会被重置。记住这点!
要启用队列,则使用 queue 选项。默认情况下,队列块是8KiB。使用 queue-blocksize 来修改其大小。
可以用作共享数组, 共享栈或共享队列
四十、RPC stack子系统
uWSGI包含了一个快速、简单、平稳跨平台的RPC栈。
虽然,你或许会爱上这个子系统,但是,答应我,只在你需要的时候才用它,好吗?对于绝大部分常见,有大量更适合的高层次RPC技术可以用。
也就是说,uWSGI RPC子系统闪光点在于它的性能和内存使用。例如,如果你需要将一个请求的负载拆分到多个服务器上,那么uWSGI RPC是个不错的选择,因为它允许你不怎么费力就可以卸载任务。
它最大的限制在于它的“无类型”方法。
RPC函数可以接收多达254个参数。每个参数必须是一个字符串,最大大小为16位 (65535字节),而返回值必须是一个字符串 (这次是64位,所以这不是一个实际的限制)。
四十一、sharedarea子系统
SharedArea是一种非常底层的机制。想要一个更易于使用的替代品,可以看看 Caching 和 Queue 框架。
sharedarea子系统允许你以一种非常快速(安全)的方式,在你的uWSGI组件(worker, spooler, mule等等)之间共享内存页。
与较高层次的 caching framework 相比,sharedarea操作是一种更快的方式 (单一的拷贝,而不是如缓存所需的那样要进行双重拷贝),并且它为特定的需求提供不同的优化。
每一个共享区域 (是哒,你可以拥有多个区域) 都有一个大小 (一般根据页面数指定),因此,如果你在拥有4 KiB页面的系统上需要一个8 KiB的共享区域,那么你会使用 sharedarea=2 。
共享区域子系统是完全线程安全的。
四十二、信号子系统
随着时间的推移,你的uWSGI堆栈越来越大,你添加spooler,更多的进程,更多的插件,等等。你添加的功能越多,你就越需要所有这些组件之间能彼此通信。
现今丰富/高级的web应用的另一个重要任务是响应不同事件。一个事件可能是一个文件修改,一个新的集群节点冒出来,另一个(黯然死去,一个定时器时间已经到了……任何你能想象到的事件。
通信和事件管理都由相同的子系统管理 —— uWSGI信号框架。
uWSGI信号是由socket管理的,因此它们 够可靠 。当你发送一个uWSGI信号时,你可以保证它会被转发。
uWSGI信号最有用的特性是,它们可以用于宣布外部事件。
编写可用外部事件的时机是:
文件系统修改
timer/rb_timer
cron
四十三、spooler子系统
Spooler是内置于uWSGI的队列管理器,它的工作方式像打印/邮件系统。
你可以排队大量的邮件发送、图像处理、视频编码等等,并且让spooler在后台为你努力工作,同时用户的请求会被正常的worker处理。
spooler通过定义”spooler文件”将会写入的目录来工作,每次spooler在它的目录下找到一个文件,它就会解析它,然后运行一个特定的函数。
你可以让多个spooler映射到不同的目录,甚至可以让多个spooler映射到相同的目录。
四十四、订阅服务器子系统
uWSGI栈的一些部分要求有一个键值映射系统。
例如, uWSGI FastRouter 需要知道对于一个特定的请求,要联系哪个服务器。
在拥有大量的节点的大网络中,手工管理这些配置可能就是地狱般可怕。uWSGI实现了一个订阅系统,其中,节点本身向订阅服务器宣告它的存在,这将反过来填入它们的内部字典。
四十五、serve静态文件
1)模式1:在传递请求给你的应用之前检查静态资源
在web应用中管理静态文件是一种相当常见的方式。诸如Ruby on Rails这样的关键和许多PHP应用已使用这种方法好多年了。
假设你的静态资产位于 /customers/foobar/app001/public 之下。你想要在传递请求给你的动态应用之前检查在那个目录下请求都有一个对应的文件。 --check-static 选项就是为你而设的;
2)模式2:信任前端DOCUMENT_ROOT
如果你的前端 (一个web服务器,一个uWSGI核心路由器……) 设置了 DOCUMENT_ROOT 值,那么你可以使用 --check-static-docroot 选项,指示uWSGI将其作为一个检查静态文件的有效目录。
3)模式3:使用静态文件挂载点
一个更一般的方法是“映射”指定请求前缀到你的文件系统上的物理目录。–static-map mountpoint=path
4)模式4:使用高级内部路由
当映射不够的时候,高级内部路由 (自1.9起可用) 将是你最后的手段。
多亏了强大的正则表达式,你将能够构建非常复杂的映射。
5)设置首页
默认情况下,对“目录” (例如/或者/foo)的请求会被跳过 (如果未使用高级内部路由)。
如果你想要映射指定文件到一个“目录”请求 (如久负盛名的index.html) ,那么仅需使用 --static-index 选项。
6)MIME类型
你的对静态文件的HTTP/SPDY/随便什么响应应该总是返回特定文件正确的mime类型,从而让用户代理正确地处理它们。
默认情况下,uWSGI从 /etc/mime.types 文件构建它的MIME类型列表。你可以使用 --mime-file 选项加载额外的文件。
7)设置Expires头部
当提供静态文件的时候,尽情使用客户端浏览器缓存是明智之选。默认情况下,uWSGI会添加一个 Last-Modified 头部到所有的静态响应中,并且将遵循 If-Modified-Since 请求头部。
这对于高流量站点或许不够。你可以使用以下选项之一来添加自动 Expires 头部;
8)传输模式
如果你开发了一个异步/非阻塞应用,那么直接从uWSGI提供静态文件就不是一个大问题。
所有的传输都是以异步方式进行管理的,因此在此期间,你的应用都不会阻塞。
在多进程/多线程模式下,你的进程(或者线程)将会在文件的整个传输期间阻塞。
对于较小的文件,这不是个问题,但是对于较大的,将它们的传输卸载到其他什么的会是一个不错的想法。
你有多种方式做到这点:
1.X-Sendfile
使用这个,uWSGI将只会生成响应头,并且将会委托web服务器传输物理文件。
2.X-Accel-Redirect
目前(2013年1月)只有Nginx支持。与X-Sendfile的工作方式相同,唯一的区别在于选项参数。
3.卸载offloading
如果你的前端服务器不能访问静态文件的话,这是最好的方法。它使用 uWSGI 卸载(offloading)子系统 来委托文件传输给非阻塞线程池。
4.GZIP
许多用户/系统管理员低估了即使Gzip编码的CPU影响。
虽然uWSGI能够即时压缩内容 (例如,这用于HTTP/HTTPS/SPDY路由器),但是提供gzip压缩的静态文件最好的方法是“手动” (但请使用脚本,而不是让实习生来做这件事) 生成它们,然后让uWSGI选择每次最好提供压缩的还是未压缩的。
用这种方式,提供gzip内容将与提供标准静态文件 (sendfile, 卸载……) 没啥区别;
5.safe
每一个静态映射都将完整转换成“正在的”路径 (因此也会转换符号链接)。
如果结果路径并不位于选项中指定的路径下,那么将会触发一个安全性错误,并且拒绝该请求。
如果你信任你的UNIX技能,并且知道你在做什么,那么你可以添加“安全”路径列表。如果一个转换路径并不位于一个配置目录下,但位于一个安全路径下,那么仍然会提供。
6.缓存路径映射/解析
静态文件服务的瓶颈之一是恒定大量的 stat() 系统调用。
你可以使用uWSGI缓存系统来存储从URI到文件系统路径的映射; --static-cache-paths 30
7.在缓存中存储静态文件
你可以使用选项 --load-file-in-cache < filename> (可以多次指定它) 在启动期间直接把一个静态文件存储到uWSGI缓存中。该文件的内容将会被存储在键< filename>之下。
所以请注意 —— load-file-in-cache ./foo.png 将会把这个项作为 ./foo.png 存储,而非它的完整路径。
四十六、服务器名称识别子系统
uWSGI 1.9 (代号为”ssl as p0rn”) 添加了对SNI (服务器名称识别,Server Name Identification) 的支持,贯穿整个SSL子系统。HTTPS路由器,SPDY路由器和SSL路由器都可以透明使用它。
SNI是SSL标准的一个扩展,它允许客户端为它想要的资源指定一个“名字”。名字通常是请求主机名,因此你可以像使用HTTP Host: 头部那样实现类虚拟主机行为,而无需而外的IP地址等。
???
四十七、GeoIP插件
geoip 插件添加新的路由变量到你的内部路由子系统中。 GeoIP变量前缀为”geoip”标签。要构建geoip插件,你需要官方的GeoIP C库和它的头文件。支持的数据库是country和city,它们会在启动的时候完全加载到内存中。
???
四十八、uWSGI转换
一个转换就像是一个应用到由你的应用生成的响应上的过滤器。
转换可以是链式的 (一个转换的输出将会是接下来的转换的输入) ,并且可以完全覆盖响应头。
转换最常见的例子是gzip编码。你的应用的输出被传递到一个用gzip压缩它并且设置Content-Encoding头的函数中。这个特性依赖2个外部包:libpcre3-dev, Ubuntu上的libz-dev。
每个转换宣告自己是一个“流”,还是一个“缓冲”。
如果你整个管道是只由“流”转换组成的,那么你的客户端将会按块接收输出。另一方面,单个缓冲转换会让整个管道缓冲,因此,你的客户端只会在最后获得输出。
四十九、websocket支持
虽然对于WebSockets,存在许多不同的解决方案,但是其中大多数依赖于更高级的语言实现,对于诸如游戏或者流这样的主题很少有足够好的。
1)自动握手
2)send:uwsgi.websocket_send(msg)
3)receive:msg = uwsgi.websocket_recv(), 非阻塞:msg = uwsgi.websocket_recv_nb()
4)ping/pong机制:
要保持一个websocket连接打开,你应该不断发送ping (或者pong,见下文) 到浏览器,并期望它响应。如果来自浏览器/客户端的响应不及时到达,那么就会关闭连接 (uwsgi.websocket_recv() 将会引发一个异常)。除了ping之外, uwsgi.websocket_recv() 函数发送所谓的 ‘无偿pong’。它们被用来通知客户端服务端可用。
5)可用代理/server
不幸的是,并非所有的HTTP web服务器/代理都与websockets工作得很好。
uWSGI HTTP/HTTPS/SPDY路由器完美支持它们。只需记得添加 --http-websockets 选项。
uwsgi --http :8080 --http-websockets --wsgi-file myapp.py
或者
uwsgi --http :8080 --http-raw-body --wsgi-file myapp.py
这有点更“原始”,但支持诸如块输入这样的东东。
Haproxy正常工作。
nginx >= 1.4 正常工作,并且无需额外的配置。
6)http代理内部路由器直接支持websocket (假设你的前线代理已经支持它们了)
五十、Metrics子系统
uWSGI度量子系统让你可以管理来自应用的“数字”。
虽然在1.9开发周期内,缓存子系统获得了一些计算能力,但是度量子系统在设计上进行了优化,以存储数字并在其上应用函数。因此,与缓存子系统相比,它是一种更快的方式,并且需要消耗一小部分内存。
在启用后,度量子系统配置了大量的度量 (例如每核请求,内存使用,等等) ,但是,除此之外,你可以配置自己的度量,例如活跃用户数,或者,比方说,特定URL的访问数,以及应用或整个服务器的内存消耗。
要启用度量子系统,只需添加 --enable-metrics 到选项中,或者配置一个统计数据推送器 (见下)。
度量子系统是完全线程安全的。
默认情况下,uWSGI会创建许多度量 (大部分是已经已计划的),因此,在添加你自己的度量之前,确保uWSGI并没有公开你所需要的度量。
1)度量名和oid
每个度量都必须要有一个名字 (只包含数字、字母、下划线、破折号和点) 和一个可选的 oid (用于映射一个度量到 内嵌SNMP服务器)。
2)度量类型metric types
在处理度量之前,你需要了解每个度量表示的各种类型:
COUNTER (type 0)
这是一个一般增长的数字 (如请求数)。
GAUGE (type 1)
这是一个可以动态增长或减少的数字 (如worker的使用内存,或者CPU负载)。
ABSOLUTE (type 2)
这是一个绝对数字,如整个服务器的内存,或者磁盘的大小。
ALIAS (type 3)
这是一个指向另一个度量的虚拟度量。你可以用它来为已存在的度量赋予不同的名字。
3)Metric collectors
一旦你定义了一个度量类型,那么你需要告诉uWSGI如何“收集”特定的度量。
有各种可用的收集器 (可以通过插件添加更多收集器)。
ptr – 该值是从内存指针收集来的
file – 该值是从文件收集来的
sum – 该值是其他度量的总和
avg – 计算孩子的算术平均值 (在1.9.20中添加)
accumulator – 总是增加孩子的值的总和到最后的值。看看下面这个例子。
Round 1: child1 = 22, child2 = 17 -> metric_value = 39 Round 2: child1 = 26, child2 = 30 -> metric_value += 56
multiplier - 用指定的参数 (arg1n) 乘以孩子的值的总和。
child1 = 22, child2 = 17, arg1n = 3 -> metric_value = (22+17)*3
func - 每次调用指定的函数计算该值。
manual - NULL收集器。必须使用度量API,从应用手动更新该值。
4)自定义metrics
5)度量目录
度量子系统可以将它所有的度量,以文本文件的形式公开到一个目录中: uwsgi --metrics-dir mymetrics
6)恢复度量(持久化度量)
当你重启一个uWSGI实例的时候,会重置它所有的度量。
这一般是最好的,但如果你想要,你可以使用之前存储在定义的度量目录中的值来恢复先前的状态。
只需增加 --metrics-dir-restore 选项,来强制度量子系统在开始收集值之前,从度量目录读回度量值。
7)api
metric_get(name)等。。。
8)统计信息推送器
可以将已收集的度量发送到外部系统,用于分析或者图表生成。
统计信息推送器是旨在发送度量给那些系统的插件。
目前,有两种类型的统计信息推送器:JSON和raw
JSON统计信息推送器发送整个JSON统计信息块 (与你从统计信息服务器获取的相同),而’raw’则户发送度量列表。
目前可用的统计信息推送器:rrdtool, statsd, carbon, zabbix, mongodb, file, socket,
9)告警/阈值
你可以为每个度量配置一个或多个“阈值”。
一旦到达了这个限制,那么就会触发指定的告警 (见 uWSGI告警子系统 (自1.3起))。
一旦传递了该告警,你可以选择重置计数器为一个指定的值 (一般是0),或者继续以特定的比率触发告警。
10)SNMP集成
内嵌SNMP服务器 服务器从1.3.6.1.4.1.35156.17.3 OID开始,公开了度量。
11)内部路由集成
‘’router_metrics’’ 插件 (默认内置) 添加了一系列的动作到内部路由子系统。
12)请求日志记录
你可以使用 %(metric.xxx) 占位符,在你的请求日志格式中访问度量值;
13)官方已注册度量
五十一、块输入API
已在uWSGI 1.9.13中添加了一个用于管理HTTP块输入请求的API。
这个API是非常低层次的,允许与标准的应用进行集成。
???
五十二、uWSGI cheaper子系统 —— 适应性进程生成
五十三、Emperor —— 多应用部署
五十四、利用Broodlord模式实现自动伸缩
Broodlord (来自于Starcraft,就像 Zerg模式 模式) 是vassal向Emperor请求“加固”的方式。“加固”是按需生成新的vassal,一般会绑定到同一个socket上。单独的Broodlord模式并不是那么有用。但是,当与 Zerg模式, Idle 和 uWSGI Emperor —— 多应用部署 组合在一起,它可以被用来实现你的应用的自动伸缩。
五十五、zerg模式
当你的站点负载时可变的时候,能够动态添加worker将会是不错的
显然,你可以编辑你的配置,增加 workers ,然后重载你的uWSGI实例,但是对于负载很多的应用而言,这是不可取的,并且老实说 —— 谁会想要做那样的手工活来扩展应用呢?
启用Zerg模式,你可以允许”uwsgi-zerg”实例附加到你已经运行的服务器上,然后在工作中帮助它。
Zerg模式显然只能用于本地。你不能用它来添加远程实例 —— 这个工作已经由 uWSGI FastRouter , HTTP plugin 或者你的web服务器的负载均衡器更好地完成了。
1)启用zerg服务器
2)附加zerg到zerg服务器
3)在zerg服务器不可用的时候回退
4)将Zerg当成测试器使用
你可以用的一个不错的技巧是,用 SIGTSTP 信号挂起主要的实例,然后在Zerg中加载你的应用的一个新的版本。如果代码不能用,那么你可以简单关闭掉这个Zerg,然后恢复主要的实例。
5)Zerg池
Zerg池是特殊的Zerg服务器,只对Zerg客户端提供服务,仅此而已。
你可以用它们来构建高可用性的系统,减少测试/重载期间的挂机时间。
五十六、动态添加应用
注意:这并不是托管多个应用的最好的方法。你最好为每个应用运行一个uWSGI实例。
你可以在没有配置应用的情况下启动uWSGI服务器。
五十七、扩展SSL连接
???
五十八、设置POSIX capabilities (指定个别权限)
POSIX capabilities 允许为进程细化权限。除了标准的UNIX权限方案之外,它们为系统资源定义了新的一组权限。要启用capabilities支持 (仅Linux),构建uWSGI之前,你必须安装 libcap 头文件 (在基于Debian的发行版上,则是 libcap-dev )。像往常一样,在 setuid 调用之后,你的进程将会失去几乎所有的capabilities。uWSGI的 cap 选项允许你定义一个通过调用保持的capabilities列表。
例如,要允许你的非特权应用绑定到特权端口,并且设置系统时钟,你将使用以下选项。
五十九、在Linux CGroup中运行uWSGI
要使用cgroup,uWSGI必须作为root运行。 uid 和 gid 是非常非常必要的。
六十、在uWSGI中使用Linux KSM
Kernel Samepage Merging 是Linux 内核 >= 2.6.32 的一个特性,允许进程共享具有相同内容的内存页。这是由一个内核守护进程周期性执行扫描,对比,以及在可能的情况下,对特定内存区域进行合并来完成的。如果你幸运的话,使用KSM可能会成倍减少你的uWSGI实例的内存使用。特别是在大量的 Emperor 部署中:为每个vassal启用KSM可能会节省大量的内存。
启动: echo 1 > /sys/kernel/mm/ksm/run
KSM是一个可选功能,必须由进程明确要求,因此只是启用KSM将不会拯救你的机器上的一切东西。
六十一、使用Linux名字空间监禁(jailing)你的应用
Linux将这个概念扩展到了其他OS层 (PID, user, IPC, 网络等等。),因此,特定的进程可以存活在一个“虚拟操作系统”中,它均有一组新的pid,一组新的用户,一个完全不共享的IPC系统 (信号量,贡献内存等等。),专用网络接口及其自身的主机名。
除了为新的进程创建新的名字空间,你还可以使用 setns() 调用附加到已经运行的(名字空间)。
为什么不使用lxc?
LXC (LinuX Containers)是一个允许你使用Linux名字空间构建完整子系统的项目。你可能会问,既然LXC实现了一个完整的“虚拟”系统,那么为什么还要“另起炉灶”。风马牛不相及……
LXC的目标是提供用户一个虚拟服务器视图。uWSGI的名字空间支持更低层次 —— 你可以用它来分离单个部件 (例如,你也许只想要取消共享IPC),从而提高安全性和隔离性。
并非所有的场景都要求一个完整的类系统视图 (在大量的场景下,是次优的,而在其他场景下则是最佳方案),试着把名字空间当成一种提高安全性和隔离性的方法,当你需要/可以分离一个组件时,使用克隆/取消共享来完成。当你想要让用户访问一个完整的类系统时,使用LXC。
六十二、Forkpty路由器, TunTap路由器
六十三、使用Nagios监控uWSGI
六十四、内嵌SNMP服务器
uWSGI服务器内嵌了一个小小的SNMP服务器,你可以用它来把你的web应用和监控基础设施集成在一起。
要启用SNMP支持,你必须运行uWSGI UDP服务器,然后选择一个SNMP community字符串 (这是SNMP使用的基本鉴权系统)。
六十五、推送统计信息
你可以通过各种系统(称之为统计信息推送器)推送统计数据 (与你通过 uWSGI Stats服务器 获得的相同的JSON块)。会定期 (默认是3秒) 对统计数据进行推送。
1)‘file’统计信息推送器
2)‘mongodb’统计信息推送器
3)你可以配置所有你需要的统计数据推送器,只需指定多个stats-push选项
六十六、与Graphite/Carbon集成
六十七、uWSGI Stats服务器
除了 SNMP ,uWSGI还支持一个Stats服务器机制,它将uWSGI状态作为一个JSON对象导出到一个socket。
只需使用 stats 选项,后面跟着一个有效的socket地址。如果你想通过HTTP提供stats,那么还需要添加 stats-http 选项。
uwsgitop 是一个类似于top的命令,它使用stats服务器。可以在PyPI找到,因此使用 easy_install 或者 pip 来安装它 (自然而然地,包名是 uwsgitop)。
六十八、WSGI异步/非堵塞模式
异步模式并不会加速你的应用,它们旨在提高并发性。不要指望启用某些模式会完美运行,异步/事件/非阻塞系统需要应用的配合,因此,如果你的应用是在没有考虑特有的异步引擎的规则下开发的,那么你就错了。
uWSGI,遵循其模块化方法,将异步引擎分成两类。
1)挂起/恢复引擎
它们简单实现了协程(coroutine)/绿色线程(green thread)技术。它们并无事件引擎,因此,你必须使用由uWSGI提供的。一个事件引擎通常是一个为平台无关的非阻塞I/O(libevent, libev, libuv等等)导出基元的库。使用 --async < n> 选项启用uWSGI事件引擎。
2)I/O引擎(或事件系统)
uWSGI有一个高度优化的事件触发技术,但也可以使用其他方法。
I/O引擎都需要一些挂起/恢复引擎,否则会发生糟糕透的事情 (整个uWSGI代码库都是协程友好的,因此,你可以非常容易地玩转栈)。
目前支持的I/O引擎是:
Tornado循环引擎
libuv (工作正在进行中)
libev (工作正在进行中)
3)循环引擎
循环引擎是既导出挂起/恢复技术,又导出事件系统的包/库。加载后,它们uWSGI管理连接和信号处理器 (uWSGI信号, 不是 POSIX信号)的方式。
目前,uWSGI支持以下循环引擎:
Gevent (Python, libev, greenlet)
Coro::AnyEvent (Perl, coro, anyevent)
虽然它们通常由特定的语言使用,但是纯C的uWSGI插件 (像CGI) 可以用它们正常地提高并发性。
4)异步开关
要启用异步模式,你得使用 --async 选项 (或者它的一些快捷方式,由循环引擎插件导出)。
–async 选项的参数是要初始化的“核心”数。每个核可以管理一个单一的请求,因此,生成越多的核,就能管理越多的请求 (并且会使用越多的内存)。挂起/恢复引擎的工作的是停止当前的请求管理,移到另一个核,最后回到旧的核(等等)。
从技术上讲,核只是保存请求数据的内存结构,但为了给用户多线程系统的错觉,我们使用了这个术语。
核之间的切换需要应用的协作。有多种方式来完成,通常,如果你正使用一个循环引擎,那么全都是自动的 (或者只需很少的努力)。
5)异步模式下运行uWSGI
要以异步模式启动,需要传递 --async 选项以及你想要的“异步核”数。
6)等待I/O
如果你不处于循环引擎之下,那么可以使用uWSGI API来等待I/O事件。
7)休眠
有时,你可能想要在你的应用中休眠,例如要限制带宽。
使用 uwsgi.async_sleep(N) 取代堵塞的 time.sleep(N) 函数来生成N秒的控制。
8)挂起/恢复
从主应用生成并不非常实用,因为大部分时间,你的应用比一个简单的可回调更高级,并且由大量的函数和不同层次的调用深度构成。
别担心!你可以通过简单调用 uwsgi.suspend() 来强制挂起(使用协程/绿色线程)
六十九、Gevent循环引擎
Gevent 是一个令人惊奇的非阻塞Python网络库,构建在 libev 和 greenlet 之上。虽然uWSGI支持Greenlet作为挂起-恢复/绿色线程/协程库,但是还需要大量的努力和代码修改才能对gevent起作用。
注意:
1)SignalFramework 完全对Gevent模式有效。每个处理函数将会在一个专用的greenlet中执行。看看 tests/ugevent.py 这个例子。
2)uWSGI多线程模式 (threads 选项) 对Gevent无效。支持在你的应用中运行Python多线程。
3)把uWSGI的异步API和gevent混在一起是明确禁止的。
七十、Tornado循环引擎
tornado循环引擎允许你将你的uWSGI栈与Tornado IOLoop类集成。
基本上,服务器的每一个I/O操作会被映射到一个tornado IOLoop回调。进行RPC、远程缓存或者简单的写入响应则由Tornado引擎管理。
由于uWSGI不是用一个基于回调的编程方法写的,因此与那种类型的库集成需要某些类型“挂起”引擎 (绿色线程/协程)
目前唯一支持的挂起引擎是”greenlet”。
七十一、uGreen – uWSGI绿色线程
uGreen是在 uWSGI async platform 之上的一个 green threads 实现。
它与Python的greenlet非常相似,但是是构建在POSIX的 swapcontext() 函数之上的。要利用uGreen,你必须设置将会映射到green线程的异步核心数。
七十二、asyncio循环引擎
七十三、Apache支持
七十四、原生HTTP支持
http-socket < bind> 选项将会让uWSGI和原生HTTP通信。如果你的web服务器不支持 uwsgi protocol ,但是可以与上游HTTP代理通信,或者如果你正在用诸如Webfaction或者Heroku这样的服务来托管你的应用,那么你可以使用 http-socket 。如果你计划只通过uWSGI开放你的应用,那么用 http 选项来代替,因为路由器/代理/负载均衡器将会保护你。
七十五、HTTPS支持
七十六、nginx支持
自0.8.40版本起,Nginx本身就包含了对使用 uwsgi protocol 的上游服务器的的支持。
1)配置Nginx
2)集群
3)动态应用
当传递特殊变量的使用,uWSGI服务器可以按需加载应用。
4)在同一个进程中托管多个应用 (亦称管理SCRIPT_NAME和PATH_INFO)
5)静态文件
6)虚拟主机
七十七、python支持
1)你可以使用应用字典机制来避免在配置中设置你的应用。
2)Virtualenv支持
3)python3: 一个主要的改变时应用必须响应 bytes 实例,而非 (Unicode) 字符串到WSGI栈。
4)Paste support, Pecan support
5)使用Django应用django-uwsgi(展示uwsgi统计数据)
七十八、uwsgi Python模块
uWSGI服务器自动添加一个 uwsgi 模块到你的Python应用中。
这对于配置uWSGI服务器是有用的,使用它的内部函数,并获取分析数据(以及检测你是否真的在uWSGI下运行)。
该模块的接口:
1)模块级别的全局变量
2)缓存函数
3)队列函数
4)SNMP函数
5)spooler函数
6)高级方法
7)异步函数
8)SharedArea函数
9)Erlang函数
10)饰器是Python较为牛逼的特性之一,因此,在uWSG源代码树中,你会发现有个模块导出了一堆的装饰器,它们涵盖了很大一部分uWSGI API。
10.1)基于信号量的装饰器在第一个可用worker中执行信号处理器。如果你已经启动了spooler,那么你可以在其中执行信号处理器,让worker不用管它,只要管理正常的请求即可。简单传递 target=‘spooler’ 给装饰器。
10.2)例子:一个Django会话清理器和视频解码器
10.3)例子:web2py + spooler + timer
10.3)uwsgidecorators API参考
uwsgidecorators.postfork(func)
uwsgidecorators.spool(func, pass_arguments=False)
uwsgidecorators.spoolforever(func, pass_arguments=False)
uwsgidecorators.spoolraw(func, pass_arguments=False)
uwsgidecorators.rpc(“name”, func)
uwsgidecorators.signal(num)(func)
uwsgidecorators.timer(interval, func)
uwsgidecorators.rbtimer(interval, func)
uwsgidecorators.cron(min, hour, day, mon, wday, func)
uwsgidecorators.filemon(path, func)
uwsgidecorators.erlang(process_name, func)
uwsgidecorators.thread(func)
uwsgidecorators.lock(func)
uwsgidecorators.mulefunc([mulespec, ]func)
uwsgidecorators.harakiri(time, func)
11)Python Tracebacker
WSGI包括了一个类似的技术,允许你通过一个UNIX socket获取实时回溯。
要启用这个回溯器,你需要添加选项py-tracebacker=<socket>
,,其中,<socket>
是已创建UNIX socket的_basename_。
12)别名化Python模块
拥有一个Python包/模块/文件的多个版本是非常常见的。
操作PYTHONPATH,或者使用virtualenv是在无需修改代码的情况下使用不同版本的一种方式。
但是亲爱的,为什么不使用一个别名系统,以让你随心所欲的将模块名映射到文件呢?这就是为嘛我们有 pymodule-alias 选项的原因了!
七十九、在uWSGI中运行PHP脚本
八十、uWSGI Perl支持, Ruby 支持, lua支持, JVM支持,Mono ASP.NET支持
八十一、在uWSGI中运行cgi脚本
八十二、GCCGO插件
八十三、Symcall插件
symcall插件 (modifier 18) 是一个便利的插件,允许你在不需要开发一个完整的uWSGI插件的情况下编写原生uWSGI请求处理器。
你告诉它在启动时加载那个时候符号,然后它就会在每个请求上运行它。
八十四、XSLT插件
自uWSGI 1.9.1起,有了一个新的名为”xslt”的插件,它同时作为请求处理器和路由指令实现了XML样式表。
想成功应用转换,你需要一个“文档” (一个XML文档) 和一个样式表 (XSLT文件)。
此外,你可以应用全局参数,并设置一个指定的内容类型 (默认情况下,生成的输出被设置为text/html)。
八十五、SSI (服务器端包含,Server Side Includes) 插件
八十六、 V8支持
八十七、gridFS插件
八十八、GlusterFS插件
自uWSGI 1.9.15起可用
官方modifier1: 27
‘glusterfs’插件允许你使用自GlusterFS 3.4起可用的glusterfs api,直接提供存储在glusterfs文件系统中的文件
这个方法 (与通过fuse或者nfs提供相比) 在性能和易于部署方面有许多优势。
八十九、RADOS插件
‘rados’插件让你可以使用librados API,直接提供存储在一个Ceph集群中的对象。
注意,不是CephFS文件系统,也不是’radosgw’ S3/Swift兼容层;RADOS是裸对象存储层。
九十、 Pty插件
-自uWSGI 1.9.15起可用,Linux, OpenBSD, FreeBSD和OSX皆支持。
这个插件允许你附加伪终端到你的应用上。
目前,只能在第一个worker上附加(并通过网络公开)伪终端服务器 (未来会移除该限制)。
该插件还公开了一个客户端模式 (避免你把它跟netcat, telnet或者screen设置混在一起)
九十一、使用LDAP配置uWSGI
可以使用LDAP配置uWSGI。LDAP是一种集中uWSGI服务器的大型集群的配置的灵活方法。