PHP沉思录-第六篇-Drupal的性能问题-左轻侯-《程序员》2008年11月号
创建时间:2008-11-09 01:12:51 最后修改时间:2008-11-09 01:12:51
本文发表在《程序员》杂志2008年第11期
PHP沉思录之六:Drupal的性能问题
左轻侯
Drupal是一个基于PHP的开源CMS系统,也是我认为技术上实现得最好的一个PHP应用。Drupal的架构非常优秀,通过微内核+plugin的方式,实现了极佳的扩展性,从而使Drupal远远超出一般的CMS这一范畴。从这个意义上来说,把Drupal称为Web OS似乎更加合适一些。关于Drupal,有太多的话可以说,也许我会在以后的时间里写一篇文章对它进行专门的讨论。但是在本文中,我想讨论的,是Drupal社区中的每一个人都会面对,但不是每一个人都对其有清晰认识的问题,即Drupal的性能问题。
因为客户需求,我曾经对Drupal做过比较全面的测试。当时的环境是双服务器(DB server+Web Server),硬件配置都是单CPU+4G。数据库里面有几千条Node记录。用JMeter对各种情况下(开/关各种cache模块,logged user/anonymous user)不同页面的读取和写入操作都进行过测试。
测试的结果可能和很多人印象中不一样。两个主要的结果如下:
1. Logged user和anonymous user的性能差距非常大。同一个页面,logged user的RPS(Requests per second)一般不超过20,而启用了cache的anonymous user的RPS在100多,当使用了file-based cache以后,甚至能超过300。
2. 数据库压力相对较小。由于Drupal把大量可配置的内容都放在数据库中,因此往往容易产生这样一种印象,即Drupal对数据库要求应该是很高的。但事实上,无论是cache还是非cache模式,DB server的压力都相当小(CPU在10%以下),而Web Server的CPU在80%以上。跟踪所有的db query的执行时间后,也证明了这一点(全部db query的执行时间只占页面生成时间的一小部分)。
经过反复的测试和思考,我得出了一些结论。很明显,Drupal在大量logged user并发情况下的瓶颈,在于执行Drupal代码的CPU时间,而不是在于数据库或者其他地方。之所以出现这样的情况,和PHP本身的执行机制和Drupal的实现方式有关。Drupal在生成一个非cached的页面时,不管这个页面多么简单,都要执行一个完整的bootstrap过程,即使只启用了最少的模块,这个过程也要调用几十个PHP文件,执行成千上万行PHP代码。而PHP的机制又决定了没有任何PHP代码或者对象能够驻留内存,每次响应请求都必须执行完整的初始化工作。而anonymous user之所以快,是因为Drupal在执行cached page的时候,不会执行完整的bootstrap过程,它先检查是否cached page,是的话就读取缓存,然后结束工作。这样当然就快了。
以这个结论为前提,可以解释一些事情:
1. 为什么Drupal的性能在各种环境下相差并不多。无论是双服务器,单服务器,甚至内存非常小的虚拟机,logged user的RPS值往往总是在10~20之间。数据库里面有几百条,或者几十万条记录,影响也不大。因为瓶颈并不在于DB或者内存,而是在于执行代码的过程。
2. 为什么使用APC/XCache这样的代码优化程序,能够得到极大的性能提升。在我自己的虚拟机环境上,RPS从3~4提升到了12。因为它提升的是PHP代码的执行时间。
从这个结论出发,列出一些对优化Drupal的logged user性能有明显作用和没有明显作用的措施:
没有明显作用的:
1. 加内存。在并发数只有10+的时候,即使每个请求占20M内存,也只有200M+内存而已。
2. DB server和Web server分开,或者增强DB server的配置。一台中等性能的mysql服务器,应付200~300的并发是很轻松的事情,在并发数只有10+的时候,db server实际上是很空闲的。
3. 基础软件的优化,例如从Windows转移到Linux,从apache转移到Lighttpd,从MySQL迁移到其他数据库,除了从Windows转移到 Linux会有比较明显的提升以外(因为PHP在Linux上的效率比在Windows上要好),其它的措施可能会快一些,但不会有大幅度的提高,因为瓶颈不在那里。
有明显作用的:
1. 使用APC/XCache这样的代码优化程序,速度会有几倍的提升。估计大家都已经这样做过了。
2. 增加web server的CPU数量。双核的肯定比单核的快,4个CPU肯定比2个CPU快得多。
3. 使用多web server+单db server的配置,把代码执行的压力分散到不同的web server上。上文说到,单台db server可以轻松应付200+的并发,这意味着理论上可以支持10台以上的web server。
4. 使用Quercus这样的引擎,把PHP代码编译成Java,再在Java VM中运行,理论上会有很大的提高。原因是,第一,Java的运行效率比PHP高,第二,Java代码是可以cache的,不需要每次都重新加载。这里有个测试结果:http://www.workhabit.org/resin-backed-php-drives-4x-performance-improvements-drupal 。Drupal在Quercus下有4倍的性能提高,但是这个数字跟Drupal在打开APC/eAccelerator下的提升差不多,所以可能没有太大的实用价值。
另外一种思路是代码本身的优化。
使用cache API基本上是没有意义的,因为对于logger user,Drupal不会调用cache API。Drupal.org上有人提出,即使是logged user,有很多页面也是不用定制化的,这意味着可以cache它们。但是Drupal没有提供这样一种机制。只要是logged user,Drupal就会执行完整的bootstrap过程,即使只打印出一个hello world,因此实际上你没有办法在logged user状态下cache单个页面。
到目前最新版本的Drupal(Drupal 6.4)为止,对于logger user,Drupal只提供了一种cache功能,就是可以将部分block设置为可cache的。在block占用大量服务器时间的情况下,block cache能够有效地提高效率。但是,由于block cache对于bootstrap过程并无影响,因此当瓶颈在于bootstrap本身时,Block cache是无能为力的。
在Drupal.org的社区,关于logger user的cache问题,一直处于热烈的讨论之中。基本的结论是,由于Drupal的架构就是这样,目前没有很好的解决方案,只能期待Drupal在以后的版本中进行改进了。
我研究了一下Drupal的bootstrap过程,发现也许这样是可行的:实现hook_boot函数,这是bootstrap中执行最靠前的一个函数,它被调用时,bootstrap的大部分过程还没有执行。在hook_boot中,检查当前页面是否需要cache,如果是,直接读 cache生成页面,然后调用exit()强行结束。这在理论上是可行的,但太过hack了一点。
Drupal的情况是这样,那么其他的PHP框架,尤其是半官方的Zend Framework,性能如何呢?通过搜索,我在网上找到了一份PHP framework comparison benchmarks,网址见:http://www.avnetlabs.com/php/php-framework-comparison-benchmarks。根据这份报告的数据,Zend Framework的性能只有原生PHP的10%,如果没有用APC,连3%都不到。当然,这份报告的数据不一定详尽,Zend Framework在不同环境下的表现应该也会有出入。但是,Zend Framework的性能大幅度落后于Baseline PHP,应该是确凿无疑的。
为什么PHP主流框架的性能都存在着这样的问题呢?其实这也不难理解。回顾PHP沉思录系列第一篇中对于PHP工作模型的讨论,由于PHP没有驻留内存的进程,所以每一个request发生时,都必须初始化所有的对象,这导致大量的时间被耗费在进程代码的执行过程中。当PHP程序仅仅是简单的脚本时,这无关紧要,但是在结构复杂的架构中,由于每次处理request都要重复调用成千上万行代码,这一问题就变得非常突出了。而且,除非PHP以后的版本对这一机制进行改进,否则这个问题无法得到彻底的解决。
那么,这是否意味着,PHP只能适用于小型的网站,而无法在高并发量的大型网站施展拳脚呢?当然不是这样。事实上,在Yahoo和其他许多知名的巨型网站上,都大量地使用了PHP。原因在于,PHP仅仅被用作一个内容生成器,生成的内容会被转化为静态文本,绝大多数用户浏览的都是被cache的静态文本。这就和PHP程序的性能毫无关系了。但是,当用户并不是仅仅进行浏览,而是需要频繁地和网站进行互动时,PHP的性能不但无法比拟C和Java,甚至无法与同为脚本语言的Python和Ruby相比。也就是说,PHP更适合于新闻门户这样的内容发布站点,而不是web 2.0应用的首选。
在本系列文章告一段落的时候,我们看到的是PHP的局限性。热爱PHP的人们可能会对此觉得沮丧。但是,这并无损于PHP作为一门优秀语言的声誉。尺有所短,寸有所长,对于我们熟悉和喜爱的工具,我们更应该了解它们的局限,这也有利于我们更有效地使用它们。

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Laravel은 직관적 인 플래시 방법을 사용하여 임시 세션 데이터 처리를 단순화합니다. 응용 프로그램에 간단한 메시지, 경고 또는 알림을 표시하는 데 적합합니다. 데이터는 기본적으로 후속 요청에만 지속됩니다. $ 요청-

