论坛首页 Web前端技术论坛

Comet,下一代Ajax?

浏览 67883 次
该帖已经被评为良好帖
作者 正文
   发表时间:2006-10-17  
pi1ot 写道
我比较害怕和喜欢用感叹号的人交流,好像有个人在我面前冲着我大喊一样。

考,怎么开始喜欢使用感叹号了,一直没发觉这一点
0 请登录后投票
   发表时间:2006-10-17  
pushlet 性能并不是很好,不知道dwr2.0的push做的怎么样。如果性能得不到提升,那末comet技术还是不用的好。
0 请登录后投票
   发表时间:2006-10-19  
Comet就是保持长连接,一个请求就一直保持,除非自己实现web,否则很难实用
0 请登录后投票
   发表时间:2006-10-19  
我没有看过comet是什么东西,按照各位的讨论看来,这种技术可以运用到基于web的聊天程序实现.
最近几个月一直在做基于web的聊天程序,主要是运用了xmpp协议,关于这个协议的详细信息,大家不妨可以google一下.运用这个协议,有很多开源的组件包,比如smack.聊天的客户端和服务器端都有开源项目,我用过webchat,wildfire,等.推荐大家有需要的话可以去看看.
0 请登录后投票
   发表时间:2006-10-23  

1.没有做过大规模测试,能支持多少说不上来。但和servlet的实现还是有挺大差别的:由一个线程池(线程池的大小自己设置)来处理所有的这些连接,而不是每个线程处理一个连接。web容器中,不能在servlet里面向下面这样写代码:
	while(true){
		if(hasMsg()){
			sendMsgToBrowser();
		}
	}

的原因就在于普通web容器中线程与http连接之间一对一的关系:每个线程占用大量的cpu资源和内存资源,所以web容器中允许的http处理线程数是非常有限的,一般设置不会超过200。而我的CometServer里面使用线程池里面固定数量的线程来处理大量连接的:它们不断轮流去执行 Request 的 run()方法。


2、CometAction不是一个Servlet,不能获得session。但事实上action很可能期望能取到session,所以我自己借助HttpSessionListener来管理了session,以便能够 CometAction 用request(非servletRequest)获得session。request的state是必要的:为了加快accept的速度,在accept的时候,没有解析request的信息,而是在run的时候去解析的,因此request至少有两个状态:分别代表解析前和解析后的。但在开发CometAction的时候可以不必关心request的状态,只要确保Action的execute()能执行你期望的逻辑就可以了。记住,action的execute是会被线程池中不确定的某些线程以不确定的间隔不断被执行的,当然间隔不会很大,具体大小视服务器总共接受了多少的连接以及线程池中有多少线程而定。
0 请登录后投票
   发表时间:2006-10-23  
hexiaodong 写道


原因就在于普通web容器中线程与http连接之间一对一的关系:每个线程占用大量的cpu资源和内存资源,所以web容器中允许的http处理线程数是非常有限的,一般设置不会超过200。而我的CometServer里面使用线程池里面固定数量的线程来处理大量连接的:它们不断轮流去执行 Request 的 run()方法。



楼主可能不认同我的观点,我觉得你的线程池和你所讲的普通web容器的线程池没有本质的区别。理由如下:

你用jdk5的特性创建一个线程池,分配线程去执行Request的run,也就是说,其实还是用一个线程去执行了你的方法。假设初始化线程数为200,当你的池里的200个线程都在干活的时候,这个时候,第201个request,来了,你的socket.accept()可以接受到新的Request,但是池里仍然没有线程来供你干活了,会不会就停止响应了呢? 还是一个socket,一个线程来响应,这点和http web容器的线程池工作道理,本质是一样的。如果刚好run里的方法写得比较重的话,一样的是cpu和内存的杀手。

另外,http协议本身是无状态的,只是容器实现加上了httpSession的具体不同实现,而CometServer(不单指楼主的CometServer)要实时地保持着客户端连接的socket,保存request的状态信息,用户标识信息等,在性能上和实现难度上,是不是比http 的server实现,难度还要更高一点。欢迎大家热烈讨论

0 请登录后投票
   发表时间:2006-10-23  
