You are here

Drupal站点拆分实用步骤及相关要点

g089h515r806 的头像
Submitted by g089h515r806 on 星期三, 2010-07-07 15:04

我们知道,一个Drupal站点,功能越多,需要启用的模块也就越多,模块越多,需要消耗的内存也就越多,因此性能也就越差.为了解决这样的问题,我们常常需要将一个门户网站拆分成多个子站的方式.将一个功能复杂的网站,拆分成多个子站,则需要解决多种技术问题. 以2u4u为例,它包含多个频道,启用了130+个模块,当登录用户比较多时,就会遇到性能瓶颈.

   首先解决的是,单点登录问题,完成拆分后,主站和子站之间,用户要共享,用户登录其中的任何一个站点,便能够自动的登录其余站点.对于单点登录,我们经过对现有的单点登录解决方法和模块进行对比,决定采用Drupal内置的多站点机制,以及用户表共享机制,同时还利用了MYsql的跨数据库查询功能,这样就能够完美的解决我们的单点登录问题了.
   其次需要解决的是,如何将子站点的内容聚合到主站点的问题,经过分析,我们目前采用了Services模块,通过XMLRPC来调用子站点的数据接口.
   解决了这两个关键的问题以后,就开始动手拆分了.这里简单的介绍一下拆分时所需的步 .骤.首先是备份,有备无患.
1,修改hosts文件,在本地将测试域名与IP绑定,正式上线则需要DNS绑定。
2,修改Apache的配置,设置测试域名下的虚拟主机。
3,Drupal内置的多站点机制,在sites目录下面创建以测试子域名命名的文件夹,并在里面添加settings.php和modules,themes目录。
4,创建测试数据库,修改用户1的密码,注意可以阿使用Phpmyadmin提供的编辑功能,方便的实现,关键是MD5加密。
5,修改文件系统目录的设置,将其设置为测试站点所对应的目录。
6,将主站点下的modules,themes目录下的模块和主题,复制到测试子站点上
7,修改files表中的filepath字段里面存储的值,需要将其改为测试子站点对应的地址。这里关键的SQL语句,
SELECT filepath,replace(filepath,’sites/2u4u.com.cn’, ’sites/testtest.2u4u.com.cn’) FROM files
 
UPDATE files SET filepath=replace(filepath,’sites/2u4u.com.cn’, ’sites/testtest.2u4u.com.cn’)
这样就解决了测试子站点中文件路径不存在的问题。
 
另外一个难点是,删除一个节点时,无法删除files表中对应的文件记录,经过研究Filefield的源代码,我们发现,Drupal首先会检查文件是否存在,如果文件存在,那么再删除files表中对应的文件记录。由于2u4u上的文件由70+G,采用文件复制的方式,也需要4,5个小时,这种方式非常笨拙,所以我们决定采用修改Filefield源代码的权宜之计,让Drupal删除节点时,直接删除对应的files表中的文件记录。
 
另外,在拆分站点时,我们需要保证,子站点的路径和现有主站点的NID保持一致,所以我们需要批量的删除无用的节点,我们开始采用了views的批量操作模块,但是每次只能批量的删除1000个,而我们有数万个节点需要删除,所以最终决定编写一个模块,采用批处理的方式,删除所选节点类型下面的所有节点,比较完美的解决了超大量节点删除的技术问题。
 

                           本文由2u4u赞助。

论坛:

g089h515r806 的头像

Filefield模块下面filefield_field.inc文件,function filefield_field_delete_file($file, $field) 函数,在代码:

if ($file->status == 0 || filefield_get_file_reference_count($file, $field) > 0) {
    $file->field_name = $field_name;
    $file->delete_nid = $delete_nid;
    return field_file_delete($file);
  }

之前添加 db_query('DELETE FROM {files} WHERE fid = %d', $file->fid);

成了:

db_query('DELETE FROM {files} WHERE fid = %d', $file->fid);
  // To prevent FileField from deleting files it doesn't know about, check the
  // FileField reference count. Temporary files can be deleted because they
  // are not yet associated with any content at all.
  if ($file->status == 0 || filefield_get_file_reference_count($file, $field) > 0) {
    $file->field_name = $field_name;
    $file->delete_nid = $delete_nid;
    return field_file_delete($file);
  }

g089h515r806 的头像

path_redirect_delete_multiple(NULL, array('source' => 'node/'. $node->nid));
      path_redirect_delete_multiple(NULL, array('source' => 'node/'. $node->nid . '/%%'));