 | | | 实战WEB服务器升级 |
| | 2003-04-13 11:24 雪里弄剑/(天极商务应用) | Java平台的多线程模型与Apache/PHP平台的多进程模型比较
比较完线程和进程的区别并了解了构成现代化web应用服务器的基本组件之后,现在,让我们对网站新旧两种web应用模式作一个对比分析。
该网站的web应用原来是用PHP语言来编写的,跑在Apache平台上,Apache属于一款pre-fork(预分岔)多进程HTTP服务器。Apache是这样工作的:首先开启一个父进程,接着,父进程又分成若干子进程进行监听,并等待HTTP连接。接着,其中的每一个子进程将一次处理一个HTTP请求,此外,Apache还创建了一个进程“池”,对HTTP连接予以适时的处理。
这种处理方法的缺点在于进程数与请求数的比率为1:1,从而导致系统处理时间的大量消耗。尤其在HTTP keepalives(这是在同一连接下处理来自一个客户端的多个连续请求的一种特性,因为不用为每一请求创建新的连接,因而能节省时间,加速web服务)条件下,情况就更是如此。由于子进程在接受来自另一客户端的连接之前,要被迫等待特定的一段时间,这种浪费系统处理时间的缺点就暴露无疑了。如果HTTP的存活时限为15秒,那么每一个Apache进程在处理完来自客户端的最后一个请求之后,15秒钟之内将不能处理任何别的请求。
也就是说,使用了keepalives特性的Apache web服务器将需要运行比连接数量更多的子进程。根据具体的设置和传输量,这能够导致生成一个比并发连接总数量庞大得多的进程“池”。实际上,由于所有的那些被封锁的进程耗用了太大的内存空间,很多大型网站甚至干脆就把keepalives特性关闭掉了。
持久的数据库连接
关于数据库连接的分配,多进程模型(如Apache)还存在一个问题。这个问题与我以前讲过的PHP脚本的不持久特性是相伴相生的。请先看看下图。
你所见的这幅图从一个由数据库驱动的动态web应用的角度说明了Apache/PHP解决方案是怎样工作并处理访问请求的。你可能注意到了,正如上文提到的一样,每一个Apache子进程一次处理一个单独的客户端连接。由于PHP脚本是单独由处理访问PHP生成文档的请求的每一个子进程来解释的,每一个进程均必须建立其独立的查询数据库的连接。
由于PHP脚本没有持久性,数据库连接在每次脚本运行时都必须打开和关闭。尤其对于那些被频繁访问的站点来说,在连接上浪费的时间可能会导致巨大的性能损失
为了避免这种情况,PHP开发商也许会采用持久的数据库连接方式,使访问请求处理完毕和PHP脚本执行结束之后仍保持打开状态。
但是,在PHP环境中采用持久的连接方式和传统意义上的连接“池”方式并不相同。在PHP环境中,当一个持久的连接被子进程打开后,不需要再耗费额外的连接时间,就能够重用该连接。但是要指出的是,只有通过同一个子进程才能重用它。由于该连接是由特定的进程打开的,因此,即使打开它的子进程处于空闲状态,不用处理任何的请求,此连接也保持着对其的附着状态。事实上,即便是该子进程又继续处理另一个非PHP请求,该数据库连接也不会关闭。
在持久的数据库连接的情况下,我们观察到的实际上还是与前面所讲相同的子进程与HTTP keepalive 请求的1:1映射比率。但是,在当前情况下,数据库连接将会一直维持打开状态,并贯穿在打开它的子进程的整个生命期中。
这种情形会导致打开的数据库连接过剩,从而使得占用的内存空间大小超过实际负载的需要。在某些环境里,这种数据库连接过剩在高负载情况下会使数据库达到连接数量的极限。这时,服务器将不再对更多的请求作出响应。用户可以把这种情况看作是应用服务器或HTTP服务器对数据库执行了一次拒绝服务攻击,从而使自己当机。
下一页>>多线程方式
|
|