唉,再说详细点,希望这次你能看懂。普通web服务器不能保持长连接,因为如果你想保持长连接,只有一个办法:那就要在servlet的service()方法内执行类似下面的代码:
	while(true){
		if(hasMsg()){
			sendMsgToBrowser();
		}
	}

service()方法里是有死循环的,这样的话,接受了一个长连接请求之后,这个线程就不能去处理其他的请求了。

但在我的CometServer中不是这样的,request中有run(),这个方法内不必有死循环来发送消息。而是线程池中的多个线程循环访问request对列中的request对象,并调用run()方法,run()执行完后立即从对列中取下一个request并执行run()。在request的run方法内,会根据url去执行一个action的execute方法。因此,你可以写一个不包含while(true){}的action来处理当前的request对象。这样,CometServer何须为每个request分配一个固定的线程?CometServer只是在执行run()的片刻为它分配了线程,但不象普通web 容器那样线程执行完的同时也把request销毁了。CometServer会把request重新插入对列,并在不久的将来再次执行它run()方法,以便把新的需要写入浏览器的消息发送出去。
1 请登录后投票
   发表时间:2006-10-25  
以前做一个消息平台的时候也看到过这样的技术,所谓的pullet其实就是一个长线程(servlet或者jsp)一直在遍历等待,有内容就写出去。这样子对于服务器的线程是个考验,尤其是对于大并发的情况下,几乎服务器没有能力去处理其他的请求了。
但是对于客户端刷新获取消息的方式对与服务器的压力也不小,就算每分钟请求一下(心跳机制),如果有几千人同时在线,心跳一致了也是很夸张的。尤其是心跳形成共振,瞬间并发量增加对于服务器也是相当可怕的事情。
有几种解决办法:
1.flash+sockets+servlet
2.applet+sockets+servlet+守护进程
3.前台刷新+后台cache
我们当时采用的是2,applet+sockets+servlet进行通行,工作良好,使用后台推的方式。
对于第三种方式可能是目前的一种中和解决办法,后台的守护进程将需要的信息读取出来放在一个cache container里面,前台来访问的时候只需要从容器中读取对应的信息,这样子不需要重新到数据库中或者其他的地方去进行复杂的业务逻辑处理,减小心跳的处理时间,降低心跳共振的机率。同时可以通过一些算法,将心跳的时间平均摊开,不至于同时对服务器发起请求。
0 请登录后投票
   发表时间:2006-10-25  
hexiaodong 写道
唉,再说详细点,希望这次你能看懂。普通web服务器不能保持长连接,因为如果你想保持长连接,只有一个办法:那就要在servlet的service()方法内执行类似下面的代码:
	while(true){
		if(hasMsg()){
			sendMsgToBrowser();
		}
	}

service()方法里是有死循环的,这样的话,接受了一个长连接请求之后,这个线程就不能去处理其他的请求了。

但在我的CometServer中不是这样的,request中有run(),这个方法内不必有死循环来发送消息。而是线程池中的多个线程循环访问request对列中的request对象,并调用run()方法,run()执行完后立即从对列中取下一个request并执行run()。在request的run方法内,会根据url去执行一个action的execute方法。因此,你可以写一个不包含while(true){}的action来处理当前的request对象。这样,CometServer何须为每个request分配一个固定的线程?CometServer只是在执行run()的片刻为它分配了线程,但不象普通web 容器那样线程执行完的同时也把request销毁了。CometServer会把request重新插入对列,并在不久的将来再次执行它run()方法,以便把新的需要写入浏览器的消息发送出去。


你这里写的我明白你的意思。可能是我上一贴没有说清楚我的问题。我换个方式说:

hexiaodong 写道
执行run()的片刻为它分配了线程


虽然我相信你的run里执行只需要比较短的一个时间片断,如果使用小型机以上高配置的服务器,甚至速度更快;我问的问题是:存在线程池里所有的线程都是busy的状态,这个时候进来新的Request的时候,是不是就停止响应,这个问题。

准备用压力工具去验证一下我的想法。

0 请登录后投票
   发表时间:2006-10-25  
另外有一个线程,仅仅把新接受到的request加入到任务队列中,这个线程对请求不做分和分析处理,因此它能够高效及时地把请求插入队列中,而不至请求的丢失。
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics