在Django中加快首个页面加载速度

22

当我更新网站上的代码后,我(自然地)重新启动我的apache实例,以便更改生效。

不幸的是,每个apache实例提供的第一页加载时都非常缓慢,因为需要将所有内容首次加载到RAM中(对于这个特定网站而言需要5-7秒)。

随后的请求仅需要0.5 - 1.5秒,因此我希望消除这种影响对我的用户造成的影响。

有没有更好的方法来使所有内容加载到RAM中,而不是执行x次wget(其中x是由http.conf中的ServerLimit定义的apache实例数)?

编写一个重新启动脚本,重启apache并运行wget 5次,似乎有些不可靠。

谢谢!


4
实际上,编写一个重新启动apache并运行“wget”五次的重启脚本对我来说似乎是一个合理的方法。 - Dominic Rodger
2
尽管您可能需要注意确保每个对wget的调用由不同的进程处理 - 您可能需要多次加载它以确保。 - Dominic Rodger
1
我已经测试过了,在Webfaction(应用程序托管的地方)的Apache配置会循环遍历实例,所以5个“wget”就可以解决问题。 - Jiaaro
@Jim - 听起来不错(并且符合Webfaction规则)。 - Dominic Rodger
2个回答

32

Apache/mod_wsgi默认仅在第一次要求进程时加载应用程序代码。 因此,第一步是配置mod_wsgi在进程启动时预加载您的代码,而不仅仅是第一个请求。 这可以使用WSGIImportScript指令在mod_wsgi 2.X中完成。

假设使用守护程序模式,这也是更好的选项,这意味着您将拥有类似以下内容的东西:

# 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,并具有预加载应用程序的副作用。


3

您是如何运行Django的(mod_python vs mod_wsgi)?

如果您正在运行mod_wsgi(在守护程序模式下),重新启动Apache不需要重新加载应用程序。您只需要更新wsgi脚本的修改时间(可以使用touch轻松完成)。

mod_wsgi的文档对该过程有相当详细的解释:

重新加载源代码


我一直在想为什么应用程序没有重新加载!我得用 touch wsgi 脚本替换我的重启脚本 :) 不过这样能解决我的首次加载问题吗?还是我仍然需要 wget? - Jiaaro
它将减少首次加载所花费的时间,但不会完全消除它。 - Josh Wright

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接