`
freespace
  • 浏览: 181228 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Drupal优化

阅读更多

 

 

Drupal的内核架构非常简洁并且非常灵活。然而,这种灵活性是有代价的。当启用的模块增加时,处理一个请求的复杂度也会增加。这意味着将耗费更多的服务器资源,必须实现一些策略,在一个站点日渐流行同时,来保证Drupal特有的简明。通过适当的配置,Drupal可以很容易的满足用户的需求。在本章中,我们将讨论性能(performance)和可升级性(scalability)。性能指的是你的站点响应一个请求所用的时间。可升级性指的是你的系统可以同时处理多少个并发请求,通常用“请求数/秒”来度量。

找出瓶颈

如果你的网站运行性能达不到预期,第一步要做的就是分析问题所在。可能的原因包括web服务器,操作系统,数据库,和网络。

初步追踪

了解如何估算一个系统的性能和可升级性,即便是在出现大的问题时,它也能使你保持自信,从而快速的隔离并找到系统的瓶颈。你可以借助于一些简单的工具,通过询问一些问题,来发现瓶颈。这里给出了一种方式,用来分析一个存在严重性能问题的服务器。首先,我们需要知道性能是有哪些因素决定的,CPU,RAM,I/O,或者带宽都是影响性能的因素。那么你需要询问以下问题:

CPU占用率达到最大了吗?检查CPU 的使用情况,在Unix上你可以使用top,在Windows上可以使用任务管理器,如果CPU占用率达到了100%,那么你的任务就是找出是什么程序占用了CPU。查看进程列表,可以让你了解到,是不是web服务器或者数据库占用了处理器的大部分计算资源。这两者都是可以解决的。

服务器的RAM用完了没有?在Unix上你可以使用top,在Windows上可以使用任务管理器,,来方便的检查这一点。如果服务器还有大量的空闲内存,那么继续下一个问题。如果服务器用完了内存,你必须找出原因。

磁盘空间不足了吗?检查磁盘子系统,在Unix使用工具vmstat,在Windows 下使用性能监测器,如果可用磁盘不能满足需求,同时又有大量空闲内存剩余,那么这就是一个I/O问题。可能的原因包括,记录了大量的冗余日志,对数据库不恰当的配置使得在磁盘上创建了许多临时表,后台脚本的执行,对于一个需要大量写操作的系统使用了一个不恰当的RAID级别,等等。

网络带宽用完了吗?如果网络带宽用完了,那么只有两种解决方案。一个是增加带宽。另一个是对发送的信息进行恰当的压缩,从而发送更少的信息。

Web服务器用完了CPU

如果你的CPU占用率达到了100%,而根据进程列表显示,是web服务器消耗了大量的资源而不是数据库(后面介绍),那么你应该去减少web服务器处理一个请求所耗费的资源。通常PHP代码的执行就是罪魁祸首。

PHP最优化措施

PHP最优化措施

在Drupal中,由于PHP代码执行在处理一个请求中占了一大块,所以我们需要知道采取哪些措施才能加快这一进程,这一点非常重要。对编译后的PHP操作代码(opcodes)进行缓存,和剖析应用层来找出低效算法,能够带来重要的性能提升。

缓存操作代码

有两种方式可以减少执行PHP代码所耗费的资源。很明显,一种是减少代码总量,可以通过禁用不必要的Drupal模块和编写高效的代码来达到这一点。另一种方式就是使用一个opcode缓存。PHP对于每个请求,都会将所有代码解析并编译成一种中间形态,在这种形态里包含了一系列的操作代码。添加一个 opcode缓存可以让PHP能够重用前面编译过的代码,这样就会跳过解析和编译。常见的opcode缓存有Alternative PHP Cache (http://pecl.php.net/package/APC), eAccelerator (http://eaccelerator.net), XCache (http://trac.lighttpd.net/xcache/), 和 Zend Platform (http://zend.com)。Zend是一个商业产品,而其它几个则是免费的。

由于Drupal是一个需要大量数据库操作的程序,所以一个opcode缓存不能作为一个单独的解决方案,但它一个整体方案中的一部份。只需要最小的努力,他人仍然可以代码明显的性能提升。


图22-1 Alternative PHP Cache (APC)带有一个接口,它能够展示内存分配情况和当前缓存中的文件。

剖析应用

通常定制的代码和模块对于小规模的站点能够很好的工作,如果将它放到大一点的站点上那么就可能成为站点的瓶颈。耗费CPU的代码循环,占用内存的算法,还有大量的数据库读取,这些都可以通过剖析你的代码来判定PHP在哪里花费了大量时间,因此,找到的关键点也就是你需要花费功夫进行调试的地方。更多关于PHP调试器和profiler的信息,参看第21章。

有时候,即便是添加了opcode并且进行了代码优化以后,你的web服务器仍然不能处理这么大的负载,那么现在你就应该换一个更强大的服务器,比如带有更多CPU或者更快的CPU,或者更换应用架构,采用多个web服务器。

Web服务器用完了RAM

Web服务器进程处理一个请求时,用到RAM的地方包括,web服务器加载所有的模块(比如Apache的mime_module, rewrite_module,等等),还有PHP解释器使用的内存。启用的web服务器和Drupal模块越多,处理单个请求耗费的RAM就越多。

因为RAM是个有限的资源,你应该决定对于每个请求分配多少内存,还有你的web服务器能够同时处理多少个请求。为了知道平均为每个请求使用多少内存,可使用一个像Unix中top一样的程序来查看你的进程列表。在Apache中,可以使用指令MaxClients来设置能够处理的最大并发请求数。一个常见的错误认为,解决满负荷的web服务器的方案是增加MaxClients的值。这只会让问题变得更加复杂,因为你将同时收到太多的请求。这意味着RAM 将被耗尽,而你的服务器将开始进行磁盘交换并开始不能响应请求。让我们假定,你的web服务器拥有2GB的内存,而每个Apache请求大约使用 20MB(对于Unix,你可以使用top来检查实际值;对于windows,则可以使用任务管理器)。通过下面的公式,你可以为MaxClients计算出一个合适的值;你要记住你需要为你的操作系统和其它进程预留一定的内存:

2GB RAM / 20MB per process = 100 MaxClients

如果禁用了不需要的web服务器模块,并且优化了定制的模块或者代码以后,你的服务器仍然耗尽内存,那么接下来你要做的是,确保数据库和操作系统不是产生瓶颈的原因。如果是由它们引起的,那么就添加更多的内存。如果不是,那么问题就很简单了,你收到的请求比你能够处理的请求要多;解决方案就是添加更多的 web服务器。

提示 由于Apache进程用到的内存,随着它的子进程增多,有逐步增加的趋势,通过将MaxRequestsPerChild的值设得小一点比如300(实际的值依赖于你所处的环境)可以收回不少的内存。Apache将会更努力的工作来生成新的子进程,而新的子进程比替换掉的子进程所需的内存要少一些,这样你就可以使用较少的内存来处理更多的请求了。MaxRequestsPerChild的默认值为0,这意味着进程永不过期。

其它web服务器最优化

为了让你的web服务器更有效的运行,这里有一些其它的措施。

Apache最优化

Apache是Drupal最常用的web服务器,通过对它进行调整可以获得更高的性能。下面的部分将给出一些可以一试的方式,供大家参考。

mod_expires

这个Apache模块将让Drupal发出ExpiresHTTP头部,在用户的浏览器中对静态文件缓存两周,或者直到一个文件存在新的版本为止。这适用于所有的图片,CSS和JavaScript文件,和其它静态文件。最终的结果是减少了带宽,而服务器需要发送的信息将会更少一些。Drupal为了使用mod_expires,对其进行了预先配置,一旦mod_expires可用,Drupal就会使用它。mod_expires的设置可以在Drupal的.htaccess文件中找到。


1 # Requires mod_expires to be enabled.
2 <IfModule mod_expires.c>
3 # Enable expirations.
4 ExpiresActive On
5 # Cache all files for 2 weeks after access (A).
6 ExpiresDefault A555-5555
7 # Do not cache dynamically generated pages.
8 ExpiresByType text/html A1
9 </IfModule>

我们不能让mod_expires缓存HTML内容,这是由于Drupal生成的HTML内容不全静态的。这也是Drupal拥有自己的内部缓存系统的原因,内置缓存系统可对它的HTML输出进行缓存(比如,页面缓存)。

将.htaccess文件中的指令迁移到httpd.conf

Drupal带有两个.htaccess文件:一个位于Drupal根路径,而另一个将被自动创建,在你创建了用于存储上传文件的目录以后,访问Administer ➤ File system来设置目录的位置,此时系统将为你自动创建一个.htaccess文件。在处理每个请求时,所有的.htaccess文件都将被搜索,读取,和解析。相反,httpd.conf只在Apache启动时才被读取。Apache指令可以放在这两种文件中。如果你能够控制你自己的服务器,你应该将.htaccess文件中的内容转移到Apache主配置文件(httpd.conf)中,并通过将AllowOverride设置为None来禁用在你的web服务器根路径下查找.htaccess文件:


1 <Directory />
2 AllowOverride None
3 ...
4 </Directory>

对于每个请求,这将阻止Apache通过遍历目录树来查找要执行的.htaccess文件。这样对于每个请求,Apache要做的工作就会有所减少,这样它就能够处理更多请求了。

其它的Web服务器

还有另外一种选项,那就是使用其它服务器来代替Apache。Benchmarks已经说明了这一点,例如,一般情况下,LightTPD web服务器每秒能够为Drupal处理更多的请求。更多详细比较,参看http://buytaert.net/drupal-webserver-configurations-compared。

数据库瓶颈

Drupal需要进行大量的数据库操作,特别是对于登录的用户和定制的模块。数据库常常会成为产生瓶颈的原因。这里有一些基本的策略用于优化Drupal中数据库的使用。

启用MySQL的查询语句缓存
MySQL 是Drupal最常用的数据库。它具有在内存中缓存常用查询语句的能力,这样一个给定的查询语句再次被调用时,MySQL将立即从缓存中将其返回。然而,在大多数MySQL中,这一特性默认是被禁用的。为了启用它,向你的MySQL配置选项文件添加以下代码;该配置文件的名称为my.cnf,它用来声明变量和你的MySQL服务器的行为(参看http://dev.mysql.com/doc/refman/5.1/en/option- files.html)。在这里,我们将查询语句缓存设为64MB:


# The MySQL server
[mysqld]
query_cache_size=64M

当前查询语句缓存的大小,可以通过MySQL的SHOW VARIABLES命令来查看:


mysql>SHOW VARIABLES;
...
| query_cache_size |555-55554
| query_cache_type | ON
...

不断的试验查询语句缓存的大小通常是有用的。缓存太小就意味着缓存了的查询语句很快就会过期。缓存太大就意味着搜索一个缓存可能需要花费相对较长的时间;还有就是使用内存进行缓存比使用其它一些方式要好,就像有更多的web服务器处理,memcache或者操作系统的文件缓存一样。

提示 在Drupal中,访问“管理➤报告➤状态报告”,点击MySQL版本号,来快速的查看一些重要的MySQL变量值。你还可以在这一页面查看,查询语句缓存是否被启用了。

识别耗费资源的查询

如果你想了解在生成一个给定页面时都发生了什么,那么devel.module就会非常有用。它拥有一个选项,用来显示生成页面所用到的所有查询语句,以及每个查询所用的时间。关于如何使用devel.module,以及通过EXPLAIN语法来识别和优化数据库查询的更详细的讨论,参看第21章。

找出执行时间过长的查询的另一种方式是,在MySQL中启用缓慢查询日志。为了启用它,需要在MySQL的配置选项文件(my.cnf)中这样设置:


# The MySQL server
[mysqld]
log-slow-queries

这会将超过10秒的查询记录到MySQL数据目录中的日志文件example.com-slow.log中去。你可以修改秒数以及日志的位置,如下面的代码所示,这里我们将缓慢查询的最小值设为5秒:


# The MySQL server
[mysqld]
long_query_time = 5
log-slow-queries = /var/log/mysql/example-slow.log

识别耗费资源的页面

识别耗费资源的页面
为了找出哪些页面是最耗费资源的,需要启用Drupal自带的统计模块。尽管统计模块增加了你的服务器的负担(由于它将你的站点的访问统计记录到了数据库中),但它能够帮助我们找出哪些页面的访问量最大,对于这些页面我们要进行更多的优化。它也可以用来追踪一个时期内生成页面的总时间,你可以在“管理➤报告➤访问日志设置”中进行声明。这可以用于识别耗费系统资源不能控制的网络爬虫,通过访问“管理➤报告➤浏览者排行”并点击 “禁止”来禁止该网络爬虫的访问。你还需要小心一点----有时候会很容易的禁用掉一个好的网络爬虫,就是能够给你的站点带来访问量的爬虫。在禁止网络爬虫以前,你一定要先检查一下它的出处。

识别耗费资源的代码
看一下下面耗费资源的代码:


01 // Very expensive, silly way to get node titles. First we get the node IDs
02 // of all published nodes.
03 $sql = "SELECT n.nid FROM {node} n WHERE n.status = 1";
04
05 // We wrap our node query in db_rewrite_sql() so that node access is respected.
06 $result = db_rewrite_sql(db_query($sql));
07
08 // Now we do a node_load() on each individual node.
09 while ($data = db_fetch_object($result)) {
10 $node = node_load($data->nid);
11 // And save the titles.
12 $titles[$node->nid] = check_plain($node->title);
13 }

完全加载一个节点是一个耗费资源的操作:运行钩子函数,通过模块处理数据库查询来添加或者修改节点,使用内存来在node_load()内部中缓存节点。如果你不依赖于其它模块对节点的修改,直接对节点表进行你自己的查询,速度将会更快一些。当然这仅仅是一个例子,但是常常会遇到同样的情景,也就是,许多时候数据是通过多个查询来取回的,而实际上可以将多个查询合并成一个简单的查询,或者不需要加载整个节点,就可以完成所要的操作。

提示 Drupal拥有一个内部的缓存机制(使用了一个静态变量),当在一个请求中多次加载同一节点时就会使用这一机制。例如,如果调用了node_load(1)。节点1将被完全加载并被缓存。当在同一个web请求中再次调用node_load(1)时,Drupal将会返回前面使用相同节点ID加载节点的缓存结果。

优化表结构

优化表结构
另外,SQL的缓慢可能是由于,第3方模块中SQL表的不良实现引起的。例如,列没有索引的话就会引起查询缓慢。一个快速查看MySQL如何执行查询的方式是,从你的缓慢查询日志中取出一个查询,在其前面加上单词EXPLAIN,然后将这个查询发给MySQL。那么结果就是得到了一个显示使用了哪些索引的表。更多信息可参看MySQL的相关书籍。

手工缓存查询语句
如果你必须要进行一些非常昂贵的查询,那么你可以在你的模块中手工的将结果缓存起来。关于Drupal缓存API的更多详细信息,参看第15章。

将表类型从MyISAM改为InnoDB
MySQL有两种常见的存储引擎,通常也称为表类型,它们是MyISAM 和InnoDB。Drupal默认使用的是MyISAM。
MyISAM 使用表级别的锁机制,而InnoDB使用行级别的锁机制。锁对于数据库的完整性非常重要;它可以避免两个数据库进程同时对同一数据进行更新操作。在实际中,锁机制策略的不同意味着当你对MyISAM表进行写操作时,整个表将被锁住。因此,在一个繁忙的Drupal站点上,当正在添加多个评论时,在插入一个新评论的同时所有的评论都不能被读取。而在InnoDB上,这就不是一个问题,因为只有正被插入的那一行被锁住了,从而允许其它的服务器线程对其它各行继续进行操作。然而,在MyISAM中,表的读取更快,而数据维护和恢复工具更加完善。MySQL表的存储架构的更多信息,参看http://dev.mysql.com/tech-resources/articles/storage-engine/part_1.html或者http://dev.mysql.com/doc/refman/5.1/en/storage-engines.html。
为了测试表级锁是不是引起性能缓慢的原因,你可以通过在MySQL中检查状态变量Table_locks_immediate和Table_locks_waited的值来分析锁的竞争程度。

mysql> SHOW STATUS LIKE 'Table%';

+-----------------------+---------+
| Variable_name         | Value     |
+-----------------------+---------+
| Table_locks_immediate |555-5555  |
| Table_locks_waited    | 15324     |
+-----------------------+---------+

Table_locks_immediate 指的是能够立即获得表级锁的次数,而Table_locks_waited指的是不能立即获取表级锁而需要等待的次数。如果 Table_locks_waited的值比较大的话,并且你遇到了性能问题,你可能希望将大表切分成小表;例如,你可以为一个定制模块创建一个专有的缓存(cache)表,或者通过其它方式来减小表的大小,或者降低表级锁命令调用的频率。对于一些表,比如cache_*,Watchdog, 和 accesslog表,减少表的大小的一种方式是减少数据的生命周期。使用Drupal的后台管理接口可以设置数据的生命周期。还有,确保每小时能够运行一次cron,从而能够不断的清理这些表中的过期数据。

因为Drupal可以运行在不同的应用下,所以不可能一刀切的具体到某个表就应该使用某个表引擎。然而,一般情况下,适合转变为InnoDB的表有cache, watchdog, sessions, 和 accesslog 表。幸运的是,转变到InnoDB上非常简单:

ALTER TABLE accesslog TYPE='InnoDB';

当然,这一转变应该在站点下线并且已经为你的数据做好备份时进行,而且你也应该首先了解InnoDB表的不同特性。

注意 尽管数据库API提供了db_lock_table() 和db_unlock_tables()函数供第3方模块使用,但是Drupal6中,核心代码并没有使用LOCK TABLES命令。

关于MySQL的性能调优,参看http://www.day32.com/MySQL/的性能调优脚本,这里提供了调整MySQL服务器变量的建议。

Memcached(内存缓存)

当数据必须使用缓慢的设备比如一个硬盘进行交互时,系统通常会遇到一个性能问题。如果你能够为数据绕过这一操作,而且你能够承受得起数据的丢失(比如session数据),那会怎么样呢?此时我们可以使用memcached,这个系统将读写操作都放到内存中进行。与本章中介绍了其它解决方案相比,Memcached更加复杂,而且更难设定。,但是当你的系统需要在可升级性方面有所提高时还是值得考虑这一方案的。

Drupal 有一个内置的数据库缓存,用来缓存页面,菜单,和其它Drupal数据,而MySQL数据库也能够缓存常用查询,但是当你的数据库不堪重负时那会怎样?你可以再买一台数据库服务器,或者你也可以直接将数据存放在内存中而不是存在数据库中,从而完全减轻数据库的重负。Memcached库(see http://www.danga.com/memcached/)和PECL Memcache PHP 扩展 (seehttp://pecl.php.net/package/memcache)都是专门为你实现这一点的工具。

Memcached 系统将任意数据都保存在随机存取的内存中,而且能够迅速的从中读取数据。使用这种方式比任何使用磁盘的方式在性能上都要好一些。Memcached存储对象并使用唯一的键来引用对象。哪些对象应该被放到memcached中,这由程序员决定。对放到Memcached中的对象,Memcached不知对象的类型和本质;在它眼中,一切都是一堆等待取回的带有键的比特数据。

系统的简单性是它的优点。当为Drupal编写支持memcached的代码时,开发者可以决定对引起瓶颈的主要因素进行缓存。这可能是,频繁出现的数据库查询的查询结果,比如路径查找,或者是更复杂的构造比如完整加载的节点和分类词汇,这些都需要许多数据库查询和大量的PHP处理才能得到。

Drupal的memcache模块和使用PECL Memcache接口的Drupal专有API可在Drupal的Memcache项目中找到(参看http://drupal.org/project/memcache)。

特定于Drupal的最优化

大多数针对Drupal的最优化措施,都在软件堆栈的其它层次中进行,也有一些专门针对Drupal本身的最优化措施,这也能使性能得到极大提升。

页面缓存
有时,一些简单的事情会被忽略掉,这也是为什么需要再次提到它们的原因。Drupal 拥有各种内置的方式,它能够通过为匿名用户存储和发送压缩了的缓存页面,来减少数据库的负重。通过启用这一缓存,你可以使用一个单独的数据库查询来高效的读取页面,而不是使用许多查询来获取页面(在没有缓存可用时就使用这种方式)。Drupal的缓存默认是禁用的,它可以在“管理➤站点配置➤性能”中配置。更多信息参看第15章。

带宽最优化
这是“管理➤站点配置➤性能”页面中的另一个性能优化措施,它能够减少发送给服务器的请求次数。通过启用 “优化CSS 文件”特性,Drupal将处理由modules创建的CSS文件,压缩它们,并将它们合并成一个文件,放到你的“文件系统路径”下的css目录中。而 “优化JavaScript文件”特性可以将多个JavaScript文件合并成一个,放到你的“文件系统路径”下的js目录中。这将减少每个页面的 HTTP请求数量,以及下载页面的整体大小。
当将一个页面存储在页面缓存中时,Drupal将会检查是否启用了页面压缩。这个特性默认是启用的,你可以在“管理➤站点配置➤性能”将其禁用。如果启用了的话,在页面存储到缓存中以前,Drupal将会检查PHP的zlib扩展(如果存在的话),并使用 gzencode($data, 9, FORCE_GZIP)对页面进行压缩。当页面从数据库中取出时,Drupal判定当前浏览器是否支持gzip编码,如果支持的话,它就简单的将缓存数据返回。否则,缓存数据在返回以前,将会使用gzinflate()进行解压处理。详情请参看includes/bootstrap.inc中的 drupal_page_cache_header()。

调优Sessions表
Drupal 将用户会话保存到了它的数据库中,而不是文件中(参看第16章)。这意味着Drupal能够很容易的应用到多个服务器上,但是由于要管理每个用户的会话信息这也增加了数据库的负担。如果一个站点每天有成千上万的用户访问,那么很容得就会看到这个表将会极速膨胀。
你可以通过PHP来控制多长时间清除一次旧的会话记录。Drupal将这一配置放到了它的settings.php文件中:


ini_set('session.gc_maxlifetime', 200000); // 55 hours (in seconds)

垃圾收集系统运行周期,默认设置为两天多点时间。这意味着如果用户两天内没有登录,那么它的会话将被删除。如果你的sessions表不断疯长,那么你需要提高PHP的会话垃圾收集系统的运行频率。


ini_set('session.gc_maxlifetime', 86400); // 24 hours (in seconds)
ini_set('session.cache_expire', 1440); // 24 hours (in minutes)

当调整session.gc_maxlifetime时,最好也将session.cache_expire设为相同的值,session.cache_expire用来控制缓存中会话页面的存活周期。注意session.cache_expire值的单位为分钟。

管理已验证用户的访问

管理已验证用户的访问
由于Drupal可以为匿名用户提供缓存了的页面,而匿名用户一般也不需要与Drupal进行交互,你可能想要减少用户登录停留的时间,或者更疯狂一点,一旦用户关闭他们的浏览器就使他们退出。通过调整settings.php文件中的cookie生存周期来做到这一点。在下面这行代码中,我们将它的值改为24小时:

ini_set('session.cookie_lifetime', 86400); // 24 hours (in seconds)

而在这里一旦用户关闭浏览我们就将他们登出:

ini_set('session.cookie_lifetime', 0); // When they close the browser.

settings.php中的默认值(2,000,000秒)能够允许用户保持登录大约3周的时间(在此期间会话垃圾收集系统不会将他们的会话记录从sessions表中删除)。

清除错误报告日志
Drupal为模块开发者提供了watchdog()函数,使用它可以将信息写入到日志中。Drupal内置了两种方式,一种是记录到数据库中,另一种是记录到syslog中。

严重性级别
调用watchdog()时,PHP代码所使用的严重性级别符合RFC 3164,如表22-1所示。

表 22-1. Drupal看门狗系统的常量和严重性级别

Drupal 常量     整数     严重性级别
WATCHDOG_EMERG     0    紧急: 系统不可用
WATCHDOG_ALERT     1    警报: 需立即采取行动
WATCHDOG_CRITICAL  2    关键: 关键条件
WATCHDOG_ERROR     3    错误:错误条件
WATCHDOG_WARNING   4    警告: 警告条件
WATCHDOG_NOTICE    5    通知: 一般的,但是重要的消息
WATCHDOG_INFO      6    信息: 一般消息
WATCHDOG_DEBUG     7    调试: 调试级别消息

记录到数据库中
Drupal内置的数据库日志模块默认是启用的,可以在“管理➤报告➤最近的日志条目”查看日志条目。数据库中的watchdog表,用来存储日志信息,如果不对其进行定期地清理的话,那么它就会快速的膨胀。如果你发现watchdog表的大小导致了你的站点运行缓慢,你可以通过在“管理➤站点配置➤日志与报警 ➤数据库日志”里来调整相关配置以减小它的大小。注意,对该设置的修改将在cron下次运行时生效。不能定期的运行cron会使得watchdog表越来越大,从而为系统增加极大的负担。

记录到Syslog
Drupal核心自带的syslog模块,默认是禁用的,它使用PHP的syslog()函数将watchdog()的调用写入到操作系统中。这一方式就绕开了数据库日志模块所需要的数据库插入操作。

运行cron

运行cron

尽管设定cron是Drupal安装指令的第5步,但是它常被忽视,而这一忽视能够给站点带来不小的麻烦。如果在一Drupal 站点上没有运行cron,那么数据库就会充满日志信息、过期的缓存数据、以及其它的统计数据,这些都是应该从系统中定期清除的。我们应该把它作为正常安装流程中的一部份,及早的配置cron,这是一个很好的实践经验。关于设定cron的更多信息,参看Drupal的INSTALL.txt文件中的步骤5。

提示 如果你处于一个非常特殊的环境下,在一个访问量很大的站点上cron却永远没有运行过或者它没有被充分的运行,你可以手工的进行一些属于cron管理的操作。你可以随时清空缓存表(TRUNCATE TABLE 'cache', TRUNCATE TABLE 'cache_filter', and TRUNCATE TABLE 'cache_page'),而它将会重新构造自己。还有,在情急之时,你可以清空watchdog和sessions表来重新控制一个失控的Drupal站点。删除watchdog记录意味着你将丢失所有的错误消息,它们可能指示站点的问题所在。如果你想保存这些数据,那么在清空表watchdog以前,先对它进行备份。清空sessions表会使当前已登录的用户退出系统。

自动节流

Drupal在核心中包含了一个名为 throttle.module的模块。这一模块通过对当前在线用户数量进行采样来测量站点的负载,如果采样显示超过了管理员设置的极值,那么它将关闭一些功能。在你配置一个站点时,最好启用这一模块,这样当一个页面成为热门话题并带来极大的访问量时,它使你能够应付这种局面。然而,节流阀模块不是一个万能药。为了进行节流,该模块本身会带来不小的负担。你也应该考虑一下其它的解决方案,比如使用memcached。

启用节流阀模块

当你启用了节流阀模块,你将会注意到在模块管理页面多了一列复选框。也就是,除了选择是否启用一个模块以外,你还可以选择它能否被节流。被节流意味着当module_list()返回了一列启用的模块时,由于访问量过大,启用了节流阀的模块将不被包含在内;被节流的模块此时将被禁用。

很明显,你将需要小心的选择你想对哪些模块进行节流。一般选择功能不重要但是耗费CPU时间或者许多数据库查询的模块。核心模块不能被节流(因为它们是Drupal正常运行所必需的),但是它们能在站点处于节流时,够意识到节流并使用它们自己的措施用来降低处理时间。例如,区块模块不能被节流,但是独立的区块可以被节流,如图22-2所示。


图22-2 当站点处于大的负载时,它将不展示头部的搜索表单和右边栏中的“Who’s new” 和 “Who’s online”区块,但是左边栏的导航和用户登录区块以及页脚的“Powered by Drupal”区块总是被显示的。

配置节流阀模块

为了使节流机制能够起作用,你必须为其提供一个阀值和一个采样频率。当启用了节流阀模块时,阀值可以在“管理➤站点配置➤节流阀”中设置。

设置阀值

可以输入两个阀值:节流开始所需要的最小匿名用户数和节流开始所需要的最小登录用户数。由于匿名用户占用的资源比验证用户小,所以匿名用户的阀值应该更高一些。实际值则依赖于你的个人站点。用户数必须是在一个给定的时间内测量的。这个时间周期在“Who’s online”区块中设置,并作为Drupal变量user_block_seconds_online存储起来。如果它没有被设置,那它默认为900秒(15分钟),如图22-3所示。


图 22-3.用户最后一次访问以后仍被作为“在线”的时间周期,可以在“Who’s online”区块设置的User activity字段中进行设置。

设置采样频率

为了判定站点的负载量,以决定是打开还是关闭节流机制,节流阀模块必须查询数据库。这为数据库服务器增加了额外的负担。使用“Auto-throttle probability limiter”来设置检查的频率(实际中有可能检查发生在一个给定请求上)。例如,选择20%,那么对于每5个请求就会采样一次。

使得模块和主题懂得节流(Throttle-Aware)

节流机制可能开着,也可能关着。当你编写自己的模块和主题时,你可以对节流阀的状态进行判断,例如:


1 // Get throttle status.
2 // We use module_invoke() instead of calling throttle_status() directly
3 // so this will still work when throttle.module is disabled.
4 $throttle = module_invoke('throttle', 'status');
5
6 if (!$throttle) {
7 // Throttle is off.
8 // Do nonessential CPU-intensive task here.
9 }

提示 如果你拥有大量的多媒体文件,这些文件不重要,但又是主题的一部分,需要提供给用户,当你的网站不堪重负时,你可以对这些文件进行节流来减少带宽的总量。

架构

Drupal可用的架构就是那些其它的LAM堆栈软件,以及使得Drupal具有可升级性的技术。因此,我们将为你讲述不同的架构,并主要针对Drupal来讨论相关的技巧。

单个服务器

这是最简单的架构。Web服务器和数据库运行在同一个服务器上。服务器可能是一个共享主机或者一个专用主机。尽管大多数Drupal站点能够在共享主机上很好的运转,如果期望具有一定的升级性的话,就应该把它放到专有主机上。

在单主机架构下,配置非常简单,因为所有的东西都已设置好了。同样的,web服务器和数据库之间的通信非常快,这是由于不需要使用网络来传播数据,所以避免了由此带来的时间延迟。很明显,如果能够使用多核处理器那就更好了,这样web服务器和数据库之间就不需要争抢处理器了。

独立的数据库服务器

如果数据库是你的瓶颈,那么你可能就需要一个单独的强大的数据库服务器了。由于需要使用网络来发送请求,所以会影响性能,但是可升级性将会提高。

注意 无论什么时候你在使用多个服务器,你都需要确保使用一个快速的本地网络将它们连接起来。

独立的数据库服务器和web服务器集群

独立的数据库服务器和web服务器集群
多个web服务器具有更好的容错性,并能处理更多的访问。集群所需的最小计算机数量是2个web服务器。还有,你需要有一种方式能够用来在服务器之间切换流量。而当其中的一个机器不能工作时,集群中其余的机器能够处理整个负载。

负载均衡

负载均衡器能够将web请求分配到多个web服务器上。还有一些其它类型的负载均衡器用来分发其它的资源,比如硬盘和数据库,但在这里,我们仅仅讨论对HTTP请求的分发。在多个web服务器的情况下,当一个web服务器当机或者处于维护状态时,负载均衡器允许web服务继续运行。

负载均衡器可分为两大类。软件负载均衡器非常便宜甚至免费,但是它的维护和管理费用高于硬件负载均衡器。Linux Virtual Server (http://www.linuxvirtualserver.org/)是一个非常流行的Linux负载均衡器。硬件负载均衡器一般很昂贵,因为与基于软件的解决方案相比,它们包含了更高级的服务器切换算法并具有更好的可靠性。

除了负载均衡,多个服务器还带来了一些其它问题,主要包括文件上传和保持代码在服务器间的同步。

文件上传和同步

文件上传和同步
当Drupal运行在单个web服务器上时,上传的文件一般存储在Drupal的files(文件)目录中。它的位置可在“管理➤站点配置➤文件系统”里配置。对于多个web服务器,则需要避免下面的场景:

1. 一个用户在web服务器A上,上传了一个文件;数据库被更新以反映这一情况。
2. 一个用户在web服务器B上查看一个页面时,引用了这个新文件。文件未找到!

很明显,答案就是将文件也同步到web服务器B上。有多种方式。

使用rsync

Rsync程序是一个解决方案,它通过仅仅复制修改了的文件来保持两个目录间的同步。更多信息,参看http://samba.anu.edu.au/rsync/。这种方式的不足之处是,同步会带来延迟,还有所有上传了的文件都有多个副本(因此增加了存储成本)。

提示 如果你有很多文件并定期的调度rsyncs,通过检查表file和upload,当文件未被修改时,不同步;文件被修改时,同步。

使用一个共享的固定的文件系统

与其在多个服务器间同步文件系统,你不如部署一个共享的固定的文件系统,它将文件存放在文件服务器上的一个单独的位置中。接着,web 服务器可以使用一个协议比如网络文件系统(NFS)来安放文件。这种方式的优点有,能够很容易的添加廉价的web服务器,而资源将被集中存放在一个耐用的文件服务器上,它上面可以带有冗余存储系统比如RAID 5。这个系统的主要缺点是,仅有一个失败点;如果你的服务器或者文件系统出了问题,那么就会影响整个站点,除非你创建一个文件服务器集群。

如果需要提供大量的多媒体文件,最好将这些文件存放在一个单独的服务器上,可以使用一个轻量级的服务器比如Lighttpd,从而减轻你的web服务器的负担,使得Drupal能够处理更多的请求。做到这一点的一个简单的方式是,在你的web服务器上使用一个重写(rewrite)规则,将到来的针对特定文件类型的所有请求重定向到静态服务器上。下面是Apache的重写(rewrite)规则的一个例子,它重写了所有针对JPEG文件的请求:


RewriteCond %{REQUEST_URI} ^/(.*\.jpg)$ [NC]
RewriteRule .* http://static.example.com/%1 [R]

这种方式的不足是,web服务器仍然需要处理额外的工作——将请求重定向到文件服务器上。一个改进的方案是,在Drupal内部重写所有文件的URLs,这样web服务器就不再参与静态文件请求了。然而,现在,在Drupal内核里还没有一个简单的方式来进行修改。

超越单个文件系统

如果存储总量不断增长,以至于超过了单个文件系统能够承受的范围,你可以通过编写定制的代码来实现一个存储抽象层,从而满足需求。另一种选择是使用一个外部的存储系统比如Amazon的S3服务。

多个数据库服务器

多个数据库服务器带来了额外的复杂性,因为数据将被重复插入和更新,或者数据库被分割到多个服务器中。

数据库复制

MySQL中的数据库复制,一个单独的主数据库接收所有的写操作,然后这些写操作将被复制到一个或多个从数据库上。读操作可以在任何主数据库或者从数据库上进行。在一个多层架构中,从数据库也可以是主数据库。

当前,在一个能够复制的数据库环境下运行Drupal的一个难点是,Drupal不能区分读和写操作。然而,由于所有的数据库查询都要通过数据库层,通过扫描查询中的关键字ALTER, CREATE, DELETE, FLUSH, INSERT, LOCK, UPDATE,等等,也不难做到这一点,从而将查询分发给合适的数据库。通过在http://drupal.org搜索“replication”可以找到这种方式的一些例子,另外还有一篇博客也值得一读http://buytaert.net/database-replication-lag。

数据库分割

由于Drupal可以处理多个数据库链接,为了增加你的数据库架构的可升级性,另一种策略是将一些表放在一个机子上的一个数据库中,将另一些表放到另一个机子上的不同数据库中。例如,将所有的cache表分离到一个独立的机子上的独立的数据库中,对于所有使用这些表的查询,使用Drupal的表前缀机制来对查询应用别名,从而提高你站点的可升级性。

总结

在本章,你学到以下几点:

  • 如何发现性能瓶颈
  • 如何优化一个web服务器
  • 如何优化一个数据库
分享到:
评论

相关推荐

    Drupal专业开发指南.pdf

    - **描述:** 实施Drupal优化的整体策略。 - **详细内容:** 包括如何评估站点性能瓶颈、如何制定合理的优化计划、如何监控优化效果等。 #### 二十、Drupal安装过程 **知识点41:安装步骤** - **描述:** Drupal的...

    drupal-9.0.1_drupal9_drupal9教程_drupal9开发实例_

    这个9.0.1版本的发布,是Drupal社区对持续创新和优化的体现。 Drupal 9的更新主要包括以下几个方面: 1. **向后兼容性**:Drupal 9.0.1在设计时考虑了向后兼容性,这意味着从Drupal 8升级到9的过程相对平滑,无需...

    Drupal7宝典+Drupal开发指南+Using Drupal

    这本书全面覆盖了Drupal7的基础知识,包括安装与配置、模块开发、主题设计、网站性能优化等。它将帮助你了解Drupal7的核心概念,如节点、用户、角色和权限,以及如何使用内置的功能来搭建网站。你将学习如何使用 ...

    Drupal data Drupal data

    Drupal 是一个强大的开源内容管理框架,它用于构建各种类型的网站,从小型个人博客到大型企业级应用程序。在“Drupal data Drupal data”的标题和描述中...深入了解这些知识点对于有效地管理和优化Drupal网站至关重要。

    drupal7与drupal6版本修改内容

    从 Drupal 6 升级到 Drupal 7,Drupal 社区引入了大量的改进和新功能,以提高用户体验、增强安全性以及优化开发者的开发体验。本文将详细探讨 Drupal 7 相比于 Drupal 6 的主要变化,包括代码、配置、用户界面(UI)...

    drupal高级开发手册

    - **环境优化**:提供关于如何优化Drupal性能的建议,包括缓存机制设置、数据库优化等。 #### 四、Drupal模块开发 - **模块生命周期**:解释Drupal模块的工作原理,包括启动、配置、钩子(Hooks)等关键概念。 - **...

    drupal6版本(这是drupal6)

    6. **XML-Sitemap**:Drupal 6内置XML Sitemap模块,有利于搜索引擎优化。 7. **WYSIWYG编辑器**:通过安装第三方模块,如CKEditor或FCKeditor,可以实现所见即所得的编辑体验。 **三、Devel模块** 在提供的...

    drupal-7.23安装包

    10. **性能优化**:Drupal 7.23 可以通过缓存、页面压缩、数据库查询优化等方式提高性能。还可以使用像 Varnish 或 Memcached 这样的外部缓存解决方案,以及 Drupal 模块如 Boost 或 Page Cache 来进一步加速网站。 ...

    Drupal资料大全(推荐几本不错的drupal电子书)

    5. **《Drupal源码分析》**:理解Drupal的源码有助于你更好地定制和优化网站。这本书通过深入解析核心代码,揭示了Drupal的工作原理,有助于提升你的问题解决能力。 6. **《Drupal 8 API指南》**:Drupal 8提供了...

    drupal 6.28 的包

    6. **搜索优化**:内置的搜索功能和对SEO(搜索引擎优化)的支持,帮助网站提高在搜索引擎中的排名。 7. **APIs**:Drupal 6提供了一系列API,如数据库API、表单API、菜单API,方便开发者进行扩展和集成其他服务。 ...

    一本关于Drupal 7的英文书 Beginning Drupal 7

    ### 关于《Beginning Drupal 7》的知识点梳理 #### 一、书籍基本信息 - **书名**:《Beginning Drupal 7》 - **作者**:Todd Tomlinson - **出版社**:Apress - **出版年份**:2010年 - **ISBN-13(纸质版)**:...

    Drupal宝典.doc

    - **搜索引擎友好的URL结构**:Drupal内置的URL优化功能,有助于提升网站在搜索引擎中的排名。 - **丰富的模块生态系统**:从短消息、个性化书签、网站管理到Blog、电子商务、电子出版,Drupal提供了多样化的模块,...

    drupal 7 中文版

    Drupal 7 中文版是全球知名的开源内容管理系统(CMS)Drupal的一个特定版本,它特别针对中文用户进行了优化,包括提供完整的中文语言包。这个版本,7.38,是Drupal 7系列的一个稳定更新,旨在增强用户体验,提高系统...

    drupal-7.38.tar

    7. **高性能**:Drupal 7 优化了数据库查询,提高了网站的加载速度,适合构建大型、高流量的网站。 8. **社区支持**:Drupal 有一个庞大的开发者社区,不断贡献新的模块、主题和解决方案,提供技术支持和问题解答。...

    drupal数据库设计图

    综上所述,"drupal数据库设计图"是理解Drupal CMS架构的宝贵资源,它能够使开发者更快地熟悉系统,提高开发效率,并为维护和优化提供有力支持。对于任何想要深入Drupal的人来说,都应该花时间研究和理解这种设计图。

    Beginning.Drupal.8

    8. **优化与性能**:了解如何优化Drupal 8站点的性能,包括缓存策略、数据库查询优化、页面加载速度提升等。 9. **安全与维护**:Drupal的安全最佳实践,包括代码审计、更新管理、备份恢复和防止常见攻击的方法。 ...

    Drupal安装与升级教程

    在实践中,你可能还会遇到更多关于Drupal的主题定制、模块开发、性能优化等方面的问题,持续学习和探索是提升Drupal技能的关键。同时,Drupal社区提供了丰富的资源和热情的用户,可以帮助你在使用过程中解决各种问题...

Global site tag (gtag.js) - Google Analytics