启动 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 时,我遇到了这个问题。在这方面的任何帮助和指导都会对我有很大帮助。