PHP 클라이언트 URL (CURL) 확장자는 개발자를위한 강력한 도구이며 원격 서버 및 REST API와의 원활한 상호 작용을 가능하게합니다. PHP CURL은 존경받는 다중 프로모토콜 파일 전송 라이브러리 인 Libcurl을 활용하여 효율적인 execu를 용이하게합니다.

Alipay PHP ...

Laravel은 간결한 HTTP 응답 시뮬레이션 구문을 제공하여 HTTP 상호 작용 테스트를 단순화합니다. 이 접근법은 테스트 시뮬레이션을보다 직관적으로 만들면서 코드 중복성을 크게 줄입니다. 기본 구현은 다양한 응답 유형 단축키를 제공합니다. Illuminate \ support \ Facades \ http를 사용하십시오. http :: 가짜 ([ 'google.com'=> 'Hello World', 'github.com'=> [ 'foo'=> 'bar'], 'forge.laravel.com'=>

고객의 가장 긴급한 문제에 실시간 인스턴트 솔루션을 제공하고 싶습니까? 라이브 채팅을 통해 고객과 실시간 대화를 나누고 문제를 즉시 해결할 수 있습니다. 그것은 당신이 당신의 관습에 더 빠른 서비스를 제공 할 수 있도록합니다.

기사는 PHP 5.3에 도입 된 PHP의 LSB (Late STATIC BING)에 대해 논의하여 정적 방법의 런타임 해상도가보다 유연한 상속을 요구할 수있게한다. LSB의 실제 응용 프로그램 및 잠재적 성능

JWT는 주로 신분증 인증 및 정보 교환을 위해 당사자간에 정보를 안전하게 전송하는 데 사용되는 JSON을 기반으로 한 개방형 표준입니다. 1. JWT는 헤더, 페이로드 및 서명의 세 부분으로 구성됩니다. 2. JWT의 작업 원칙에는 세 가지 단계가 포함됩니다. JWT 생성, JWT 확인 및 Parsing Payload. 3. PHP에서 인증에 JWT를 사용하면 JWT를 생성하고 확인할 수 있으며 사용자 역할 및 권한 정보가 고급 사용에 포함될 수 있습니다. 4. 일반적인 오류에는 서명 검증 실패, 토큰 만료 및 대형 페이로드가 포함됩니다. 디버깅 기술에는 디버깅 도구 및 로깅 사용이 포함됩니다. 5. 성능 최적화 및 모범 사례에는 적절한 시그니처 알고리즘 사용, 타당성 기간 설정 합리적,

기사는 입력 유효성 검사, 인증 및 정기 업데이트를 포함한 취약점을 방지하기 위해 프레임 워크의 필수 보안 기능을 논의합니다.
