现在已经有不少文章在谈论各种版本的Data Services,然而却没人能说清楚该如何从这些Data Services中进行选择,同时也没人对端点(end point)和管道(channel)是如何影响着应用性能这个议题进行过详细论述。
相关厂商内容尽管Adobe提到4个不同版本的Data Services,但实际上只有2个主要版本。一个是开源的Blaze Data Services,另一个是名为LiveCycle Data Services(LCDS)的私有版本。这两个产品都提供了一个重要特性:借助于Message Broker Servlet连接Flex和Java。他们都可以通过二进制协议,ActionScript消息格式(AMF)使用远程过程调用和消息与服务器端进行通 信。此外,Adobe还在这两个核心产品之上提供了支持版本和更具扩展性的产品套件。
从我在Gorilla Logic的工作经历来看,我认为这两个产品之间的主要差异在于支持项与数据管理,而性能和可伸缩性之间的差异则颇具争议。LCDS为客户端通信提供了额 外的端点和管道。Adobe宣称这么做的主要好处在于提升了可伸缩性,然而基本的通信方式依然是通过HTTP上的AMF,这样不管服务器端或客户端的配置 如何,其性能没什么差别。
LCDS提供的另一个特性是数据管理,它通过实时的冲突调节(conflict resolution)实现Flex客户端和Java服务器端之间的数据同步,同时还提供了数据装配器和适配器以通过JDBC、Hibernate或其他 客户化的适配器连接Data Services和持久化存储。
那么这4个不同版本都是什么呢?
同时还有一个Adobe称之为LiveCycle Data Services Enterprise Suite的产品套件。它向核心的Data Services中添加了额外的产品以通过PDF Generation、Forms及Digital Signatures等工具提供内容服务和文档输出功能。
理论上来说,我们可以根据以下三点来选择产品。
在本文的最后有一张比较图表概览了这4个不同版本。
概览不同的端点——Servlet和NIO在Data Services中,端点就是服务器监听来自客户端连接的方式。对于Blaze DS和LCDS来说,标准的端点基于Servlet,运行在应用服务器上。端点通过Message Broker Servlet(配置在web.xml中)加入到标准的Servlet过滤器链中,这样我们就可以将Blaze DS和LCDS部署到现有的Java应用中。与Java Servlet端点类似,每个客户端连接都需要服务器上一个单独的线程。
与上面相比,NIO端点的工作方式就完全不同了。NIO表示Java新的输入/输出。NIO端点会创建一个独立的基于NIO的Socket Server。其优势在于单个线程能管理多个I/O流,这样就无需很多线程,同时能处理更多的客户端。
要想使用NIO,我们面临着如下几个挑战:
尽管我们可以通过配置的方式让NIO服务器监听80端口,但通常它却驻留在其它端口上。这样就给网络配置带来了挑战,我们必须将网络配置成可以接收 新端口上的连接。根据服务器内部网络和各种客户端的不同,这可能会产生问题。不过这个问题还是有可能解决的:使用带有sticky sessions的负载平衡器。
然而Java NIO的这些优势却是颇具争议的。开发Java NIO的目的在于让单个线程处理多个连接,这是通过令单个线程遍历连接池以检查是否需要读取或写入新的数据来实现的。但由于NIO是在2002年引入的, 那时的JDK版本还是1.4,而现在JVM和Linux中的线程已经得到了极大的改进,因此Java和Linux处理大量线程的能力也已经得到了巨大的提 升。
举个例子吧,Linux Kernel 2.6引入了一个新的线程库,也就是本地的POSIX Linux线程库(NPTL)。测试表明,借助于NPTL在IA-32上只需2秒钟1就能启动100,000个线程,而如果不使用NPTL的话,Linux Kernel需要花费15分钟才能启动这么多线程。
更有意思的是Paul Tyma等人发布了一篇博文说到Java NIO实际上是个劣势2, 3, 4。凭借一系列基准,Paul得出了如下一些结论:
Paul根据这些测试得出如下结论:一个连接对应一个线程完全没问题。在使用JDK 1.6的情况下,JVM可以处理15K到30K的线程数。这意味着Servlet端点已经不再局限于几百个线程了,相反,线程数可以更多,甚至15K个连 接以上。当然了,实际的限制取决于硬件配置,比如内存、CPU等等。
概览不同类型的管道我们可以在基本的网络连接之上使用多种不同类型的管道进行客户端与服务器端的通信。基本远程过程调用使用的是标准AMF管道。
另一种通信形式就是消息,这样应用就可以推送来自于服务器端的消息并进行近乎实时的通信。代表性应用就是聊天服务器、拍卖客户端及协作服务。
Data services处理消息的主要方式就是轮询(polling)。由于HTTP上的标准通信并不会一直打开通信管道,这样一个轮询管道就会让客户端请求一 直等待服务器端,直到数据可用为止,其等待时间从几毫秒到几分钟不等。这么做就模拟了从服务器端推送数据的过程。
有两种基本的轮询管道:短轮询与长轮询。其主要区别在于服务器端等到客户端数据变得可用时所需时间的多少。
一种更高级的管道是流式AMF(streaming AMF)。它会打开到服务器端的HTTP连接并让服务器以流的方式在该管道上传输消息(消息的数量没有限制)。这么做就无需客户端轮询了,同时还能使用标 准的网络配置。该方式最接近于实时流。流式AMF的挑战在于它使用了HTTP 1.1的持续连接,而不同的浏览器对其的实现方式却不同。
最后一种管道就是RTMP(实时消息协议)管道了,目前只有LiveCycle DS对其提供了支持。Adobe最近宣布将要发布RTMP规范,由此我猜想它最终将会得到其他产品的支持。
设计RTMP的目的是在双向管道上以流的方式处理大量多媒体和数据。RTMP的一个主要好处是可以一直打开与客户端的连接,这样就可以推送服务器端的数据了。凭借这一点,RTMP可用于Comet风格的通信和实时的数据推送。
RTMP有三种形式。一种是基于TCP并使用1935端口,其底层实现要求在客户端浏览器上初始化连接。由于使用了非标准的端口,这样客户端防火墙经常会阻止其运行。
RTMP的另两种形式在HTTP请求内封装了RTMP消息,这样协议就可以穿越防火墙并使用标准的端口。这两种形式分别是RTMPT(用在标准的HTTP上)及RTMPTS(用在安全的HTTPS上)。
在Flex中,所有对服务器的调用都是异步执行的,因此这些管道都不会对客户端性能造成任何影响。然而他们却对服务器端性能有一定的影响,尤其是在 同时打开多个客户端连接的情况下更是如此。例如,流式AMF会导致服务器端打开大量并发的客户端连接,这也就意味着会产生多个线程。但如前所述,多个线程 的影响微乎其微。
所有的客户端连接都可以配置默认管道和备选管道,如果默认管道失败则可以切换到备选管道上。根据服务器端处理的不同通信类型,我们可以指定不同的管道链。例如,可以指定RTMP管道,但如果该连接失败,就回到长轮询管道。
结论相对于Blaze DS来说,LiveCycle DS的真正优势在于其支持与数据管理,而额外的端点和管道所带来的优势却是颇具争议的。根据我们在Gorilla Logic所完成的项目来看,根本无需使用NIO端点或是RTMP。但从技术角度来看,没什么是确定的。我倒是想多点项目经历。
特性比较表
关于作者
Ryan Knight是Gorilla Logic的高级软件架构师,他主要从事Flex和Java咨询方面的工作,同时还是Anvil Flex的主要贡献者,这是一个开源的项目,用来帮助企业上手Flex开发。他有着12年的Java开发经验,期间经历了从开发到咨询的各种角色变迁。
资源
1 http://www.linuxjournal.com/article/6530
2 http://paultyma.blogspot.com/2008/03/writing-java-multithreaded-servers.html
3 http://www.theserverside.com/discussions/thread.tss?thread_id=26700
4 http://cometdaily.com/2008/11/21/are-raining-comets-and-threads/
来自Adobe的链接
LiveCycle Data Services ES FAQ
Comparison of the different LiveCycle Data Services solutions
其他资源
LiveCycle ES vs LiveCycle DS vs BlazeDS - clearing up the confusion
Why are you NOT using LiveCycle DS?
查看英文原文: Blaze Data Services or LiveCycle Data Services?
给InfoQ中文站投稿或者参与内容翻译工作,请邮件至。也欢迎大家加入到InfoQ中文站用户讨论组中与我们的编辑和其他读者朋友交流。