`

Comet,下一代Ajax?

    博客分类:
  • Ajax
阅读更多
   最近在看comet(server push)技术,经过一番google之后,大致理清了头绪,目前已经研究完一个开源的comet实现:pushlet([url]http://www.pushlets.com),包括前台的js,html代码以及后台的java代码,也基本搞清楚了关于pushlet的处理机制并且胡乱写了一部分pushlet的学习笔记,目前还在整理中,到时候将与大家分享!
    接下来的打算看另外两个开源的comet实现:dwr 2.0的reverse ajax和dojo的io.bind(),
如果有志同道合者大家可以一起来研究共同提高!

概念
     关于comet的最初定义来自这篇blog文章:http://alex.dojotoolkit.org/?p=545
     简单的说就是客户端发送一个请求,服务器接收它,并使用一个无限循环,将客户端需要的数据push到response中,并进行刷新,但是该response并不关闭,继续接收新的数据并刷新,直到客户端断开连接,该循环才结束退出。
     我们可以认为ajax解决了单用户响应的问题,而comet则解决了在保证性能的前提下进行协同多用户的响应问题。
     comet的优点在于它可以在任何时候向客户端发送数据,而不仅仅只是响应用户的输入请求。而发送数据是在一个已有的单连接上进行的。因此可以大大降低发送数据的延迟时间(建立connection的开销,以及客户端发送请求的等待时间)。

关于Event Web Server
     comet技术的一个重要组成部分就是event-drived web server,目前商用的实现已经出现,如lightstreamer(http://www.lightstreamer.com),这个我没有仔细看,只是跑了一下他给出的demo,还行!开源的实现就是apache+jetty(还要加一个mod)这个我还没有具体用过!

     有国人声称实现了comet server(http://cnc.agile.com/read.php?tid=319),还没去仔细研究,不知道如何。

      pushlet目前使用的是client pull做法,当然它的server push也将在不久的将来实现,它没有声称只能在专用的event-drived web server上运行,目前在tomcat运行环境下是可以的,不知道最多能承受多少用户同时访问还有待考证!

comet新体验
      我看了一下comet技术的一些实现,其中meebo(http://wwwm.meebo.com/)算是做的比较好的一个(gmail有谁用过?说说感受),我觉得它的web版本msn messager,比微软自己的web msn就要好用的多。
分享到:
评论
36 楼 kettas 2011-10-15  
我觉得我距离这些还有点距离。不过留下来慢慢看
35 楼 zb1015 2007-09-20  
这里有人提到过flash,我用applet做过一个,也不错,现在GlassFish已经容入了java webstart,applet发布更方便了
34 楼 rasonyang 2007-08-23  
结合Continuations使用Comet,效率能够提高10倍。详见
http://www.ibm.com/developerworks/cn/java/j-jettydwr/index.html
33 楼 fkpwolf 2007-07-20  
what about Grizzly?
32 楼 zyihang789 2007-07-09  
我现在的项目是一个实时监控系统,需要将server端的数据push到client端,push的条件是页面元素的数据发生变化。现在正在研究jetty6中的实现。第一次接触comet方式的东西。大家能不能给些建议阿?
31 楼 lukeshei 2007-04-14  
你可以上 http://rd-program.blogspot.com 參考我對comet 一系列的文章
30 楼 pppppp 2007-03-06  
tomcat6已经支持comet
29 楼 hexiaodong 2007-01-22  
通过一个iframe连接到服务器上,服务器在需要的时机发送js代码,iframe收到代码的时候,会即时执行。
28 楼 cleverpig 2007-01-09  
写了一些关于Comet技术的介绍,有兴趣的分享一起一下:
Comet技术介绍
27 楼 hexiaodong 2007-01-07  
普通的符合servlet规范的web容器,并不支持真正的comet服务。因此,我怀疑dwr2.0的reverse ajax只能通过client poll来模拟comet 连接。
26 楼 konas 2007-01-06  
我測試了DWR 2.0的reverse ajax
發現他還是client poll

請問要如何使用DWR 2.0 reverse ajax的comet ?
25 楼 konas 2007-01-06  
我測試了DWR 2.0的reverse ajax
發現他還是client poll

請問要如何使用DWR 2.0 reverse ajax的comet ?
24 楼 hpq852 2006-12-27  
基于 NIO 的web server 能够有效的解决线程分配的问题.

但由于是长连接, 客户端数量越来越多时候,仍然难以解决负载问题.

http://www.iteye.com/topic/39063
23 楼 hexiaodong 2006-12-27  
常常有Javaeyer通过短信问我要CometServer的源代码,特发一个附件在此
22 楼 macrochen 2006-10-26  
mineral 写道

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



在看jetty的相关文档的时候,我发现了continuation(延续)这个东东,而continuation是java语言本身不支持的,jetty做到了这一点,目前我还没搞懂它与长连接之间是什么关系,在dwr 2.0的DwrSystem.java中看到了这样的代码:
static
    {
        try
        {
            continuationClass = LocalUtil.classForName("org.mortbay.util.ajax.Continuation"); //$NON-NLS-1$
            suspendMethod = continuationClass.getMethod("suspend", new Class[] { Long.TYPE }); //$NON-NLS-1$
            resumeMethod = continuationClass.getMethod("resume", new Class[] {}); //$NON-NLS-1$
            getObject = continuationClass.getMethod("getObject", new Class[] {}); //$NON-NLS-1$
            setObject = continuationClass.getMethod("setObject", new Class[] { Object.class }); //$NON-NLS-1$
        }
        catch (Exception ex)
        {
            log.debug("No Jetty ContuniationSupport class, using standard Servlet API"); //$NON-NLS-1$
        }
    }

... ...
public void pollPreStreamWait()
    {
        WebContext context = WebContextFactory.get();
        Container container = context.getContainer();

        final ScriptSession scriptSession = context.getScriptSession();
        ServerLoadMonitor monitor = (ServerLoadMonitor) container.getBean(ServerLoadMonitor.class.getName());
        long sleepTime = monitor.timeWithinPollPreStream();

        synchronized (scriptSession.getScriptLock())
        {
            // Don't wait if there are queued scripts
            if (scriptSession.getQueuedScripts() > 0)
            {
                return;
            }

            // If this is Jetty then we can use Continuations
            HttpServletRequest request = context.getHttpServletRequest();

            boolean useSleep = true;
            Object continuation = request.getAttribute(ATTRIBUTE_JETTY_CONTINUATION);
            if (continuation != null)
            {
                useSleep = false;

                try
                {
                    // create a listener 
                    ScriptConduit listener = (ScriptConduit) getObject.invoke(continuation, new Object[0]);
                    if (listener == null)
                    {
                        listener = new SystemScriptConduit(continuation);
                        setObject.invoke(continuation, new Object[] { listener });
                    }
                    scriptSession.addScriptConduit(listener);

                    // continuation.suspend(sleepTime);
                    // NB. May throw a Runtime exception that must propogate to the container!
                    suspendMethod.invoke(continuation, new Object[] { new Long(sleepTime) });
                }
                catch (InvocationTargetException ex)
                {
                    ContinuationUtil.rethrowIfContinuation(ex.getTargetException());

                    log.warn("Error in Reflection", ex.getTargetException()); //$NON-NLS-1$
                    useSleep = true;
                }
                catch (Exception ex)
                {
                    log.warn("Exception", ex); //$NON-NLS-1$
                    useSleep = true;
                }
            }

            if (useSleep)
            {
                // create a listener // TODO avoid the expense of creation and registration
                ScriptConduit listener = new ScriptConduit()
                {
                    public boolean addScript(String script)
                    {
                        try
                        {
                            synchronized (scriptSession.getScriptLock())
                            {
                                scriptSession.getScriptLock().notifyAll();
                            }
                        }
                        catch (Exception ex)
                        {
                            log.warn("Failed to notify all ScriptSession users", ex); //$NON-NLS-1$
                        }

                        // just listening!
                        return false;
                    }

                    public void flush()
                    {
                    }
                };
                scriptSession.addScriptConduit(listener);

                // The comet part of a poll request
                try
                {
                    scriptSession.getScriptLock().wait(sleepTime);
                }
                catch (InterruptedException ex)
                {
                    log.warn("Interupted", ex); //$NON-NLS-1$
                }
                finally
                {
                    scriptSession.removeScriptConduit(listener);
                }
            }
        }
    }

不过目前我还没有搞清楚这些代码是起什么作用的。
21 楼 macrochen 2006-10-26  
ppeter 写道
我没有看过comet是什么东西,按照各位的讨论看来,这种技术可以运用到基于web的聊天程序实现.
最近几个月一直在做基于web的聊天程序,主要是运用了xmpp协议,关于这个协议的详细信息,大家不妨可以google一下.运用这个协议,有很多开源的组件包,比如smack.聊天的客户端和服务器端都有开源项目,我用过webchat,wildfire,等.推荐大家有需要的话可以去看看.

基于其他协议(非http协议)不在研究范围之内。
20 楼 macrochen 2006-10-26  
jerry.li 写道
pushlet 性能并不是很好,不知道dwr2.0的push做的怎么样。如果性能得不到提升,那末comet技术还是不用的好。

pushlet性能好不好咱没测试不好下结论,不过他的实现还是比较容易理解的,dwr 2.0所谓reverse ajax部分的源代码刚看完,在reverseAjax中使用的是poll方式来模拟push操作的,也就是在客户端使用setTimeout,不断的发送请求获取新的内容。至于性能好不好我不说大家也应该知道了
下面是dwr的java-chat demo中使用reverse ajax的几个关键代码点:
首先是在onload中进行设置
引用

<body onload="DWREngine.setReverseAjax(true);">


然后是engine.js中的代码
引用

DWREngine.setReverseAjax = function(reverseAjax) {
  DWREngine._reverseAjax = reverseAjax;
  if (DWREngine._reverseAjax) {
    DWREngine._triggerNextPoll(0);
  }
};

DWREngine._triggerNextPoll = function(pause) {
  setTimeout("DWREngine._poll()", pause);
}


_poll函数中就是发送请求了。


19 楼 hexiaodong 2006-10-25  
另外有一个线程,仅仅把新接受到的request加入到任务队列中,这个线程对请求不做分和分析处理,因此它能够高效及时地把请求插入队列中,而不至请求的丢失。
18 楼 mineral 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的时候,是不是就停止响应,这个问题。

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

17 楼 layout 2006-10-25  
以前做一个消息平台的时候也看到过这样的技术,所谓的pullet其实就是一个长线程(servlet或者jsp)一直在遍历等待,有内容就写出去。这样子对于服务器的线程是个考验,尤其是对于大并发的情况下,几乎服务器没有能力去处理其他的请求了。
但是对于客户端刷新获取消息的方式对与服务器的压力也不小,就算每分钟请求一下(心跳机制),如果有几千人同时在线,心跳一致了也是很夸张的。尤其是心跳形成共振,瞬间并发量增加对于服务器也是相当可怕的事情。
有几种解决办法:
1.flash+sockets+servlet
2.applet+sockets+servlet+守护进程
3.前台刷新+后台cache
我们当时采用的是2,applet+sockets+servlet进行通行,工作良好,使用后台推的方式。
对于第三种方式可能是目前的一种中和解决办法,后台的守护进程将需要的信息读取出来放在一个cache container里面,前台来访问的时候只需要从容器中读取对应的信息,这样子不需要重新到数据库中或者其他的地方去进行复杂的业务逻辑处理,减小心跳的处理时间,降低心跳共振的机率。同时可以通过一些算法,将心跳的时间平均摊开,不至于同时对服务器发起请求。

相关推荐

    comet的ajax实现

    comet两种实现之一的ajax实现,内部有源代码,这是一个聊天室的例子

    Comet,反向Ajax,直接就能跑

    dwr comet 反向ajax实力 直接抛 我打了一个包, 放到Tomcat,jetty下面就能直接跑了 很方便 还有注视 对新手 。。。。很好的

    comet-ajax

    comet-ajax聊天comet-ajax聊天comet-ajax聊天comet-ajax聊天comet-ajax聊天comet-ajax聊天comet-ajax聊天comet-ajax聊天comet-ajax聊天

    Comet, 下一代反向AJAX(即服务器推送技术- Server-side push)

    Comet 有时也称反向 Ajax 或服务器端推技术(server-side push)。其思想很简单:将数据直接从服务器推到浏览器,而不必等到浏览器请求数据。听起来简单,但是如果熟悉 Web 应用程序,尤其是 HTTP 协议,那么您就会...

    comet-ajax.rar

    Comet技术与Ajax技术在Web开发中的应用 Comet技术和Ajax技术都是Web应用程序中实现实时交互的重要手段,它们改变了传统的HTTP请求-响应模式,提升了Web应用的用户体验。在这篇文章中,我们将深入探讨这两种技术,...

    Ajax和Comet技术总结

    Comet是一种用于实现实时双向通信的技术,与传统的Ajax请求不同,Comet允许服务器向客户端推送数据,而不是仅由客户端发起请求。这在实时应用如聊天、股票报价或在线游戏等场景中特别有用。Comet有多种实现方式,...

    asp.net comet例子

    总结来说,这个ASP.NET Comet例子展示了如何利用Ajax和可能的IFrame技术在不同浏览器环境下实现实时的数据推送。开发者可以通过分析提供的Service.aspx和Service.aspx.cs文件,以及客户端的ajax.html,学习如何在ASP...

    comet4j 所需js以及comet4j-tomcat6.jar、comet4j-tomcat7.jar包

    在实际应用中,使用Comet4j可以显著提升用户体验,因为它避免了传统的AJAX轮询带来的频繁请求和高延迟问题。同时,Comet4j也支持大规模并发,可以处理成千上万的并发连接,这对于构建高并发、实时性的互联网应用非常...

    comet demo 向客户端推送例子

    Comet技术是一种基于HTTP长连接的反向Ajax技术,它允许服务器向客户端浏览器主动推送数据,从而实现双向通信。在Web应用中,通常的HTTP请求是客户端发起的,而Comet打破了这种模式,使得服务器可以在适当的时候主动...

    Comet Reverse Ajax

    EXAMPLE CODE FOR "Comet & Reverse Ajax" by Crane & McCarthy, FirstPress 2008 GENERAL SETUP The examples presented here use Groovy on Grails, a Java-based web technology stack. More details at ...

    web推送 comet技术

    客户端通常需要JavaScript来接收并处理服务器推送的数据,这可能涉及到AJAX或者WebSocket的使用,尽管Comet4J主要基于HTTP长连接,但也可以通过WebSocket进行优化,以提供更低延迟的双向通信。 为了在MyEclipse和...

    comet4j开发指南

    Comet4J是一个专为Java平台设计的服务器推送技术框架,它充分利用了AJAX(XMLHttpRequest)技术,实现了一种高效、实时的双向通信机制。在传统的HTTP协议中,服务器与客户端的交互是基于请求-响应模型的,即客户端...

    comet4j.jar

    - **性能优化**:探讨Comet4j在高并发环境下的性能表现,以及如何通过优化设置或代码来提高系统效率。 - **安全性考虑**:了解在使用Comet技术时可能面临的安全问题,如跨站脚本攻击(XSS)、跨站请求伪造(CSRF)...

    comet的demo

    - **反向Ajax**:Comet技术有时被称为反向Ajax,因为它是服务器向浏览器推送数据,而不是传统的Ajax(Asynchronous JavaScript and XML)由浏览器发起请求获取数据。 2. **Comet技术类型**: - **HTTP流**:...

    comet4j实例

    2. **通道(Channel)**:类似于传统的HTTP请求,但在Comet模式下,一个通道可以保持长时间的开放状态。服务器端和客户端可以通过通道进行双向通信。 3. **事件驱动**:Comet4j基于事件模型,当服务器端有新的数据...

    comet框架例子项目

    在本"Comet框架例子项目"中,我们可以深入理解并学习如何利用Comet技术构建实时通信的应用。 Comet的核心理念是通过长时间保持一个HTTP连接来实现服务器到客户端的数据推送,而不是每次有新数据时都创建新的连接。...

    Python库 | comet_ml-2.0.12.tar.gz

    《Python库Comet_ml-2.0.12:跟踪、优化与实验管理》 在IT行业中,Python作为一门强大的开发语言,拥有丰富的库支持,其中Comet_ml就是一款专为机器学习和深度学习项目提供实验跟踪、模型优化以及协作功能的库。...

Global site tag (gtag.js) - Google Analytics