这是uWSGI项目有争议的选项之一。
默认情况下,uWSGI会在第一个启动的进程中加载整个应用,并在加载完毕之后,会将自己多次fork()。这是常见的Unix模式,这能够显著降低应用的内存使用量,允许使用一些有趣的技巧,同时对于某些语言来说,这也会给你带来一些令人头疼的问题。
虽然它的名字,uWSGI,来自于一个Perl应用服务器(但不叫uWSGI,也没有开源),在Perl的世界中,preforking通常是被极力推崇的方式。
而对于其它的语言、平台和框架来说,却未必是这样的,所以,在和uWSGI打交道之前,你要选择如何在你的栈中管理fork()。
从“优雅的重新加载”的角度来看,preforking极大地提升了速度:你的应用只被加载一次,然后从其派生出其它的工作进程会非常快。避免你栈中的每个工作进程都做磁盘访问,会减少启动的时间,特别是对于那些需要做大量的磁盘访问来查询模块的框架和语言,效果会更加明显。
不幸的是,如果你使用的是preforking的方式,当你对代码做了修改之后,你需要重新加载整个栈,而不仅仅是对应的工作进程。
除此之外,你的应用或者可以使用preforking的方式,或者会因为应用本身开发的方式导致preforking方式下应用的崩溃。
lazy-apps模式却是每个工作进程都会加载一次你的应用。这会花费O(n)的时间来完成整个加载过程(其中n是工作进程的数量),同时这种方式非常有可能会占用更多的内存,但是应用会运行在一个更加一致和干净的环境中。
记住,lazy-apps不同于lazy,前者只是告诉uWSGI每个工作进程要加载一次应用,而后者更加具有侵入性(通常应避免这种情况),因为这会要求更改大量的默认的内部运作方式。
下面展示了在preforking和lazy模式下,如何达到0宕机时间/等待的几种方式:
Note:每种方式都有其优点和缺点,谨慎选择
标准的(默认的/乏味的)优雅重加载(也称为SIGHUP)方式
你可以通过以下方式触发它:
• 向master发送SIGHUP信号
• 向Master FIFO写入r
• 使用--touch-reload选项
• 调用uwsgi.reload() API
在preforking和lazy-apps模式下,将会:
1. 等待正在运行的工作进程
2. 关闭除映射到套接字之外的所有的文件描述符
3. 调用自身的exec()方法
在lazy模式下,将会:
1. 等待正在运行的工作进程
2. 重新启动它们(这意味着,使用这种重加载的方式,你不能更改uWSGI选项)
Warning:lazy模式不推荐使用!
优点:
• 便于管理
• 没有边边角角的问题
• 没有不一致的状态
• 基本上是实例的完全重置
缺点:
• 我们之前看到的
• 监听队列充满
• 工作进程无响应
• 潜在的长时间等待
lazy-apps模式下的工作进程重加载
需要启用--lazy-apps选项
要触发它,使用:
• 向Master FIFO写入w
• 使用--touch-workers-reload选项
这样会等待所有正在运行的工作进程,然后重启每一个。
优点:
• 避免了重启整个实例
缺点:
• 与标准的优雅重加载相比,没有用户体验上的改善,它仅仅是在实例不引入重新配置的情况下更新代码的一种便捷方式
链式重加载(lazy apps)
需要启用--lazy-apps选项
你可以通过以下方式触发它:
• 向Master FIFO中写入c
• 使用—touch-chain-reload选项
这是第一种能够改善用户体验的重载方式。当触发的时候,它会一次重启一个工作进程,后面的工作进程只有在前面的工作进程准备好接受新的请求后才会被重载。
优点:
• 可以大幅度地减少用户的等待时间
• 在重加载的过程中,不会明显增加机器负载(多个进程不会同时加载相同的代码)
缺点:
• 只是在代码更新的时候有用
• 需要一定数量的工作进程来获取更好的用户体验