随笔 - 71  文章 - 0  评论 - 179 

主题列表:

COMET彗星(一)SERVER PUSH介绍

引言:

      在上一篇随笔中,对COMET的机制和原理做了简短的介绍。网上的确有很多类似的资料可以查看,基于PHP,JSP,.NET的框架更是层出不穷。本文将简要介绍并分析一个基于.NET的SERVER PUSH框架,实现了从消息的发布,广播,到接收等一系列SERVER PUSH关键技术。

COMET技术要点:

      COMET的理念是先进而直接的,从服务器发布信息,同时让浏览器(也可以是客户端)接收并响应消息事件。就是这样简单的理念,造成了系统设计上的多重麻烦。

      首先就是如何让我们的浏览器接收到服务器发来的事件呢?

      有一种实现方式是借由无实体大小的FLASH,IFRAME或者APPLET等组件来间接打通客户端SOCKET,然后向这些元件中推入信息,并通过javascript线程,得到元件返回的信息(当然也有极个别情况下,由这些元件来直接向页面注入信息)。

      从最终结果看,我们好似得到了一个服务器的稳定连接,并刷新了页面信息。但是实际上,这样的实现方式实在是有点不够“直接”。

      FLASH(或FLEX)本身可以通过WEBSERVICE组件调用WSDL,或者直接调用java serverlet,这是FLASH PLAYER给我们的便利条件,但通过FLASH通讯的办法来实现SERVER PUSH总是让人觉得无法接受,为何不直接做一个FLASH通讯呢。

      APPLET更不用说,直接将JAR包“推”到页面运行,启动麻烦的JRE的同时还要下载庞大的JAVA程序。没有JRE的情况下,还需要相应下载。

      SILVER LIGHT的机制与FLASH类似,那是由于并没有FLASH PLAYER普及,用户同样需要下载相应播放器。

      以上三者实在谈不上是完全的web应用,我们只是想用最纯粹的javascript和html来解决问题,又何必劳师动众呢?单纯的javascript事件和线程,难道就不能满足我们的需要么?

      于是又有人想到了IFRAME,通过一个隐形的IFRAME来发送AJAX请求,通过长轮询得到消息。但这也不是真正意义上COMET,顶多是一个不成熟的AJAX应用。

      COMET的精髓就在于用服务器与javascript来维持浏览器的长连接,同时完成服务器端事件的浏览器端响应。这样的事件广播机制是跨网络的,同时也是实时的。

COMET技术难点:

      1.维持长连接

      2.维持服务器端的“心跳”

      3.浏览器端对“心跳”的“感应”

      4.维持长连接与超时的平衡

      5.线程同步

      6.通用的接口设计

     PS:这里需要注意的是,我们是在说COMET技术,而不是在谈论如何找女朋友。虽然从某个角度来看这二者似乎存在着很多类似的地方……

.NET下的COMET实现:

      我们需要COMET,我们需要源码,我们需要最单纯的实现。本着这三点需求,我为大家准备了以下这个例子,James Simpson的基于COMET技术的.NET IM。

      ClassDiagram1

图1.1 COMET基类类图

 

      实体类:

      1.CometClient:                      COMET的服务实体,实例化一个CometClinet的意义在于记录必要的服务信息,比如用户名称超时设置等。

      2.CometMessage:                  包含对服务信息和相信属性的实体类,是消息传输的主体。

      3.InProcCometStateProvider:继承了ICometStateProvider并实现了消息操作的方法,同时将消息保存在内存中。

      接口类:

      1.ICometStateProvider:          定义了一系列的接口来提供对CometClient实体和CometMessage的操作。

      异常类:

      1.CometException:                没有什么特殊的异常类。

      事件:

      1.CometClientEventHandler:  CometClient的事件监听类和广播类。

      线程相关:

      1.CometWaitThread:              服务器端线程池,排队等待信息请求并调用,同时提供超时等操作。

      2.CometWaitRequest:            服务器端线程,监听客户端的message请求。

      3.CometAsyncResult:           异步请求的管理类,通过继承SYSTEM.IAsyncResult来实现异步。

      主体:

      1.CometStateManager:         用来管理线程池,管理线程和用户连接,消息转发等一系列操作的工厂类。

     

     ps:从某种意义上来说,这个例子最好的地方就是在于它的CometStateManager实现是可以被拓展的,定制自己的管理模式,定制自己的存储操作等都可以通过这个类来进行扩展。线程管理在这个DEMO里做得相对成熟,而且事件机制可以通过定制Adapter更加丰富。

      由于时间有限,下一篇随笔中将介绍几个关键类的具体实现,和一些关于设计模式的思考。年末了,希望园子里的朋友们都过个收获满满的年。

