我在apps.py
中有以下代码:
class Pqawv1Config(AppConfig):
# ...
def ready(self):
env_run_main=os.environ.get('RUN_MAIN')
print('IS_PRODUCTION=%s, RUN_MAIN=%s' % (settings.IS_PRODUCTION, env_run_main))
if (not settings.IS_PRODUCTION) and (env_run_main != 'true'):
print('Exiting because detected running in reloader.')
return
print('Starting up for PID=%s, argv=%s...' % (os.getpid(), sys.argv))
# Initialization of a singleton object from a C++ DLL
# Raise an exception if this library was already initialized in this process
晚上,我重新启动了服务器,并按预期在日志中打印了以下内容:
[Sun Sep 15 22:50:34.928549 2019] [wsgi:error] [pid 11792:tid 1176] Starting up for PID=11792, argv=['mod_wsgi']...\r
但是,早上我注意到发生了一些奇怪的事情。看起来Apache启动了Web应用程序的新线程:
[Mon Sep 16 04:10:41.224464 2019] [wsgi:error] [pid 11792:tid 1160] Starting up for PID=11792, argv=['mod_wsgi']...\r
后来:
[Mon Sep 16 07:16:21.028429 2019] [mpm_winnt:error] [pid 11792:tid 2272] AH00326: Server ran out of threads to serve requests. Consider raising the ThreadsPerChild setting
我认为这不是两次调用AppConfig.ready()
方法的问题,因为在两者之间有对网站的请求并且处理得很好。看起来,Django的AppConfig.ready()
方法在Apache进程的每个工作线程中都被调用过一次。是这样吗在这种情况下,如何在每个进程中运行一次代码,而不是在由Apache和mod-wsgi支持的Django中每个线程运行一次代码?
答案 0 :(得分:0)
根据您的apache配置,这可能是一个非答案。但是,大多数apache mod_wsgi配置建议您在重新启动wsgi进程之前实现某种max_request。您的代码可能是根据正常请求执行此操作,或者您的代码遇到了Django异常。
在这两种情况下,您都应该能够仅通过apache config或选项来分辨这一点。
https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIDaemonProcess.html
需要注意的一些有价值的选择
restart-interval = sss
以秒为单位定义时间限制 守护进程应在重新启动之前运行。
这可能用于定期强制重新启动WSGI应用程序 与Python对象参考相关的问题时的处理 计算周期,或不正确使用内存缓存,这会导致 持续的内存增长。
如果未定义此选项或将其定义为0,则守护程序 流程将是持久的,并将继续为请求提供服务,直到 Apache本身将重新启动或关闭。
避免将其设置得太低。这是因为不断重启 并且重新加载WSGI应用程序可能会导致不必要的加载 您的系统并影响性能。
您可以与此同时使用graceful-timeout选项 减少活动请求被请求的机会的选项 由于使用此选项而在重新启动时中断。
maximum-requests = nnn
定义请求数量的限制 守护进程应在关闭并重新启动之前进行处理。
这可能用于定期强制重新启动WSGI应用程序 与Python对象参考相关的问题时的处理 计算周期,或不正确使用内存缓存,这会导致 持续的内存增长。
如果未定义此选项或将其定义为0,则守护程序 流程将是持久的,并将继续为请求提供服务,直到 Apache本身将重新启动或关闭。
避免将其设置为可处理的网站上的少量请求 大量的流量。这是因为不断重启 重新加载WSGI应用程序可能会导致不必要的加载 系统并影响性能。仅当您没有时才使用此选项 由于内存使用问题,其他选择。尽快停止使用 内存问题已解决。
您可以与此同时使用graceful-timeout选项 减少活动请求被请求的机会的选项 由于使用此选项而在重新启动时中断。
inactivity-timeout = sss
定义允许的最大秒数 在守护进程关闭之前通过并在重新启动时通过 守护进程已进入空闲状态。为此目的 选项,处于空闲状态意味着没有当前活动的请求,也没有 收到新的请求。
存在此选项是为了允许不经常使用的应用程序在 守护进程重新启动,从而允许内存用于 回收,进程大小降回到初始启动 加载任何应用程序或处理请求之前的大小。
请注意,在重新启动WSGI应用程序过程之后,WSGI 应用程序将需要重新加载。这可能意味着 进程重新启动后,进程收到的请求可以是 慢点。如果您的WSGI应用程序在CPU上的启动成本很高 和时间,使用该选项可能不是一个好主意。
另请参见请求超时选项,用于在以下情况下强制重新启动进程 请求在指定的时间段内处于阻止状态。
请注意,与请求超时选项的功能类似, 是在请求被阻止时强制重新启动的一部分 由inactivity-timeout选项实现。请求超时为 在mod_wsgi的4.1.0版本中分解为一个单独的功能。
request-timeout = sss
定义a的最大秒数 允许该请求在守护进程重新启动之前运行。这个 可用于从请求被阻止的情况中恢复 无限期,如果所有请求线程都在此消耗掉 这样会导致整个WSGI应用程序流程被阻止。
此选项的行为方式会有所不同,具体取决于 守护进程仅使用一个线程,或将一个以上的线程用于 按照threads选项设置处理请求。
如果只有一个线程,那么该进程只能处理 一次超过一个请求,一旦超时,将重新启动 该过程将启动。
如果有多个线程,则将请求超时应用于 所有请求在所有线程上的平均运行时间。这个 意味着一个请求可以运行超过请求超时的时间。这是 这样做是为了减少中断其他正在运行的请求的可能性, 并导致用户看到故障。所以哪里还有容量 为了处理更多请求,如果出现以下情况,将重启进程 可能。
死锁超时= sss
定义允许的最大秒数 在守护进程关闭之前通过,并在一个守护进程之后重新启动 已检测到Python GIL上的潜在死锁。默认是 300秒。
存在此选项是为了解决守护程序进程冻结的问题 由于恶意的Python C扩展模块没有 在进入阻塞或长时间阻塞时正确释放Python GIL 运行操作。
startup-timeout = sss
定义允许的最大秒数 通过等待,看是否可以成功加载WSGI脚本文件 通过守护进程。超过超时时间后,该过程将 重新启动。
这可用于在瞬态时强制重新加载进程 第一次尝试加载WSGI脚本文件时发生问题,但是 随后的尝试仍然失败,因为 加载的状态保留,从而阻止尝试运行初始化 在同一过程中第二次。 Django套件可能会导致 这种情况由于Django本身的初始化不再可能 在同一过程中尝试了多次。