1

启动 CometD 时,我在 Tomcat 7.0 中遇到以下异常。如果我尝试推送消息,有时会花费更多时间 6000 毫秒来推送消息,并且一次推送两个消息,而不是一次全部推送。我试图将 10 推到 200,但情况没有改变。我已经在 CometD 服务器应用程序中包含了 jetty-websocket-7.6.10.v20130312.jar 和 jetty-server-7.6.13.v20130916.jar,但我仍然遇到了这个异常。

例外:

23 Oct, 2013 10:12:45 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [cometd] in context with path [/Samp] threw   exception
java.lang.NullPointerException
at org.eclipse.jetty.websocket.WebSocketFactory.upgrade(WebSocketFactory.java:238)
at org.eclipse.jetty.websocket.WebSocketFactory.acceptWebSocket(WebSocketFactory.java:396)
at org.cometd.websocket.server.WebSocketTransport.handle(WebSocketTransport.java:157)
at org.cometd.server.CometdServlet.service(CometdServlet.java:166)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.eclipse.jetty.servlets.CrossOriginFilter.handle(CrossOriginFilter.java:247)
at org.eclipse.jetty.servlets.CrossOriginFilter.doFilter(CrossOriginFilter.java:210)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:928)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:539)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:298)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)

23 Oct, 2013 10:12:46 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [cometd] in context with path [/Samp] threw exception
java.lang.IllegalStateException: Not supported.
at org.apache.catalina.connector.Request.startAsync(Request.java:1664)
at org.apache.catalina.connector.Request.startAsync(Request.java:1657)
at org.apache.catalina.connector.RequestFacade.startAsync(RequestFacade.java:1022)
at org.eclipse.jetty.continuation.Servlet3Continuation.suspend(Servlet3Continuation.java:189)
at org.cometd.server.transport.LongPollingTransport.handle(LongPollingTransport.java:289)
at org.cometd.server.CometdServlet.service(CometdServlet.java:166)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.eclipse.jetty.servlets.CrossOriginFilter.handle(CrossOriginFilter.java:247)
at org.eclipse.jetty.servlets.CrossOriginFilter.doFilter(CrossOriginFilter.java:210)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:928)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:539)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:300)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662) 

服务等级:

@Service
public class HelloService
{
@Inject
private BayeuxServer bayeux;
@Session
private ServerSession serverSession;

private static int msgCount = 0;

private  static Logger log;

@Listener("/service/java")
public void processMsgFromJava(ServerSession remote, ServerMessage.Mutable message)
{
    msgCount++;

    String msgId = "EVENT-"+msgCount;
    Date dt = Calendar.getInstance().getTime();

    Map<String, Object> input = message.getDataAsMap();
    String eventId = (String)input.get("eventID");

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

    String channelName = "/java/test";
    // Initialize the channel, making it persistent and lazy
    bayeux.createIfAbsent(channelName, new ConfigurableServerChannel.Initializer(){
        public void configureChannel(ConfigurableServerChannel channel){
            channel.setPersistent(false);
            channel.setLazy(false);
        }
    });

    // Publish to all subscribers
    ServerChannel channel = bayeux.getChannel(channelName);
    input.put("ms", System.currentTimeMillis());
    channel.publish(serverSession, input, null);
    log.info("Msg published 111111111111........"+msgId);
    System.out.println(channel.isPersistent());
 }
   }

客户端类:

private ClientTransport transport= null;
private BayeuxClient client = null;

private ClientSessionChannel clientSession = null;
public static int msgCount = 0;

public boolean pushToComet(String cometDURL, String subscriberChannel, Map<String,Object> msgToPublish) throws Exception{
    boolean isSuccess = true;

    try {

        Map<String, Object> options = new HashMap<String, Object>();

        /* Prepare the WebSocket transport*/
        WebSocketClientFactory wsFactory = new WebSocketClientFactory();
        wsFactory.start();
        ClientTransport wsTransport = new WebSocketTransport(null, wsFactory, null);
        wsTransport.setOption("maxNetworkDelay", 0);
        wsTransport.setOption("connectTimeout", 10000);
        wsTransport.setOption("idleTimeout", 10000);
        wsTransport.setOption("maxMessageSize", 8192);

        transport = LongPollingTransport.create(options);
    //  transport.setDebugEnabled(true);
        transport.setOption("maxNetworkDelay", 0);

        client = new BayeuxClient(cometDURL,wsTransport, transport);
        //client.setDebugEnabled(true);

        client.handshake();

        boolean handshaken = client.waitFor(2000, BayeuxClient.State.CONNECTED);
        if(handshaken){
            msgCount++;
            clientSession = client.getChannel(subscriberChannel);
            clientSession.publish(msgToPublish);
        }else{
            isSuccess=false;
            System.out.println("CommetD not connected????????");
        }
    } catch (Exception e) {
        isSuccess=false;
        e.printStackTrace();
    }finally{
//          close();
    }
    return isSuccess;
}