标签: gis, comet, ajax, .net, im, 长轮询
posted on 2009-01-20 10:16 lzlynn 阅读(5742) 评论(16) 编辑 收藏

 回复 引用 查看   
#1楼 2009-01-20 10:42 | JimLiu      
保持关注……
 回复 引用 查看   
#2楼 2009-01-20 10:45 | 谢慧琦      
服务器与客户端保持长时间的连接,这样客户端的用户会比使用client pull的方式减少很多很多吧?
 回复 引用 查看   
#3楼 2009-01-20 10:47 | welshem      
关注中.
 回复 引用 查看   
#4楼[楼主] 2009-01-20 10:48 | lzlynn      
@谢慧琦
主要是针对不同的应用方式,比如在报警,聊天室,地图跟踪,股票分析等。或者服务器集群这样的应用上。client pull的方法不能保证实时,而且要消耗客户端的资源,server push消耗的更多的是服务资源,两者各有利弊吧。
不过在以上的几个应用里,comet是非常好的。

 回复 引用 查看   
#5楼[楼主] 2009-01-20 10:49 | lzlynn      
@welshem
呵呵,这套框架很有代表性,所以我打算改进并丰富它。
希望大家都能参与进来。

 回复 引用 查看   
#6楼 2009-01-20 10:55 | 谢慧琦      
其实我想知道其核心是怎样实现的或者说原理是什么?
是不是类似java的使用线程让网页长时期不下载完成?

 回复 引用 查看   
#7楼[楼主] 2009-01-20 11:01 | lzlynn      
@谢慧琦
只是单纯的保持http连接
“是不是类似java的使用线程让网页长时期不下载完成?”可以当作一种实现方式,只是有点不够优雅。
http是可以实现长连接的,也叫做“全连接”,只是大家在考虑性能时,不去使用罢了。

 回复 引用 查看   
#8楼 2009-01-20 12:32 | Evernory      
关注
 回复 引用 查看   
#9楼 2009-01-20 13:08 | JimLiu      
--引用--------------------------------------------------
谢慧琦: 服务器与客户端保持长时间的连接,这样客户端的用户会比使用client pull的方式减少很多很多吧?
--------------------------------------------------------
应该不能这么说吧,更大程度上是改变了请求的生命周期,Ajax方式是使用多次零散的请求(比如轮询),而Comet是用一个生命周期很长的请求

 回复 引用 查看   
#10楼[楼主] 2009-01-20 13:44 | lzlynn      
@JimLiu
呵呵,简洁明了。

 回复 引用 查看   
#11楼[楼主] 2009-01-20 13:49 | lzlynn      
ps:一套好的开源框架,远比一个封装的应用对大家更有价值。
 回复 引用 查看   
#12楼 2009-01-20 17:27 | 谢慧琦      
--引用--------------------------------------------------
JimLiu: --引用--------------------------------------------------
谢慧琦: 服务器与客户端保持长时间的连接,这样客户端的用户会比使用client pull的方式减少很多很多吧?
--------------------------------------------------------
应该不能这么说吧,更大程度上是改变了请求的生命周期,Ajax方式是使用多次零散的请求(比如轮询),而Comet是用一个生命周期很长的请求
--------------------------------------------------------
类似sql server,如果你连接sql server长时期不断开,会造成什么后果?

 回复 引用 查看   
#13楼[楼主] 2009-01-21 08:59 | lzlynn      
@谢慧琦
长生命周期和超时之间总会有一个平衡,要看应用是否需要。比如股票监控这样对实时要求很高的需求,使用comet并不过分。

 回复 引用   
#14楼 2009-01-21 09:48 | Leele[未注册用户]
"COMET的理念是先进而直接的"
comet和ServerPush不是新概念,他甚至比ajax的前身还早。只不过没有ajax那么完美的解决方案

 回复 引用 查看   
#15楼[楼主] 2009-01-21 14:44 | lzlynn      
@Leele
总不会有完美的实物,不过希望大家都来讨论下comet。

 回复 引用   
#16楼 2009-02-12 21:32 | omeweb[未注册用户]
你好,这个框架我测试过,并发100-200的时候,w3wp的CPU就耗到100%了;不知道你测试过没有??期待