前段时间就rails的部署的负载能力进行了相关的讨论,请看:
http://www.javaeye.com/topic/19534
http://www.javaeye.com/topic/18675
这两天在安装服务器,顺便到处看了一下,搞清楚了一些对rails的误解。因此对服务器部署有了一些新的想法,和大家探讨一下。
以前我以为rails像PHP那样,以apache的server mod方式运行,今天仔细看了一下FastCGI/SCGI/mongrel的安装手册,这才搞明白,我弄错了。
当FastCGI/SCGI/mongrel方式部署的时候,ruby并不是直接运行在apache的进程中的,而是独立的运行在CGI或者 server上面的。在这种情况下lighthttpd/apache仅仅充当了一个前端HTTP请求分发的代理作用(和静态页面的处理),动态内容交给了后台的ruby CGI/Server去处理的。
其实这种部署方式和我们J2EE常用的apache+(mod_jk)+n个tomcat实例的方式本质上是没有什么区别的。更进一步来说,IBM WebSphere的cluster实际上也是这种方式,在前端使用Apache作为请求分发代理,后面若干个WebSphere实例来处理请求。
在J2EE群集部署方案中,虽然目前的企业应用都强调了应用服务器提供的Session复制功能,EJB调用的负载均衡能力,但是考虑到目前 J2EE潮流发展的趋势,已经不再使用EJB的负载均衡,同时Session复制也被证明为影响cluster水平扩展的主要障碍之一。因此对于大容量的 J2EE水平扩展群集而言,保持每个节点的无状态性,不再使用Session来保持全局状态是必经之路。
因为只有每个JVM进程不保持全局状态,才能够保证n个JVM节点的幂等性,那些所有涉及到全局状态的,必须放在JVM进程之外,例如用户ID可以使用cookie,session可以放入数据库,文件可以放在共享存储系统中。
这样的方案做下来,前端的apache也仅仅是一个HTTP请求代理,后面的应用服务器实例几乎是可以无限水平扩展的,瓶颈永远不会出现在应用服务器层,只会出现在apache端,或者数据库端。当然apache不行,还可以用lighthttpd,甚至使用四层交换机硬件进行请求的分发工作,后端的单台数据库不行,还可以使用多个数据库同步复制,甚至使用Oracle Grid。
这个时候我们考察一下J2EE的群集方案,竟然会发现和Rails的群集方案没有多大的差别了。为了讨论的简单,我们拿J2EE的apache2.2 + tomcat5.5和apache2.2 + mongrel来对比一下:
先看J2EE群集方案:
Apache2.2 proxy分发请求给后面n个tomat5.5实例(这里甚至都不需要使用mod_proxy_ajp,apache直接转发请求给tomcat的http端口);
每个tomcat实例没有内部全局状态,完全是无状态的服务,用户标示从cookie取得,session可以放在数据库中,假设不使用分布式Cache。每个tomcat实例收到一个请求以后,自行处理,然后返回给apache。
再看rails群集方案:
Apache2.2 proxy分发请求给后面n个mongrel实例;
每个mongrel实例也是无状态的,用户标示使用cookie,从apache收到一个请求以后,自行处理,然后返回给apache。
从两者的对比来看,J2EE的每个节点是一个JVM进程,里面若干Java线程都是无状态的,而mongrel据说也是多线程的,rails的每个节点是一个Ruby进程,里面若干ruby线程都是无状态。竟然完全一致的模型!
在这种情况下,究竟是进程多一点,线程少一点;还是进程少一点,线程多一点,都不是最重要的讨论话题,焦点是J2EE和Rails的群集方案是一致的,在应用逻辑处理层的群集水平扩展能力都是近乎无限的,因此都不是系统的瓶颈所在。这意味着什么呢?
这意味着,只要硬件管够,J2EE系统和Rails系统的网站负载能力不会有多大的差别。
也许,ruby的解析执行速度比Java慢,由于没有数据库连接池导致每个请求需要多消耗一些建立物理连接的时间。但是这些因素只能导致单个用户请求的响应时间比Java慢,不会导致整个网站的负载能力差。
也就是说,如果Java的系统,用户打开一个页面需要两秒钟,而Rails的系统,用户打开一个页面可能需要四秒钟,但是他们都能够每天负载100 万的PV,这100万个请求,rails大概也同样是四秒钟,这方面没有什么差别(同样的网站负载,mongrel的实例数量也许远多于tomcat实例数量,但是总体处理能力没有区别)。
当然,J2EE群集方案和Rails群集方案还是有两点不同:
1、J2EE有内置分布式Cache,例如JBoss Cache,而rails的方式是独立的Cache进程在运行,这两种方式来说,对于群集水平扩展,甚至rails的Cache方案还要更好。
2、数据库连接池,对于mongrel,我觉得增加数据库连接池是完全做得到的事情。不过即使不增加连接池,这里也不会成为系统瓶颈,最多会导致数据库多花一些时间在处理连接的建立和断开上面。
最后这种群集部署方案下面,web server退化成为一个请求分发代理,找不到任何理由使用apache了,对,是lighthttpd出场kick off apache的时候。如果网站容量大到连lighthttpd都无法及时分发请求的时候,你还可以用四层交换机来分发请求,那lighthttpd也该被 kick off了。
用J2EE看起来确实能够更加节省硬件,但是我们不能再用Rails无法负载大容量网站的理由来攻击rails了,只有硬件管够,不管是J2EE,还是Rails,都有近乎无限的水平扩展能力。
没有评论:
发表评论