买回ipod classic 120G也有两个多月了吧。昨天晚上听完歌后,就直接睡眠了。
今天早上乘公车发现黑屏。以为是昨天晚上误按导致启动后电全部用完。
因为身边没带数据线,所以无法操作。
晚上回到家中,插上机器,发现仍然是黑屏(上次没电的时候,还是可以点亮,并提示不要拔机器的。)这回,全黑了,一点反应没有。。。
紧张啊。itunes打开一看,发现quicktime被我删除,无法启动。。。
只能先google了。找到相应的提示:按住MENU+当中的按钮。长按,过了好久,终于出现一个暗暗的苹果标志。
然后打开移动硬盘(也就是苹果的磁盘),数据还在。。。
激动啊。看来苹果的东西也是会经常死机的嘛。。
看到网上很多人都说无法激活,然后送修,花了N多钱后,还是很安慰。省下一笔开销了。虽然可能在保修期内是免费的,但要跑到售后点,太累了。天又热。
解决了。安心了。睡觉了。
补天网上的一个软件,适合给那些中了木马的朋友们使用。
我没有试用,我只是看他介绍里有一句:可以使用 Perl 风格的正则表达式,支持命令行参数,可以用 XML 保存结果,可以将 Perl 脚本转换到 Unix 平台
下载地址:http://www.butian.org/soft/731.html
图片介绍:
介绍内容:
一个功能超强的文本查找和替换工具。它可以使用类似于搜索引擎的查询方式在多个文档中搜索和替换整段文本!
你可以使用不同的扩展名过滤要搜索的文件,定义类似于搜索引擎语法的搜索查询。此外你可以从多个文件中插入,替换和删除由好几行所组成的文本块。
其它的功能比如:可以使用 Perl 风格的正则表达式,支持命令行参数,可以用 XML 保存结果,可以将 Perl 脚本转换到 Unix 平台。
本版本不是最新版本,而是2.0中文正式版,3.0开始AFR还支持搜索OFFICE WORD EXCEL等,有意向的朋友可以自行搜索下载。
.abu.点评:
推荐这个工具的主要原因是一次朋友的网站被批量挂马,我意外的发现,每个页面挂的木马的代码都不一样,所以无法批量删除,最终才向我求助。
在补天areone的帮助下,我通过AFR这个支持正则表达式的文本查找替换工具,批量删除了木马。
建议网站管理员配备一下。
这是cssrain站长翻译的一篇文章,事实上,在PHP中,已经不太建议使用switch-case了。
特别是在面向OO的代码中,你几乎也看不到这样的代码出现
不是说这个方式不好。而是,它的可扩展性不强。所以在大多数情况下,都放弃采用这种方式。
以下是翻译内容,来源于:http://www.cssrain.cn/article.asp?id=1384:
我很年轻,还没有做过很长的编程。所以我对使用switch-case 语法没有什么很深刻的印象,至少在我的记忆中是这样。或许你认为这是一件坏事情。你甚至会怀疑我为什么不使用它们。我真的不知道为什么,似乎我天生就不喜欢使用它,如下所示:
JavaScript代码
- switch (something) {
- case 1:
- doX();
- break;
- case 2:
- doY();
- break;
- case 3:
- doN();
- break;
-
- }
显然,虚构此代码的作者不够了解使用其他JavaScript方法来构建此功能。其实有很多种方式更适合这种情况,而不是一个丑陋的switch. 有许多许多更轻松,更优雅的方式来实现这种功能。
switch-case组合肯定是非常有用的,当你有一个变量并且依靠它的值的不同来做不同的事情。使用多个if-else不太恰当,所以人们通常使用switch-case来代替多个if-else.我敢肯定你也是.
上面的例子依赖于 something 判断 ,然后根据条件运行doX , doY或doN 。在JavaScript中,同样的逻辑可以表示一个简单的查找表的形式————对象,如下所示:
JavaScript代码
- var cases = {
- 1: doX,
- 2: doY,
- 3: doN
- };
- if (cases[something]) {
- cases[something]();
- }
这不仅简洁,而且也可以重复使用和修改条件。所有条件都是对象的一部分,因此,如果您需要改变某些条件那就非常简单了。
所以,我想说的是:请不要使用switch-case,除非绝对必要的。 为什么? 因为有更好的替代品,比它更简单!
关于“ switch-case”的语法,请浏览:http://en.wikipedia.org/wiki/Switch_statement
如果想阅读原文,请点击这里:http://james.padolsey.com/javascript/how-to-avoid-switch-case-syndrome/
提示:译文跟原文有出入,请看原文。
文章很长。请慢慢看,有部分因为没有接触过,所以不懂。。。
当成学习资料吧。。
影响web服务器性能的最大的因素是内存。一个web服务器应该从不使用交换机制,因为交换产生的滞后使用户总感觉"不够快",所以用户就可能去按"停止"和"刷新",从而带来更大的负载。你可以,也应该,控制MaxClients
的设置,以避免服务器产生太多的子进程而发生交换。这个过程很简单:通过top
命令计算出每个Apache进程平均消耗的内存,然后再为其它进程留出足够多的内存。
其他因素就很普通了,装一个足够快的CPU,一个足够快的网卡,几个足够快的硬盘,这里说的"足够快"是指能满足实际应用的需求。
操作系统是很值得关注的又一个因素,已经被证实的很有用的经验有:
-
选择能够得到的最新最稳定的版本并打好补丁。近年来,许多操作系统厂商都提供了可以显著改善性能的TCP协议栈和线程库。
-
如果你的操作系统支持sendfile()
系统调用,则务必安装带有此功能的版本或补丁(译者注:Linux2.4内核支持sendfile()系统调用,但2.6内核已经不再支持;对Solaris8的早期版本,则需要安装补丁)。在支持sendfile
的系统中,Apache2可以更快地发送静态内容而且占用较少的CPU时间。
在Apache1.3以前的版本中,HostnameLookups
默认被设为On
。它会带来延迟,因为对每一个请求都需要作一次DNS查询。在Apache1.3中,它被默认地设置为Off
。如果需要日志文件提供主机名信息以生成分析报告,则可以使用日志后处理程序logresolve
,以完成DNS查询,而客户端无须等待。
推荐你最好是在其他机器上,而不是在web服务器上执行后处理和其他日志统计操作,以免影响服务器的性能。
如果你使用了任何"Allow
from domain
"或"Deny
from domain
"指令(也就是domain
使用的是主机名而不是IP地址),则代价是要进行两次DNS查询(一次正向和一次反向,以确认没有作假)。所以,为了得到最高的性能,应该避免使用这些指令(不用域名而用IP地址也是可以的)。
注意,可以把这些指令包含在<Location /server-status>
段中使之局部化。在这种情况下,只有对这个区域的请求才会发生DNS查询。下例禁止除了.html
和.cgi
以外的所有DNS查询:
HostnameLookups off
<Files ~ "\.(html|cgi)$">
HostnameLookups on
</Files>
如果在某些CGI中偶尔需要DNS名称,则可以调用gethostbyname
来解决。
如果网站空间中没有使用Options FollowSymLinks
,或使用了Options SymLinksIfOwnerMatch
,Apache就必须执行额外的系统调用以验证符号连接。文件名的每一个组成部分都需要一个额外的调用。例如,如果设置了:
DocumentRoot /www/htdocs
<Directory />
Options SymLinksIfOwnerMatch
</Directory>
在请求"/index.html
"时,Apache将对"/www
"、"/www/htdocs
"、"/www/htdocs/index.html
"执行lstat()
调用。而且lstat()
的执行结果不被缓存,因此对每一个请求都要执行一次。如果确实需要验证符号连接的安全性,则可以这样:
DocumentRoot /www/htdocs
<Directory />
Options FollowSymLinks
</Directory>
<Directory /www/htdocs>
Options -FollowSymLinks +SymLinksIfOwnerMatch
</Directory>
这样,至少可以避免对DocumentRoot
路径的多余的验证。注意,如果Alias
或RewriteRule
中含有DocumentRoot
以外的路径,那么同样需要增加这样的段。为了得到最佳性能,应当放弃对符号连接的保护,在所有地方都设置FollowSymLinks
,并放弃使用SymLinksIfOwnerMatch
。
如果网站空间允许覆盖(通常是用.htaccess
文件),则Apache会试图对文件名的每一个组成部分都打开.htaccess
,例如:
DocumentRoot /www/htdocs
<Directory />
AllowOverride all
</Directory>
如果请求"/index.html
",则Apache会试图打开"/.htaccess
"、"/www/.htaccess
"、"/www/htdocs/.htaccess
"。其解决方法和前面所述的Options FollowSymLinks
类似。为了得到最佳性能,应当对文件系统中所有的地方都使用AllowOverride None
。
实践中,内容协商的好处大于性能的损失,如果你很在意那一点点的性能损失,则可以禁止使用内容协商。但是仍然有个方法可以提高服务器的速度,就是不要使用通配符,如:
而使用完整的列表,如:
DirectoryIndex index.cgi index.pl index.shtml index.html
其中最常用的应该放在前面。
还有,建立一个明确的type-map
文件在性能上优于使用"Options MultiViews
",因为所有需要的信息都在一个单独的文件中,而无须搜索目录。请参考内容协商文档以获得更详细的协商方法和创建type-map
文件的指导。
内存映射
在Apache2.0需要搜索被发送文件的内容时,比如处理服务器端包含时,如果操作系统支持某种形式的mmap()
,则会对此文件执行内存映射。
在某些平台上,内存映射可以提高性能,但是在某些情况下,内存映射会降低性能甚至影响到httpd的稳定性:
如果有上述情况发生,则应该使用EnableMMAP off
关闭对发送文件的内存映射。注意:此指令可以被针对目录的设置覆盖。
Sendfile
在Apache2.0能够忽略将要被发送的文件的内容的时候(比如发送静态内容),如果操作系统支持sendfile()
,则Apache将使用内核提供的sendfile()
来发送文件。译者注:Linux2.4内核支持sendfile()系统调用,但2.6内核已经不再支持。
在大多数平台上,使用sendfile可以通过免除分离的读和写操作来提升性能。然而在某些情况下,使用sendfile会危害到httpd的稳定性
如果出现以上情况,你应当使用"EnableSendfile off
"来禁用sendfile 。注意,这个指令可以被针对目录的设置覆盖。
在Apache1.3以前,MinSpareServers
,MaxSpareServers
,StartServers
的设置对性能都有很大的影响。尤其是为了应对负载而建立足够的子进程时,Apache需要有一个"渐进"的过程。在最初建立StartServers
数量的子进程后,为了满足MinSpareServers
设置的需要,每一秒钟只能建立一个子进程。所以,对一个需要同时处理100个客户端的服务器,如果StartServers
使用默认的设置5
,则为了应对负载而建立足够多的子进程需要95秒。在实际应用中,如果不频繁重新启动服务器,这样还可以,但是如果仅仅为了提供10分钟的服务,这样就很糟糕了。
" 一秒钟一个"的规定是为了避免在创建子进程过程中服务器对请求的响应停顿,但是它对服务器性能的影响太大了,必须予以改变。在Apache1.3中,这 个"一秒钟一个"的规定变得宽松了,创建一个进程,等待一秒钟,继续创建第二个,再等待一秒钟,继而创建四个,如此按指数级增加创建的进程数,最多达到每 秒32个,直到满足MinSpareServers
设置的值为止。
从多数反映看来,似乎没有必要调整MinSpareServers
,MaxSpareServers
,StartServers
。如果每秒钟创建的进程数超过4个,则会在ErrorLog
中产生一条消息,如果产生大量此消息,则可以考虑修改这些设置。可以使用mod_status
的输出作为参考。
与进程创建相关的是由MaxRequestsPerChild
引发的进程的销毁。其默认值是"0
",意味着每个进程所处理的请求数是不受限制的。如果此值设置得很小,比如30,则可能需要大幅增加。在SunOS或者Solaris的早期版本上,其最大值为10000
以免内存泄漏。
如果启用了持久链接,子进程将保持忙碌状态以等待被打开连接上的新请求。为了最小化其负面影响,KeepAliveTimeout
的默认值被设置为5
秒,以谋求网络带宽和服务器资源之间的平衡。在任何情况下此值都不应当大于60
秒,参见most of the benefits are lost。
选择一个MPM
Apache 2.x 支持插入式并行处理模块,称为多路处理模块(MPM)。在编译Apache时你必须选择也只能选择一个MPM,这里有几个针对非UNIX系统的MPM:beos
,mpm_netware
,mpmt_os2
,mpm_winnt
。对类UNIX系统,有几个不同的MPM可供选择,他们都会影响到httpd的速度和可伸缩性:
worker
MPM使用多个子进程,每个子进程中又有多个线程。每个线程处理一个请求。该MPM通常对高流量的服务器是一个不错的选择。因为它比prefork
MPM需要更少的内存且更具有伸缩性。
prefork
MPM使用多个子进程,但每个子进程并不包含多线程。每个进程只处理一个链接。在许多系统上它的速度和worker
MPM一样快,但是需要更多的内存。这种无线程的设计在某些情况下优于worker
MPM:它可以应用于不具备线程安全的第三方模块(比如php3/4/5),且在不支持线程调试的平台上易于调试,而且还具有比worker
MPM更高的稳定性。
关于MPM的更多内容,请参考其文档。
既然内存用量是影响性能的重要因素,你就应当尽量去除你不需要的模块。如果你将模块编译成DSO,取消不必要的模块就是一件非常简单的事情:注释掉LoadModule
指令中不需要的模块。
如果你已经将模块静态链接进Apache二进制核心,你就必须重新编译Apache并去掉你不想要的模块。
增减模块牵涉到的一个问题是:究竟需要哪些模块、不需要哪些模块?这取决于服务器的具体情况。一般说来,至少要包含下列模块:mod_mime
,mod_dir
,mod_log_config
。你也可以不要mod_log_config
,但是一般不推荐这样做。
原子操作
一些模块,比如mod_cache
和worker
使用APR(Apache可移植运行时)的原子API。这些API提供了能够用于轻量级线程同步的原子操作。
默 认情况下,APR在每个目标OS/CPU上使用其最有效的特性执行这些操作。比如许多现代CPU的指令集中有一个原子的比较交换(compare- and-swap, CAS)操作指令。在一些老式平台上,APR默认使用一种缓慢的、基于互斥执行的原子API以保持对没有CAS指令的老式CPU的兼容。如果你只打算在新 式的CPU上运行Apache,你可以在编译时使用--enable-nonportable-atomics
选项:
./buildconf
./configure --with-mpm=worker --enable-nonportable-atomics=yes
--enable-nonportable-atomics
选项只和下列平台相关:
- SPARC上的Solaris
默认情况下,APR使用基于互斥执行的原子操作。如果你使用--enable-nonportable-atomics
选项,APR将使用SPARC v8plus操作码来加快基于硬件的CAS操作。注意,这仅对UltraSPARC CPU有效。
- x86上的Linux
默认情况下,APR在Linux上使用基于互斥执行的原子操作。如果你使用--enable-nonportable-atomics
选项,APR将使用486操作码来加快基于硬件的CAS操作。注意,这仅对486以上的CPU有效。
mod_status 和 "ExtendedStatus On"
如果Apache在编译时包含了mod_status
,而且在运行时设置了"ExtendedStatus On
",那么Apache会对每个请求调用两次gettimeofday()
(或者根据操作系统的不同,调用times()
)以及(1.3版之前)几个额外的time()
调用,使状态记录带有时间标志。为了得到最佳性能,可以设置"ExtendedStatus off
"(这也是默认值)。
多socket情况下的串行accept
警告
这部分内容尚未完全根据Apache2.0中的变化进行更新 。一些信息依然有效,使用中请注意。
这里要说的是 Unix socket API 的一个缺点。假设web服务器使用了多个Listen
语句监听多个端口或者多个地址,Apache会使用select()
以检测每个socket是否就绪。select()
会表明一个socket有零或至少一个连接正等候处理。由于Apache的模型是多子进程的,所有空闲进程会同时检测新的连接。一个很天真的实现方法是这样的(这些例子并不是源代码,只是为了说明问题而已):
for (;;) {
for (;;) {
fd_set accept_fds;
FD_ZERO (&accept_fds);
for (i = first_socket; i <= last_socket; ++i) {
FD_SET (i, &accept_fds);
}
rc = select (last_socket+1, &accept_fds, NULL, NULL, NULL);
if (rc < 1) continue;
new_connection = -1;
for (i = first_socket; i <= last_socket; ++i) {
if (FD_ISSET (i, &accept_fds)) {
new_connection = accept (i, NULL, NULL);
if (new_connection != -1) break;
}
}
if (new_connection != -1) break;
}
process the new_connection;
}
这种天真的实现方法有一个严重的"饥饿"问题。如果多个子进程同时执行这个循环,则在多个请求之间,进程会被阻塞在select
,随即进入循环并试图accept
此连接,但是只有一个进程可以成功执行(假设还有一个连接就绪),而其余的则会被阻塞在accept
。这样,只有那一个socket可以处理请求,而其他都被锁住了,直到有足够多的请求将它们唤醒。此"饥饿"问题在PR#467中有专门的讲述。目前至少有两种解决方案。
一种方案是使用非阻塞型socket ,不阻塞子进程并允许它们立即继续执行。但是这样会浪费CPU时间。设想一下,select
有10个子进程,当一个请求到达的时候,其中9个被唤醒,并试图accept
此连接,继而进入select
循环,无所事事,并且其间没有一个子进程能够响应出现在其他socket上的请求,直到退出select
循环。总之,这个方案效率并不怎么高,除非你有很多的CPU,而且开了很多子进程。
另一种也是Apache所使用的方案是,使内层循环的入口串行化,形如(不同之处以高亮显示):
for (;;) {
accept_mutex_on ();
for (;;) {
fd_set accept_fds;
FD_ZERO (&accept_fds);
for (i = first_socket; i <= last_socket; ++i) {
FD_SET (i, &accept_fds);
}
rc = select (last_socket+1, &accept_fds, NULL, NULL, NULL);
if (rc < 1) continue;
new_connection = -1;
for (i = first_socket; i <= last_socket; ++i) {
if (FD_ISSET (i, &accept_fds)) {
new_connection = accept (i, NULL, NULL);
if (new_connection != -1) break;
}
}
if (new_connection != -1) break;
}
accept_mutex_off ();
process the new_connection;
}
函数accept_mutex_on
和accept_mutex_off
实现了一个互斥信号灯,在任何时刻只被为一个子进程所拥有。实现互斥的方法有多种,其定义位于src/conf.h
(1.3以前的版本)或src/include/ap_config.h
(1.3或以后的版本)中。在一些根本没有锁定机制的体系中,使用多个Listen
指令就是不安全的。
AcceptMutex
指令被用来改变在运行时使用的互斥方案。
AcceptMutex flock
-
这种方法调用系统函数flock()
来锁定一个加锁文件(其位置取决于LockFile
指令)。
AcceptMutex fcntl
-
这种方法调用系统函数fcntl()
来锁定一个加锁文件(其位置取决于LockFile
指令)。
AcceptMutex sysvsem
-
(1.3及更新版本)这种方案使用SysV风格的信号灯以实现互斥。不幸的是,SysV风格的信号灯有一些副作用,其一是,Apache有可能不能在结束以前释放这种信号灯(见ipcs()
的man page),另外,这种信号灯API给与网络服务器有相同uid的CGI提供了拒绝服务攻击的机会(所有CGI,除非用了类似suexec
或cgiwrapper
)。鉴于此,在多数体系中都不用这种方法,除了IRIX(因为前两种方法在IRIX中代价太高)。
AcceptMutex pthread
-
(1.3 及更新版本)这种方法使用了POSIX互斥,按理应该可以用于所有完整实现了POSIX线程规范的体系中,但是似乎只能用在Solaris2.5及更新版 本中,甚至只能在某种配置下才正常运作。如果遇到这种情况,则应该提防服务器的挂起和失去响应。只提供静态内容的服务器可能不受影响。
AcceptMutex posixsem
-
(2.0及更新版本)这种方法使用了POSIX信号灯。如果一个运行中的线程占有了互斥segfault ,则信号灯的所有者将不会被恢复,从而导致服务器的挂起和失去响应。
如果你的系统提供了上述方法以外的串行机制,那就可能需要为APR增加代码(或者提交一个补丁给Apache)。
还 有一种曾经考虑过但从未予以实施的方案是使循环部分地串行化,即只允许一定数量的进程进入循环。这种方法仅在多个进程可以同时进行的多处理器的系统中才是 有价值的,而且这样的串行方法并没有占用整个带宽。它也许是将来研究的一个领域,但是由于高度并行的网络服务器并不符合规范,所以其被优先考虑的程度会比 较低。
当然,为了得到最佳性能,最后就根本不使用多个Listen
语句。但是上述内容还是值得读一读。
单socket情况下的串行accept
上述对多socket的服务器进行了一流的讲述,那么对单socket的服务器又怎样呢?理论上似乎应该没有什么问题,因为所有进程在连接到来的时候可以由accept()
阻塞,而不会产生进程"饥饿"的问题,但是在实际应用中,它掩盖了与上述非阻塞方案几乎相同的问题。按大多数TCP栈的实现方法,在单个连接到来时,内核实际上唤醒了所有阻塞在accept
的进程,但只有一个能得到此连接并返回到用户空间,而其余的由于得不到连接而在内核中处于休眠状态。这种休眠状态为代码所掩盖,但的确存在,并产生与多socket中采用非阻塞方案相同的负载尖峰的浪费。
同时,我们发现在许多体系结构中,即使在单socket的情况下,实施串行化的效果也不错,因此在几乎所有的情况下,事实上就都这样处理了。在Linux(2.0.30,双Pentium pro 166/128M RAM)下的测试显示,对单socket,串行化比不串行化每秒钟可以处理的请求少了不到3%,但是,不串行化对每一个请求多了额外的100ms的延迟,此延迟可能是因为长距离的网络线路所致,并且仅发生在LAN中。如果需要改变对单socket的串行化,可以定义SINGLE_LISTEN_UNSERIALIZED_ACCEPT
,使单socket的服务器彻底放弃串行化。
延迟的关闭
正如draft-ietf-http-connection-00.txtsection 8所述,HTTP服务器为了可靠地实现此协议,需要单独地在每个方向上关闭通讯(重申一下,一个TCP连接是双向的,两个方向之间是独立的)。在这一点上,其他服务器经常敷衍了事,但从1.2版本开始被Apache正确实现了。
但是增加了此功能以后,由于一些Unix版本的短见,随之也出现了许多问题。TCP规范并没有规定FIN_WAIT_2
必须有一个超时,但也没有明确禁止。在没有超时的系统中,Apache1.2经常会陷于FIN_WAIT_2
状态中。多数情况下,这个问题可以用供应商提供的TCP/IP补丁予以解决。而如果供应商不提供补丁(指SunOS4 -- 尽管用户们持有允许自己修补代码的许可证),那么只能关闭此功能。
实现的方法有两种,其一是socket选项SO_LINGER
,但是似乎命中注定,大多数TCP/IP栈都从未予以正确实现。即使在正确实现的栈中(指Linux2.0.31),此方法也被证明其代价比下一种方法高昂。
Apache对此的实现代码大多位于函数lingering_close
(位于http_main.c
)中。此函数大致形如:
void lingering_close (int s)
{
char junk_buffer[2048];
/* shutdown the sending side */
shutdown (s, 1);
signal (SIGALRM, lingering_death);
alarm (30);
for (;;) {
select (s for reading, 2 second timeout);
if (error) break;
if (s is ready for reading) {
if (read (s, junk_buffer, sizeof (junk_buffer)) <= 0) {
break;
}
/* just toss away whatever is here */
}
}
close (s);
}
此代码在连接结束时多了一些开销,但这是可靠实现所必须的。由于HTTP/1.1越来越流行,而且所有连接都是稳定的,此开销将由更多的请求共同分担。如果你要玩火去关闭这个功能,可以定义NO_LINGCLOSE
,但绝不推荐这样做。尤其是,随着HTTP/1.1中管道化稳定连接的启用,lingering_close
已经成为绝对必须。而且,管道化连接速度更快,应该考虑予以支持。
Scoreboard 文件
Apache父进程和子进程通过scoreboard进行通讯。通过共享内存来实现当然是最理想的。在我们曾经实践过或者提供了完整移植的操作系统中,都使用共享内存,其余的则使用磁盘文件。磁盘文件不仅速度慢,而且不可靠(功能也少)。仔细阅读你的体系所对应的src/main/conf.h
文件,并查找USE_MMAP_SCOREBOARD
或USE_SHMGET_SCOREBOARD
。定义其中之一(或者分别类似HAVE_MMAP和HAVE_SHMGET),可以使共享内容的相关代码生效。如果你的系统提供其他类型的共享内容,则需要修改src/main/http_main.c
文件,并把必需的挂钩添加到服务器中。(也请发送一个补丁给我们)
注意:在对Linux的Apache1.2移植版本之前,没有使用内存共享,此失误使Apache的早期版本在Linux中表现很差。
DYNAMIC_MODULE_LIMIT
如果你不想使用动态加载模块(或者是因为看见了这段话,或者是为了获得最后一点点性能上的提高),可以在编译服务器时定义-DDYNAMIC_MODULE_LIMIT=0
,这样可以节省为支持动态加载模块而分配的内存。
在Solaris8的MPM中,Apache2.0.38使用一个系统调用以收集踪迹:
truss -l -phttpd_child_pid.
-l
参数使truss记录每个执行系统调用的LWP(lightweight process--Solaris核心级线程)的ID。
其他系统可能使用不同的系统调用追踪工具,诸如strace
,ktrace
,par
,其输出都是相似的。
下例中,一个客户端向httpd请求了一个10KB的静态文件。对非静态或内容协商请求的记录会有很大不同(有时也很难看明白)。
/67: accept(3, 0x00200BEC, 0x00200C0C, 1) (sleeping...)
/67: accept(3, 0x00200BEC, 0x00200C0C, 1) = 9
下例中,监听线程是 LWP #67 。
注意对accept()
串行化支持的匮乏。与这个特殊平台对应的MPM在默认情况下使用非串行的accept ,除了在监听多个端口的时候。
/65: lwp_park(0x00000000, 0) = 0
/67: lwp_unpark(65, 1) = 0
接受了一个连接后,监听线程唤醒一个工作线程以处理此请求。下例中,处理请求的那个工作线程是 LWP #65 。
/65: getsockname(9, 0x00200BA4, 0x00200BC4, 1) = 0
为了实现虚拟主机,Apache需要知道接受连接的本地socket地址。在许多情况下,有可能无须执行此调用(比如没有虚拟主机,或者Listen
指令中没有使用通配地址),但是目前并没有对此作优化处理。
/65: brk(0x002170E8) = 0
/65: brk(0x002190E8) = 0
此brk()
调用是从堆中分配内存的,它在系统调用记录中并不多见,因为httpd在多数请求处理中使用了自己的内存分配器(apr_pool
和apr_bucket_alloc
)。下例中,httpd刚刚启动,所以它必须调用malloc()
以分配原始内存块用于自己的内存分配器。
/65: fcntl(9, F_GETFL, 0x00000000) = 2
/65: fstat64(9, 0xFAF7B818) = 0
/65: getsockopt(9, 65535, 8192, 0xFAF7B918, 0xFAF7B910, 2190656) = 0
/65: fstat64(9, 0xFAF7B818) = 0
/65: getsockopt(9, 65535, 8192, 0xFAF7B918, 0xFAF7B914, 2190656) = 0
/65: setsockopt(9, 65535, 8192, 0xFAF7B918, 4, 2190656) = 0
/65: fcntl(9, F_SETFL, 0x00000082) = 0
接着,工作线程使客户端连接处于非阻塞模式。setsockopt()
和getsockopt()
调用是Solaris的libc对socket执行fcntl()
所必须的。
/65: read(9, " G E T / 1 0 k . h t m".., 8000) = 97
工作线程从客户端读取请求。
/65: stat("/var/httpd/apache/httpd-8999/htdocs/10k.html", 0xFAF7B978) = 0
/65: open("/var/httpd/apache/httpd-8999/htdocs/10k.html", O_RDONLY) = 10
这里,httpd被配置为"Options FollowSymLinks
"和"AllowOverride None
"。所以,无须对每个被请求文件路径中的目录执行lstat()
,也不需要检查.htaccess
文件,它简单地调用stat()
以检查此文件是否存在,以及是一个普通的文件还是一个目录。
/65: sendfilev(0, 9, 0x00200F90, 2, 0xFAF7B53C) = 10269
此例中,httpd可以通过单个系统调用sendfilev()
发送HTTP响应头和被请求的文件。Sendfile因操作系统会有所不同,有些系统中,在调用sendfile()
以前,需要调用write()
或writev()
以发送响应头。
/65: write(4, " 1 2 7 . 0 . 0 . 1 - ".., 78) = 78
此write()
调用在访问日志中对请求作了记录。注意,其中没有对time()
的调用的记录。与Apache1.3不同,Apache2.0使用gettimeofday()
以查询时间。在有些操作系统中,比如Linux和Solaris,gettimeofday
有一个优化的版本,其开销比一个普通的系统调用要小一点。
/65: shutdown(9, 1, 1) = 0
/65: poll(0xFAF7B980, 1, 2000) = 1
/65: read(9, 0xFAF7BC20, 512) = 0
/65: close(9) = 0
工作线程对连接作延迟的关闭。
/65: close(10) = 0
/65: lwp_park(0x00000000, 0) (sleeping...)
最后,工作线程关闭发送完的文件和块,直到监听进程把它指派给另一个连接。
/67: accept(3, 0x001FEB74, 0x001FEB94, 1) (sleeping...)
其间,监听进程可以在把一个连接指派给一个工作进程后立即接受另一个连接(但是如果所有工作进程都处于忙碌状态,则会受MPM中的一些溢出控制逻辑的制约)。虽然在此例中并不明显,在工作线程刚接受了一个连接之后,下一个accept()
会(在高负荷的情况下更会)立即并行产生。
本文允许自由使用、分发、转载,但必须保留译者署名;详见:译者声明。
______________________________________
本手册是在原来尚未完成的“Apache 2.0手册中文版翻译项目”的基础上,根据新的 Apache 2.2 文档进行修订、更新、补充的结果,没有他们之前辛勤劳动积累的成果,单靠一人之力是很难完成的[目前尚有部分未翻译]。所以首先应当感谢那个项目的各位自 愿者:kajaa 、biAji 、fei 、suncjs 、Daniel 、flytosea 、forehead 。
感谢http://www.15913.com/热心的站长 bingzhou 兄提供网络空间[电信]。
感谢LinuxFans.Org上热心的 sejishikong 兄提供网络空间[网通]。
感谢http://www.haloso.com/热心的站长 harvey 兄提供网络空间[铁通,教育网]。
感谢热心的 乔章池 兄制作 chm 版本。
感谢热心的 刘智丹 兄制作 pdf 版本。
innodb和myisam两种类型的表,是mysql的基础表。很多人为了选择该使用哪 种表而头疼。
一般来说innodb对事务的支持比较好,而myisam则一般,innodb是行锁,mysql是表锁。但。。。下面这个测试却:
原文:http://rdc.taobao.com/blog/dba/html/295_insert_benchmark_for_myisam_and_innodb.html
作者:陶方
内容:
测试表结构:
CREATE TABLE `test` (
`ID` bigint(20) NOT NULL auto_increment,
`INT_A` int(11) default NULL,
`INT_B` int(11) default NULL,
`INT_C` int(11) default NULL,
`STRING_A` varchar(50) default NULL,
`STRING_B` varchar(250) default NULL,
`STRING_C` varchar(700) default NULL,
PRIMARY KEY (`ID`),
KEY `IDX_TEST_IA` (`INT_A`),
KEY `IDX_TEST_IB` (`INT_B`),
KEY `IDX_TEST_SA` (`STRING_A`,`INT_C`)
) ;
数据量:总共10个表,每个表插入400w数据
并发数:每个表并发20个线程去执行插入操作,总共200个线程
数据特点:除了主键采用自增外,索引相关字段全是随机生成的。字符串的长度和内容都是随机的,平均长度为预定义的一半
X轴是unix时间戳,Y轴是十秒钟的插入量。从以上测试结果可以看出,InnoDB的插入性能随着数据量的增多一直在下降,而且表现相当不稳定。MyISAM的表现还是比较好的,虽然瞬时插入的谷值一直在下降,但是整体表现很稳定。
总的来说,Ext3的cache算法性能还是非常不错的,不愧是linux上面备受推崇的文件系统。InnoDB虽然提供了高可用性,但是插入性能方面的表现并不如MyISAM稳定。
--EOF--
对于这个图是什么生成的,我也很有兴趣。。。。目前未知