当前位置

开启了Pathauto模块的Drupal多语言网站访问极慢的问题

James Qi 在 2013年3月6日 - 16:39 提交

  各国邮编的系列网站是用Drupal 6搭建的,当初都开启了Pathauto, Boost等模块,使用起来也都还正常,后来将一部分网站进行了50种多语言和手机版的扩充,访问速度就感觉要慢一些,最近一两个月来扩充得越多就感觉网站访问越慢,而且后来取消了Boost缓存(因为没有那么大的硬盘来缓存100倍的文件,即使可以放得下,文件数量太多访问也慢)后感觉更慢了一些。

  这个问题先在google webmaster tools中有所发现,但直到最近操作越来越慢才引起重视,监控软件的报错也开始频繁,昨天再一查监控软件的记录,这个系列的子网站打开首页都需要20秒以上,基本上没有办法正常使用了,必须尽快解决、马上解决。

  昨天就开始找办法,先以为是Views引起的,对一些MySQL字段添加索引后依然没有解决,再安装Devel仔细排查SQL语句,发现有过多的drupal_lookup_path,一个首页就达到100多条在url_alias表中查找路径的语句,网上资料有人说遇到类似问题,主要有两种解决办法:

  • 一是修改includes/path.inc;
  • 二是安装cachepath模块。

  后者只是对每个页面的drupal_lookup_path进行缓存,第一次缓存依然需要花很长时间,而我看到很多drupal_lookup_path语句都没有必要,所以还是想用第一种办法。

  本来Drupal是不建议修改核心模块文件的,但也没有更好的办法,网上别人做的patch实际上也就是修改includes/path.inc,他们改这个文件有两个作用:

  • 一是增加查询的缓存;
  • 二是排除一些不必要的查询。

  其中第一条我没有搞得很懂,第二条我觉得是有必要的,因为Devel看到一些查询语句根本没有必要,在MySQL中看看需要查询的表就知道根本就查不到结果,我没有采用src中建黑名单的方式,而是src中建白名单,只有网址开头是node、user和taxonomy这3种方式才查询数据库,这样修改后页面中的查询数量减少了大约一小半,MySQL的进程数明显减少,一个典型网页打开时间从约25秒减少到15秒左右。

  但这样还是不够的,又用Devel追踪发现每个页面都有的50种语言链接也在使用drupal_lookup_path语句,查询的网址是一样的,而语言不同,其实我们所有语言的网址都是一样的,这50个不同的查询其实可以改为同一个查询执行50遍,这样可以利用MySQL本身的查询结果缓存来加速,于是再改path.inc,去掉了查询语句中与语言有关的内容,这一下效果非常明显,一个典型网页打开时间可以小于5秒了,基本上算是正常访问了!

  最后把源代码记录如下:

// Get the most fitting result falling back with alias without language

//jamesqi 2013-3-6      $alias = db_result(db_query("SELECT dst FROM {url_alias} WHERE src = '%s' AND language IN('%s', '') ORDER BY language DESC, pid DESC", $path, $path_language));
      //start modify
      $path05=substr($path,0,5);
      $path014=substr($path,0,14);
      if ($path05=='node/' || $path05=='user/' || $path14=='taxonomy/term/') {
        $alias = db_result(db_query("SELECT dst FROM {url_alias} WHERE src = '%s' ORDER BY pid DESC", $path, $path_language));
      } else {
        $alias = FALSE;
      }
      //end modify
      $map[$path_language][$path] = $alias;
      return $alias;
}
    // Check $no_src for this $path in case we've already determined that there
    // isn't a path that has this alias
    elseif ($action == 'source' && !isset($no_src[$path_language][$path])) {
      // Look for the value $path within the cached $map
      $src = FALSE;
      if (!isset($map[$path_language]) || !($src = array_search($path, $map[$path_language]))) {
        // Get the most fitting result falling back with alias without language
//jamesqi 2013-3-6        if ($src = db_result(db_query("SELECT src FROM {url_alias} WHERE dst = '%s' AND language IN('%s', '') ORDER BY language DESC, pid DESC", $path, $path_language))) {
        if ($src = db_result(db_query("SELECT src FROM {url_alias} WHERE dst = '%s' ORDER BY pid DESC", $path, $path_language))) {
//end modify
$map[$path_language][$src] = $path;
        }
        else {
          // We can't record anything into $map because we do not have a valid
          // index and there is no need because we have not learned anything
          // about any Drupal path. Thus cache to $no_src.
          $no_src[$path_language][$path] = TRUE;
        }

 

 

 

 

添加新评论

Plain text

  • 不允许使用HTML标签。
  • 自动将网址与电子邮件地址转变为链接。
  • 自动断行和分段。