Drupal 7 开发内部培训资料, 分头诗人

Drupal性能优化之-将Boost模块用到极致

标签: Boost

Boost模块是drupal的一个静态页面缓存模块,效率非常之高,如果还不了解,请参考《让猪去飞-Drupal性能优化贴》,本文就使用Boost以及如何 hack该模块来打造高性能drupal网站做简单介绍。

一般情况下,Boost模块适用于匿名访问多的Drupal站点,因为这会直接去访问事先建好的静态页面,效率很高,不需要进行数据库查询。但是在很多情况下,我们的网站需要用户登录,以登录用户的方式访问网站,但是,网站的很多内容其实和匿名用户看到的完全一样。

举个例子,比如新浪博客,腾讯博客等。当用户登录之后和匿名用户看到的博文完全一样,唯一不同的就是上面的用户信息(topbar),也可以称之为顶栏或者侧栏。(参考下图)


当用户登录之后,上面的顶栏信息就会变成用户名和用户的个人信息链接。如果仔细观察,会发现(很多网站,如新浪、淘宝)的信息栏不是立刻加载的。也就是说用户信息栏的内容是异步的,当整个网页加载之后,上面的信息通过ajax,或者flash,或者iframe等异步方式获取。

所以,我们可以做这样一个结构的页面:把用户信息块用javascript脚本填充,其余部分均是静态内容,用户信息块在页面初始化的时候通过ajax方式动态加载,如果没有登录,显示登录连接;如果已经登录,则显示用户欢迎信息。

如此一来,所有public的页面(注意是public)都可以对匿名用户的非匿名用户缓存成静态页面了。借用Boost模块,我们实现缓存的生成,然后修改一下对应rewrite规则,即可让登录用户也访问静态页面了。

具体步骤如下,

1. 所有public页面生成静态页面,并当内容有修改时更新静态缓存。

2. 让匿名用户和普通登录用户都访问静态页面。

3. 让超级用户,比如durpal管理员,不要访问静态页面,直接运行drupal动态内容。

第一步,Boost模块完全可以实现。第二和第三步,我们用一小段代码,来标记用户是否是管理员,这样就可以在rewrite的规则中判断是否需要返回静态页面。

首先,实现hook_user,以标记用户。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* Implementation of hook_user().
*/
function MODULE_user($op, &$edit, &$account, $category = NULL) {
  switch ($op) {
    case 'logout':
      if (_is_admin($account)) {
       setcookie('DRUPAL_ADMIN', strval(), time()-3600, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), ini_get('session.cookie_secure') == '1');
        drupal_goto();
      }
      break;
    case 'login':
     if (_is_admin($account)) {
        //using it in rewrite rules for server
        setcookie('DRUPAL_ADMIN', strval($account->uid), time()+1800, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), ini_get('session.cookie_secure') == '1');
      }
      break;
  }
}
function _is_admin($account) {
  $admin_roles = variable_get('admin_role_ids', $admin_roles);
  return array_intersect($admin_roles, array_keys($account->roles));
}

这样,我们给超级用户添加了一个cookie以标记其角色。
下来,我们在apache或者nginx中,修改一下rewrite rule就可以让所有非DRUPAL_ADMIN使用静态页面了。
这里是Nginx的代码部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
###Nginx-BOOST
  set $boost "";
  set $boost_query "_";
 
  if ( $request_method = GET ) {
    set $boost G;
  }
  if ($http_cookie !~ "DRUPAL_ADMIN") {
    set $boost "${boost}D";
  }
  if ($query_string = "") {
    set $boost "${boost}Q";
  }
  if ( -f $document_root/cache/normal/$http_host$request_uri$boost_query$query_string.html ) {
    set $boost "${boost}F";
  }
  if ($boost = GDQF){
    rewrite ^.*$ /cache/normal/$http_host/$request_uri$boost_query$query_string.html break;
  }
  if ( -f $document_root/cache/perm/$http_host$request_uri$boost_query$query_string.css ) {
    set $boost "${boost}F";
  }
  if ($boost = GDQF){
    rewrite ^.*$ /cache/perm/$http_host/$request_uri$boost_query$query_string.css break;
  }
  if ( -f $document_root/cache/perm/$http_host$request_uri$boost_query$query_string.js ) {
    set $boost "${boost}F";
  }
  if ($boost = GDQF){
    rewrite ^.*$ /cache/perm/$http_host/$request_uri$boost_query$query_string.js break;
  }
  ###END-BOOST

 

也可以这么写

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
location / {
    rewrite ^/(.*)/$ /$1 permanent; # remove trailing slashes - disabled
    #try_files $uri @cache;
    try_files $uri @drupal;
    #if (!-e $request_filename) {
    #  rewrite  ^(.*)$  /index.php?q=$1  last;
    #  break;
    #}
  }
  location @cache {
    if ( $request_method !~ ^(GET|HEAD)$ ) {
        return 405;
    }
    if ($http_cookie ~ "DRUPAL_UID") {
        return 405;
    }
    error_page 405 = @drupal;
    add_header Expires "Tue, 24 Jan 1984 08:00:00 GMT";       
    add_header Cache-Control "must-revalidate, post-check=0, pre-check=0";
    add_header X-Header "Boost Citrus 1.9";              
    charset utf-8;
    try_files /cache/normal/$host${uri}_$args.html /cache/$host${uri}_$args.html @drupal;
  }

 

在apache下面的重写比较简单,大家可以借鉴一下Nginx的重写方式完成。主要也是判断cookie,大致就是添加如下代码:

 

1
RewriteCond %{HTTP_COOKIE} !DRUPAL_ADMIN

 

详细的,可以参考boost模块的说明。
这样我们基本就完成了Drupal对登录用户的缓存,按照2/8法则所述,我们用20%时间,提高了网站80%的性能。

最后附上Drupal网站的架构以及静态页面缓存和NFS的搭配使用示例图,以供大家参考。

其中web节点和fastcgi节点都可以水平扩展,NFS为各个服务器之间共享都存储介质,不过需要监控内网都网络IO,以防止产生瓶颈。