tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Bruce Huang <mailbru...@gmail.com>
Subject Re: Does Tomcat8 NIO2 connector support Apache CometEvent?
Date Wed, 02 Nov 2016 04:19:26 GMT
Mark Thomas <markt@apache.org> 於 2016年11月1日 週二 下午6:06寫道:

> On 01/11/2016 09:44, Bruce Huang wrote:
> > Hi all,
> >
> > We have a simple servlet which implements Apache CometEvent for long
> > polling connection on tomcat8. It works well when we used
> > org.apache.coyote.http11.Http11NioProtocol, however, we have now changed
> to
> > using org.apache.coyote.http11.Http11Nio2Protocol and it will not work
> > properly.
> >
> > Tomcat: v8.0.23
> > JDK: v1.8.0_45
> > OS: Windows server 2008 R2
>
> The first thing to do is to test the latest 8.0.x release.
>
> Keep in mind that Comet is deprecated so if there is still a bug in
> 8.0.x, fixing it might not be a priority. Switching back to NIO may be a
> better option.
>
> Mark
>
>
Thanks for your suggestion.

I have tested on 8.0.38 release, but it even can't close the comet
properly. On 8.0.23, after OutputStream.close(), I have to do event.close()
to make the END event to be fired correctly.

ServletOutputStream servletOutputStream =
event.getHttpServletResponse().getOutputStream();

servletOutputStream.write(triggerMessage);
servletOutputStream.flush();
servletOutputStream.close();

event.close(); // add for NIO2

I found that the event.close() won't work from v8.0.27~8.0.38 and I could
make the comet to be connected start from v8.0.9 to v8.0.38, but
event.setTimeout() are not working on both of them.

Since our server is running on Windows platform, we have to switch to NIO2
for this issue
http://tomcat.10.x6.nabble.com/Tomcat-8-uses-high-CPU-td5049333.html

Bruce


> >
> > The connector setting as below:
> >
> > <Connector port="8443"
> > protocol="org.apache.coyote.http11.Http11Nio2Protocol"
> >    maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
> >    clientAuth="false" sslProtocol="TLS" connectionTimeout="60000"
> >    keystoreFile="D:\localhost.jks" keystorePass="******" />
> >
> > The timeout of the event will not work as we have set it to 300
> seconds(by
> > event.setTimeout(300000)), the comet connection will be disconnected
> after
> > 60 seconds which I believe is the connector connection timeout. And there
> > will have thrown an exception as below
> >
> > 28-Oct-2016 15:04:33.748 SEVERE [http-nio2-8443-exec-5]
> > org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process
> Error
> > reading request, ignored
> > java.lang.IllegalStateException: Reading not allowed due to timeout or
> > cancellation
> >     at
> > sun.nio.ch
> .AsynchronousSocketChannelImpl.read(AsynchronousSocketChannelImpl.java:249)
> >     at
> > sun.nio.ch
> .AsynchronousSocketChannelImpl.read(AsynchronousSocketChannelImpl.java:297)
> >     at
> > org.apache.tomcat.util.net
> .SecureNio2Channel.read(SecureNio2Channel.java:792)
> >     at
> > org.apache.tomcat.util.net
> .Nio2Endpoint.awaitBytes(Nio2Endpoint.java:871)
> >     at
> >
> org.apache.coyote.http11.Http11Nio2Protocol$Http11ConnectionHandler.release(Http11Nio2Protocol.java:180)
> >     at
> >
> org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:722)
> >     at
> > org.apache.tomcat.util.net
> .Nio2Endpoint$SocketProcessor.doRun(Nio2Endpoint.java:1073)
> >     at
> > org.apache.tomcat.util.net
> .Nio2Endpoint$SocketProcessor.run(Nio2Endpoint.java:1032)
> >     at
> >
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
> >     at
> >
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
> >     at
> >
> org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
> >     at java.lang.Thread.run(Thread.java:745)
> >
> > If the client makes the comet connection again after this, and the other
> > client tries to send message. The comet will be END immediately and
> > connection disconnected.
> >
> >
> > The Connect servlet as below
> >
> > public class Connect extends HttpServlet implements CometProcessor {
> >
> >     ...
> >
> >     public void event(CometEvent event) throws IOException,
> > ServletException {
> >         HttpServletRequest request = event.getHttpServletRequest();
> >         HttpServletResponse response = event.getHttpServletResponse();
> >         if (event.getEventType() == CometEvent.EventType.BEGIN) {
> >             String deviceid = request.getParameter("id");
> >             MessageSender.getInstance().addConnection(deviceid, event);
> >             request.setAttribute("org.apache.tomcat.comet.timeout", 300 *
> > 1000);
> >             event.setTimeout(300 * 1000);
> >         } else if (event.getEventType() == CometEvent.EventType.ERROR) {
> >             MessageSender.getInstance().removeConnection(event);
> >             event.close();
> >         } else if (event.getEventType() == CometEvent.EventType.END) {
> >             MessageSender.getInstance().removeConnection(event);
> >             event.close();
> >         } else if (event.getEventType() == CometEvent.EventType.READ) {
> >             throw new UnsupportedOperationException("This servlet does
> not
> > accept data");
> >         }
> >     }
> > }
> >
> > And we have another Trigger servlet for sending message to client:
> >
> > public class Trigger extends HttpServlet {
> >     protected void doPost(HttpServletRequest req, HttpServletResponse
> resp)
> >             throws ServletException, IOException {
> >         byte[] receieveByteArray =
> ByteUtil.getHttpServletRequestBody(req);
> >         sendTrigger(req, resp, receieveByteArray);
> >     }
> >
> >     private void sendTrigger(HttpServletRequest req, HttpServletResponse
> > resp, byte[] trigger) throws IOException, ServletException
> >     {
> >         try
> >         {
> >             MessageSender.getInstance().sendTrigger(deviceId, trigger);
> >         } catch (Exception e)
> >         {
> >             logger.error("Send trigger has thrown exception: ", e);
> >         }
> >     }
> > }
> >
> > And the MessageSender class as below
> >
> > public class MessageSender
> > {
> >     private static final Map<String, CometEvent> connections = new
> > ConcurrentHashMap<String, CometEvent>();
> >
> >     public void addConnection(String deviceId, CometEvent event) {
> >         connections.put(deviceId, event);
> >     }
> >
> >     public void removeConnection(CometEvent event) {
> >
> >         while (connections.values().remove(event)) {
> >     }
> >
> >     public static MessageSender getInstance() {
> >         return instance;
> >     }
> >
> >     public void sendTrigger(String deviceId, byte[] triggerMessage)
> throws
> > IOException, ConnectionNotFoundException {
> >         CometEvent comet = connections.get(deviceId);
> >         HttpServletResponse response = comet.getHttpServletResponse();
> >         response.addHeader("Content-Length",
> > Integer.toString(triggerMessage.length));
> >         response.addHeader("Content-Language", "en-US");
> >
> >         ServletOutputStream servletOutputStream =
> > response.getOutputStream();
> >         servletOutputStream.write(triggerMessage);
> >         servletOutputStream.flush();
> >         servletOutputStream.close();
> >
> >         comet.close(); // add for NIO2
> >         connections.remove(deviceId);
> >     }
> > }
> >
> >
> > Thanks,
> > Bruce
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message