我know it's not recommended使用python myapp.py --port=80
在制作时运行Bottle或Flask应用,因为它只是一个开发服务器。
我认为不建议使用python myapp.py --port=5000
运行它并将其链接到Apache:RewriteEngine On
,RewriteRule /(.*) http://localhost:5000/$1 [P,L]
(或者我错了?),因为WSGI是首选。
所以我目前正在设置Python app <-> mod_wsgi <-> Apache
(没有枪支或其他工具来保持简单)。
问题:在使用WSGI时,我知道Apache和mod_wsgi
会在请求到来时自动启动/停止运行myapp.py
的足够进程,但是:
示例:
我在myapp.py
中进行了一些更改,我想重新启动运行它的所有进程,这些进程已由mod_wsgi启动(注意:我知道mod_wsgi可以查看源代码的更改,然后重新启动,但这仅适用于.wsgi文件上的更改,而不是.py文件。我已经读过touch myapp.wsgi
可以解决这个问题,但更常见的是我喜欢能够手动停止和重启
我想暂时停止整个应用myapp.py
(所有实例)
我不想使用service apache2 stop
,因为我还使用Apache运行其他网站,而不仅仅是这个(我有一些VirtualHosts
)。出于同样的原因(我使用Apache运行其他网站,而某些客户端可能同时下载1 GB文件),我不希望service apache2 restart
对所有使用Apache的网站产生影响
我正在寻找一种比kill pid
或SIGTERM等更清晰的方法(因为在这种情况下我读了not recommended to use signals)。
注意:我已经阅读了How to do graceful application shutdown from mod_wsgi,它有所帮助,但这里是补充问题,而不是重复问题。
安装:
apt-get install libapache2-mod-wsgi
a2enmod wsgi # might be done automatically by previous line, but just to be sure
Apache配置(来源:Bottle doc):
<VirtualHost *:80>
ServerName example.com
WSGIDaemonProcess yourapp user=www-data group=www-data processes=5 threads=5
WSGIScriptAlias / /home/www/wsgi_test/app.wsgi
<Directory /home/www/wsgi_test>
WSGIProcessGroup yourapp
WSGIApplicationGroup %{GLOBAL}
Require all granted
</Directory>
</VirtualHost>
最多应该有5个进程,是吗?正如之前在问题中所述,如何知道有多少人正在运行,如何阻止他们?
/home/www/wsgi_test/app.wsgi
(来源:Bottle doc)
import os
from bottle import route, template, default_app
os.chdir(os.path.dirname(__file__))
@route('/hello/<name>')
def index(name):
return template('<b>Hello {{name}}</b>!', name=name)
application = default_app()
答案 0 :(得分:2)
部分取自this问题,将display-name
添加到WSGIDaemonProcess
,以便您可以使用以下命令抓取它们:
ps aux | grep modwsgi
将此添加到您的配置中:
Define GROUPNAME modwsgi
WSGIDaemonProcess yourapp user=www-data group=www-data processes=5 threads=5 display-name=%{GROUPNAME}
<强>更新强>
有几个原因导致ps不能给你DaemonProcess display-name
如docs:
display-name = value定义要为守护程序显示的其他名称 使用ps命令列出进程时的进程。如果值是 %{GROUP}然后名称将是(wsgi:group),其中组被替换 使用守护程序进程组的名称。
请注意,只提供所提供值的字符数 显示为最初由执行的argv0占用 处理。任何超出此范围的内容都将被截断。
此功能可能无法在所有平台上执行。通常它 还需要一个具有BSD传统的ps程序。因此在某些版本上 Solaris UNIX / usr / bin / ps程序不起作用,但/ usr / ucb / ps 确实。其他可以显示此值的程序包括htop。
你可以:
设置较小长度的display-name
:
WSGIDaemonProcess yourapp user=www-data group=www-data processes=5 threads=5 display-name=wsws
并尝试通过以下方式找到它们:
ps aux | grep wsws
或者将其设置为%{GROUP}
并使用守护进程组(wsgi:group)的名称进行过滤。
答案 1 :(得分:2)
在每种模式下使用mod_wsgi管理进程的方式如下所述:
对于嵌入式模式,您的WSGI应用程序在Apache子工作进程内部运行,Apache根据Apache MPM设置管理何时创建和销毁进程。由于Apache管理进程的方式,如果请求吞吐量不足,可以随时关闭它们,或者如果请求吞吐量增加,可以创建更多进程。运行时,相同的进程将随着时间的推移处理许多请求,直到它关闭。换句话说,Apache动态管理进程数。
由于这种动态的流程管理,使用mod_wsgi的嵌入模式是个坏主意,除非你知道如何正确地调整Apache以及许多其他事情。简而言之,除非您对Apache有丰富的经验并使用它运行Python应用程序,否则永远不要使用嵌入式模式。您可以观看有关您不希望在嵌入模式下运行的原因的视频:
还有博客文章:
因此,请使用守护程序模式并验证您的配置是否正确,并且您实际上是通过使用签入来使用守护程序模式:
对于守护程序模式,WSGI应用程序在一组单独的托管处理中运行。这些是在开始时创建的,并且将一直运行直到Apache重新启动,或者由于各种原因重新启动进程,包括:
在这些情况下,当进程关闭时,它将被替换。
有关各种超时选项以及进程如何响应信号的更多详细信息,请参见:
有关源代码重新加载和触摸WSGI脚本文件的更多详细信息,请参阅:
记录的一个项目是如何合并代码,以查找应用程序使用的Python代码文件的任何更改。当任何文件发生更改时,将通过向自身发送信号来重新启动该过程。这应该仅用于开发,而不是用于生产。
如果您在开发中使用mod_wsgi-express
,这比自己手动配置Apache更好,则可以使用--reload-on-changes
选项。
如果向守护进程发送SIGTERM
信号,则会有一个设置关闭序列,它会等待几秒钟等待当前请求完成。如果请求没有完成,则无论如何都会关闭该过程。该时间段由关闭超时决定。你不应该玩那个值。
如果向守护进程发送SIGUSR1
信号,默认情况下它就像发送SIGTERM
信号一样。但是,如果为关闭指定了正常超时,则可以延长等待当前请求完成的时间。在此期间,新的请求将被接受。该优雅超时也适用于其他情况,例如最大接收请求数或触发定期重启的定时器。如果在使用SIGUSR1
与这些情况不同时需要超时,请改为定义驱逐超时。
关于如何识别要发送信号的守护程序进程,请使用选项display-name
的{{1}}。然后使用WSGIDaemonProcess
标识进程,或者如果它在您的平台上使用修改后的进程名称,则可以使用ps
。如果想要更优雅的关闭,则发送守护进程处理killall
信号;如果希望它们立即重新启动,则发送SIGUSR1
。
如果要跟踪守护程序进程的运行时间,可以使用:
SIGTERM
import mod_wsgi
metrics = mod_wsgi.process_metrics()
值将包括以下输出,用于进行调用的过程:
metrics
如果您只想知道当前守护程序进程组使用了多少进程/线程,您可以使用:
{'active_requests': 1,
'cpu_system_time': 0.009999999776482582,
'cpu_user_time': 0.05000000074505806,
'current_time': 1525047105.710778,
'memory_max_rss': 11767808,
'memory_rss': 11767808,
'pid': 4774,
'request_busy_time': 0.001851,
'request_count': 2,
'request_threads': 2,
'restart_time': 1525047096.31548,
'running_time': 9,
'threads': [{'request_count': 2, 'thread_id': 1},
{'request_count': 1, 'thread_id': 2}]}
获取有关进程组的详细信息。此时对于守护程序模式的进程数是固定的,名称mod_wsgi.process_group
mod_wsgi.application_group
mod_wsgi.maximum_processes
mod_wsgi.threads_per_process
只是与嵌入模式下的名称一致。
如果需要在进程关闭时运行代码,则不应尝试定义自己的信号处理程序。这样做和mod_wsgi实际上会忽略它们,因为它们会干扰Apache和mod_wsgi的正常操作。相反,如果您需要在进程关闭时运行代码,请使用maximum_processes
。或者,您可以订阅mod_wsgi生成的特殊事件,并触发流程关闭事件。
答案 2 :(得分:1)
根据Evhz的回答,我做了一个简单的测试来检查进程是否仍在运行:
Apache配置:
<VirtualHost *:80>
ServerName example.com
WSGIDaemonProcess yourapp user=www-data group=www-data processes=5 threads=5 display-name=testwsgi
WSGIScriptAlias / /home/www/wsgi_test/app.wsgi
<Directory /home/www/wsgi_test>
WSGIProcessGroup yourapp
WSGIApplicationGroup %{GLOBAL}
Require all granted
</Directory>
</VirtualHost>
app.wsgi
档案:
import os, time
from bottle import route, template, default_app
os.chdir(os.path.dirname(__file__))
@route('/hello/<name>')
def index(name):
global i
i += 1
return template('<b>Hello {{name}}</b>! request={{i}}, pid={{pid}}',
name=name, i=i, pid=os.getpid())
i = 0
time.sleep(3) # wait 3 seconds to make the client notice we launch a new process!
application = default_app()
现在多次访问http://www.example.com/hello/you:
从客户端浏览器开始,初始time.sleep(3)
将有助于查看何时启动新流程,请求计数器i
将允许查看有多少每个流程都提供了请求。
PID将与ps aux | grep testwsgi
中的值相对应:
此外time.sleep(3)
最多会发生5次(在5个进程中的每个进程启动时),然后进程应该永远运行,直到我们重新启动/停止服务器或修改app.wsgi
文件(修改它会触发5个进程的重启,你可以看到新的PID)。
[我会通过让我的测试立即运行来检查,并在2天内访问http://www.example.com/hello/you以查看它是否仍然是之前启动的流程或新流程!]
编辑:第二天,相同的流程仍然正常运行。现在,两天后,当重新加载相同的URL时,我注意到创建了新进程...(是否有一段时间没有请求的进程死了?)