需要知道的事情 (最佳实践和“问题”) 必读!!!
http
和http-socket
选项是完全不同的。第一个生成一个额外的进程,转发请求到一系列的worker (将它想象为一种形式的盾牌,与apache或者nginx同级),而第二个设置worker为原生使用http协议。
TL/DR: 如果你计划直接将uWSGI公开,那么使用—http
,如果你想要在一个使用http与后端通信的web服务器后代理它,那么使用—http-socket
。.. seealso:: 原生HTTP支持
直到uWSGI 2.1,默认情况下,发送
SIGTERM
信号给uWSGI意味着“粗鲁地重载栈”,然而习惯是用SIGTERM
信号来关闭一个应用。要关闭uWSGI,请使用SIGINT
或者SIGQUIT
代替。如果你完全不能忍受uWSGI如此地不尊重SIGTERM
,那么务必启用die-on-term
选项。幸运的是,这个糟糕的选择已经在uWSGI 2.1修复了。如果你计划托管多个应用,那么就当做是帮你自己一个忙,看看 uWSGI Emperor —— 多应用部署 文档。
始终使用uwsgitop,通过 uWSGI Stats服务器 或一些类似的东东来监控你的应用健康度。
uWSGI可以在核心部分包含特性,也可以将特性作为插件加载。由操作系统发行版提供提供的uWSGI包倾向于模块化。在这样的步骤中,确保使用
plugins
选项加载你所需的插件。识别一个未加载的插件的一个好症状是日志中像”Unavailable modifier requested”这样的消息。如果你正使用由发行版提供的包,那么仔细检查你是否已经安装了用于你所选的语言的插件。配置文件支持一种有限形式的继承、变量、if构造和简单的循环。看看 配置逻辑 和 uWSGI是如何解析配置文件的 页面。
要路由请求到一个指定的插件,web服务器需要传递一个称为modifier的魔术数字到uWSGI实例。默认情况下,这个数字被设置为0,这会映射到Python。例如,路由一个请求到一个
PSGI
应用要求你设置modifier为5
- 或者可选地加载PSGI插件作为modifier0
。(这将意味着,所有的无modifier的请求将会被认为是Perl的。)没有设置要使用的进程数或线程数的魔法规则。它是灰常依赖于应用和系统的。简单的算术,例如
processes = 2 * cpucores
,并不够。你需要对多种步骤进行实验,并且准备好不断监控当你的应用。uwsgitop
会是一个帮你找到最佳值的好工具。如果一个HTTP请求有请求体 (例如由表单生成的POST请求),那么你 必须 在你的应用中读取 (消费) 它。如果你不这么做,那么通过你的web服务器的通信套接字可能会被重写。如果你懒癌犯了,那么你可以使用
post-buffering
选项,它会自动地为你读取数据。对于Rack
应用,这是自动启用的。经常检查你的应用的内存使用。
memory-report
选项会是你最好的伙伴。如果你计划使用UNIX socket (与TCP相对),那么记住,它们是标准的文件系统对象。这意味着,它们有权限,并且同样地,你的web服务器必须有对它们的写权限。
常识:不要以root用户运行uWSGI实例。你可以作为root启动你的uWSGI们,但是确保使用
uid
和gid
选项来移除权限。uWSGI试图在一切可能的情况下(滥)用 fork() 调用的写时拷贝语义。默认情况下,它会在加载你的应用之后进行fork,以尽可能的共享它们的内存。如果出于某些原因,不期望这个行为,那么使用
lazy-apps
选项。这将会指示uWSGI在每个worker的fork()
之后加载应用。注意,有一个更老的名为lazy
的选项,它是一种更侵入以及极度不推荐的方式 (它仍然能用,只是为了向后兼容)默认情况下,Python插件并不初始化GIL。这意味着你由应用生成的线程并不会运行。如果你需要线程,记得通过
enable-threads
启用它们。在多线程模式(使用threads
选项)下运行uWSGI将会自动启用线程支持。这种“奇怪的”默认行为是出于性能考量的,这并不可耻。如果你在请求期间生成一个新的进程,那么它户继承生成它的worker的文件描述符 - 包括连接到web服务器/路由器的socket。如果你并不想要这种行为,那么设置
close-on-exec
选项。Ruby垃圾回收器是默认配置的,它会在每个请求之后运行。这是一个激进的策略,可能会减缓一点你的应用 —— 但是CPU资源比内存便宜,特别是比耗尽内存便宜。要调整这个评论,则使用
ruby-gc <freq>
选项。在OpenBSD, NetBSD和FreeBSD < 9上,SysV IPC信号量被用作锁子系统。这些操作系统倾向于限制可分配信号量的数目为一个非常小的值。如果你计划运行超过1个uWSGI实例,那么你应该提高默认限制。FreeBSD 9有POSIX信号量,所以你无需为它费心。
不要使用与构建uWSGI二进制文件本身的配置文件不同的配置文件来构建插件 —— 除非你喜欢遭罪,或者 确切 知道你在干什么。
默认情况下,uWSGI为每个请求头分配一个非常小的缓存 (4096字节)。如果你的日志中开始收到”invalid request block size”,这可能意味着你需要更大的缓存了。通过
buffer-size
选项来增加它(最大值为65535)。
注解
如果你的日志中接收到了请求块大小为‘21573’,那这可能意味着你使用HTTP协议与一个使用uwsgi协议的实例进行通信。不要这样做。
如果你的 (Linux) 服务器似乎有大量的idle状态的worker,但性能仍然不佳,那么你或许想要看看
ip_conntrack_max
系统变量 (/proc/sys/net/ipv4/ip_conntrack_max
) 的值,然后增加它以看看是否有帮助。一些Linux发行版 (即,Debian 4 Etch, RHEL / CentOS 5)混合了较新的内核和非常老的用户空间。这种组合会让uWSGI构建系统显示错误 (在
unshare()
, pthread locking,inotify
…之上最值得注意)。你可以给’make’ (或者任何你用来构建它的方式) 加上前缀CFLAGS="-DOBSOLETE_LINUX_KERNEL"
,强制uWSGI对较老的系统进行配置默认情况下,在uWSGI启动的适合,stdin被重新映射到
/dev/null
。如果你需要一个有效的stdin (用于调试、管道等等),那么添加—honour-stdin
。你可以轻松地添加不存在的选项到你的配置文件中 (例如占位符、自定义选项或者应用相关的配置项)。这是一个非常方便的特性,但一旦有错别字,那就头疼了。strict模式 (
—strict
) 将禁用此特性,并且只允许有效的uWSGI选项。一些插件 (最明显的是Python和Perl) 具有代码自动重载机制。虽然这也许听起来很诱人,但是你必须只在开发阶段使用它们,因为它们真的很重。例如,Python的–py-autoreload选项将会在每个检查周期中扫描你整个模块树。
wsgi.file_wrapper
是WSGI标准的一个优化。在个别情况下,它会引发错误。例如,当在Python 3.5中返回一个内存中字节缓存 (io.Bytesio) 的时候。看看这个 issue 。你可以通过设置选项wsgi-disable-file-wrapper
为true
来禁用它。