private void close(){
        clientSession.release();
        client.disconnect();
        client.waitFor(1000, BayeuxClient.State.DISCONNECTED);
        transport.terminate();

}

public void closeConn(){
    client.disconnect();
    client.waitFor(1000, BayeuxClient.State.DISCONNECTED);
    transport.terminate();
}

web.xml

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
     version="2.5">

<servlet>
    <servlet-name>cometd</servlet-name>
    <servlet-class>org.cometd.annotation.AnnotationCometdServlet</servlet-class>
    <init-param>
        <param-name>transports</param-name>
        <param-value>org.cometd.websocket.server.WebSocketTransport</param-value>
    </init-param>
    <init-param> 
        <param-name>services</param-name>
        <param-value>galaxy_comet.HelloService</param-value>
    </init-param>
    <init-param>
        <param-name>maxLazyTimeout</param-name>
        <param-value>-1</param-value>
    </init-param>
     <init-param>
        <param-name>timeout</param-name>
        <param-value>2000</param-value>
    </init-param>
    <init-param>
        <param-name>interval</param-name>
        <param-value>5000</param-value>
    </init-param>
    <init-param>
        <param-name>maxInterval</param-name>
        <param-value>10000</param-value>
    </init-param>
    <init-param>
        <param-name>maxQueue</param-name>
        <param-value>-1</param-value>
    </init-param>
    <init-param>
        <param-name>metaConnectDeliverOnly</param-name>
        <param-value>true</param-value>
    </init-param>
   <!--  <init-param>
        <param-name>multiFrameInterval</param-name>
        <param-value>200</param-value>
    </init-param> -->
    <load-on-startup>1</load-on-startup>

</servlet>
<servlet-mapping>
    <servlet-name>cometd</servlet-name>
    <url-pattern>/cometd/*</url-pattern>
</servlet-mapping>


<filter>
    <filter-name>cross-origin</filter-name>
    <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>cross-origin</filter-name>
    <url-pattern>/cometd/*</url-pattern>
</filter-mapping>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

jsp中的Javascript

(function($)
{
var cometd = $.cometd;

$(document).ready(function()
{
    function _connectionEstablished()
    {
        $('#body').append('<div>CometD Connection Established</div>');
    }

    function _connectionBroken()
    {
        $('#body').append('<div>CometD Connection Broken</div>');
    }

    function _connectionClosed()
    {
        $('#body').append('<div>CometD Connection Closed</div>');
    }

    // Function that manages the connection status with the Bayeux server
    var _connected = false;
    function _metaConnect(message)
    {
        if (cometd.isDisconnected())
        {
            _connected = false;
            _connectionClosed();
            return;
        }

        var wasConnected = _connected;
        _connected = message.successful === true;
        if (!wasConnected && _connected)
        {
            _connectionEstablished();
        }
        else if (wasConnected && !_connected)
        {
            _connectionBroken();
        }
    }

     function _metaHandshake(handshake)
    {
        if (handshake.successful === true)
        {
            cometd.batch(function()
            {
                cometd.subscribe('/java/test', function(message)
                {
                    var d = new Date();
                    $('#body').append('<div>Server Says: ' + message.data.eventID + ':'+ (d.getTime()-message.data.ms) + '</div>');
                });
            });
        }
    }

    // Disconnect when the page unloads
    $(window).unload(function()
    {
        cometd.disconnect(true);
    });

    var cometURL = "http://localhost:8080/cometd1/cometd";
    cometd.configure({
        url: cometURL,
        logLevel: 'debug'
    });

    cometd.addListener('/meta/handshake', _metaHandshake);
    cometd.addListener('/meta/connect', _metaConnect);

    cometd.handshake();
});
})(jQuery);

控制台消息总是打印为假通道是持久的()。

如果我在客户端类的 finally 中调用 close(),我会收到 NullPointerException。

我无法获得基准中提到的结果。我不确定我哪里出错了。我什至制作了 channel.setLazy(false) 但仍然需要时间。而且,如果多个客户端订阅了同一个频道,那么这些客户端的消息推送时间是不同的(例如,在第一个客户端中,如果它需要 2 秒,而在第二个客户端中,它需要 4 秒来发布等等)。意味着它不是一次广播消息。为什么会这样。我试过没有 websocket 传输。那个时候消息也被延迟了。现在,当我尝试同时使用 websocket 和 longpolling 时,我遇到了这个问题。在这方面的任何帮助和指导都会对我有很大帮助。

4

1 回答 1

0

CometD 2.x 实现的 WebSocket 传输仅适用于 Jetty,如CometD 文档所述

使用 CometD 3.x,您会发现基于 JSR 356 的传输,它可以在任何实现 JSR 356 的 Servlet 容器中移植。

IllegalStateException: Not supported调用时遇到的startAsync()错误配置问题也在CometD 文档中进行了说明

于 2013-10-23T09:16:51.237 回答