加速Django中首页加载速度
当我更新我网站的代码时,我会(很自然地)重启我的apache实例,这样更改才能生效。
不幸的是,每个apache实例第一次提供的页面加载速度比较慢,因为它需要把所有东西都加载到内存里(对于这个特定的网站,大约需要5到7秒)。
之后的请求只需要0.5到1.5秒,所以我想消除这种对用户的影响。
有没有比用wget命令执行x次(这里的x是http.conf文件中ServerLimit定义的apache实例数量)更好的方法来让所有内容都加载到内存里呢?
我觉得写一个重启apache并运行wget 5次的脚本有点像是临时解决办法。
谢谢!
2 个回答
你是怎么运行Django的?是用mod_python还是mod_wsgi?
如果你是用mod_wsgi(在守护进程模式下),那么重启Apache服务器并不是必须的来重新加载你的应用程序。你只需要更新一下你的wsgi脚本的修改时间(这可以通过简单的touch
命令来完成)。
mod_wsgi的文档里对这个过程有很详细的解释:
Apache和mod_wsgi的默认设置是,只在第一次请求时加载应用程序代码,这样会导致应用程序的启动变得比较慢。所以,第一步是要配置mod_wsgi,让它在进程启动时就预加载你的代码,而不是等到第一次请求时再加载。这个可以在mod_wsgi 2.X版本中通过使用WSGIImportScript指令来实现。
假设你使用的是守护进程模式,这种方式更好,这样你就可以像下面这样设置:
# Define process group.
WSGIDaemonProcess django display-name=%{GROUP}
# Mount application.
WSGIScriptAlias / /usr/local/django/mysite/apache/django.wsgi
# Ensure application preloaded on process start. Must specify the
# process group and application group (Python interpreter) to use.
WSGIImportScript /usr/local/django/mysite/apache/django.wsgi \
process-group=django application-group=%{GLOBAL}
<Directory /usr/local/django/mysite/apache>
# Ensure application runs in same process group and application
# group as was preloaded into on process start.
WSGIProcessGroup django
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Allow from all
</Directory>
当你修改了代码后,不要去触碰WSGI脚本文件,因为这个文件只会在下一个请求时被检查。相反,你应该给守护进程组中的进程发送一个SIGINT信号。
通过在WSGIDaemonProcess中使用'display-name'选项,你可以用BSD风格的'ps'程序来识别哪些进程。将'display-name'设置为'%{GROUP}',那么'ps'的输出应该会显示'(wsgi:django)'作为进程名称。找到进程ID后,执行:
kill -SIGINT pid
把'pid'替换成实际的进程ID。如果守护进程组中有多个进程,就要给它们全部发送信号。
不太确定'killall'是否可以一步到位地做到这一点。我在MacOS X上遇到过问题。
在mod_wsgi 3.X版本中,配置可以更简单,可以使用下面的方式:
# Define process group.
WSGIDaemonProcess django display-name=%{GROUP}
# Mount application and designate which process group and
# application group (Python interpreter) to run it in. As
# process group and application group named, this will have
# side effect of preloading application on process start.
WSGIScriptAlias / /usr/local/django/mysite/apache/django.wsgi \
process-group=django application-group=%{GLOBAL}
<Directory /usr/local/django/mysite/apache>
Order deny,allow
Allow from all
</Directory>
也就是说,不需要单独使用WSGIImportScript指令,因为可以将特定的进程组和应用组作为参数传递给WSGIScriptAlias,这样的副作用就是它会预加载应用程序。