Re: Intercepting WebSocket ping messages
On 31/03/17 15:03, Robert Lewis wrote: > We have a Server <-> Client connection. The client periodically sends pings > to the server, and Tomcat will respond with a sendPong() on a container > thread, but the same instance of WsRemoteEndpointImplServer we are actively > sending writes on. WsRemoteEndpointImplServer.doWrite() does not seem > thread safe, so I have a feeling that tomcat handling the pongs on a > separate thread is interfering with our constant calls to doWrite() on the > same instance of WsRemoteEndpointImplServer. > > If I could synchronize the pong with our application application calls to > sendBinary(), I could fix a potential problem. If it is not supported, > completely understand. I apologize as I have yet to time this perfectly > where the calls do overlap. Do you happen to know if these calls will be > synchronized by the container? Yes, Tomcat should handle this for you. > I attached logging into WsRemoteEndpointImplServer (for doWrite() and > onWritePossible()), this includes start and end of the function calls, and > each start will show a hashcode of the WsRemoteEndpointImplServer instance, > and a hashcode of the SendHandler instance (endpointhash:handlerhash), > where two threads are making what seems not so thread safe calls. "seems"? Can you be more precise. To be clear, if you can show exactly what the problem is / how the thread-safety problem occurs then you stand a much greater chance of it being fixed. Mark > The first > thread is the application calling down to doWrite() (locked at the > application level) and the second thread is a container thread responding > to a ping: > > Thread 1 (Application Synchronized) > > http-nio-8443-exec-5: doWrite (start) 909703826:81194941 > java.lang.Thread.getStackTrace(Thread.java:1556) > > org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doWrite(WsRemoteEndpointImplServer.java:81) > > org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:453) > > org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessage(WsRemoteEndpointImplBase.java:341) > > org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:273) > > org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendBytes(WsRemoteEndpointImplBase.java:134) > > org.apache.tomcat.websocket.WsRemoteEndpointBasic.sendBinary(WsRemoteEndpointBasic.java:43) > > com.thingworx.communications.server.connection.jsr356.Jsr356ServerConnection.sendBinaryMessage(Jsr356ServerConnection.java:613) > > com.thingworx.communications.common.contexts.BaseContext.write(BaseContext.java:95) > > com.thingworx.communications.common.messaging.ThingworxMessage.writeContent(ThingworxMessage.java:39) > > com.thingworx.communications.server.modules.ServerCommunicationModuleBase.registerServerConnection(ServerCommunicationModuleBase.java:141) > > com.thingworx.communications.server.connection.jsr356.Jsr356ServerConnection.registerConnection(Jsr356ServerConnection.java:332) > > com.thingworx.communications.server.connection.jsr356.Jsr356ServerConnection.onMessage(Jsr356ServerConnection.java:304) > sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) > > sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) > > sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) > java.lang.reflect.Method.invoke(Method.java:498) > > org.apache.tomcat.websocket.pojo.PojoMessageHandlerWholeBase.onMessage(PojoMessageHandlerWholeBase.java:80) > > org.apache.tomcat.websocket.WsFrameBase.sendMessageBinary(WsFrameBase.java:592) > > org.apache.tomcat.websocket.WsFrameBase.processDataBinary(WsFrameBase.java:549) > org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:301) > > org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:131) > > org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:71) > > org.apache.tomcat.websocket.server.WsHttpUpgradeHandler$WsReadListener.onDataAvailable(WsHttpUpgradeHandler.java:185) > > org.apache.coyote.http11.upgrade.AbstractServletInputStream.onDataAvailable(AbstractServletInputStream.java:198) > > org.apache.coyote.http11.upgrade.AbstractProcessor.upgradeDispatch(AbstractProcessor.java:96) > > org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:664) > > org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520) > > org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476) > > java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) > > java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) > > org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) > java.lang.Thread.run(Thread.java:745) > http-nio-8443-exec-5:
Re: Intercepting WebSocket ping messages
We have a Server <-> Client connection. The client periodically sends pings to the server, and Tomcat will respond with a sendPong() on a container thread, but the same instance of WsRemoteEndpointImplServer we are actively sending writes on. WsRemoteEndpointImplServer.doWrite() does not seem thread safe, so I have a feeling that tomcat handling the pongs on a separate thread is interfering with our constant calls to doWrite() on the same instance of WsRemoteEndpointImplServer. If I could synchronize the pong with our application application calls to sendBinary(), I could fix a potential problem. If it is not supported, completely understand. I apologize as I have yet to time this perfectly where the calls do overlap. Do you happen to know if these calls will be synchronized by the container? I attached logging into WsRemoteEndpointImplServer (for doWrite() and onWritePossible()), this includes start and end of the function calls, and each start will show a hashcode of the WsRemoteEndpointImplServer instance, and a hashcode of the SendHandler instance (endpointhash:handlerhash), where two threads are making what seems not so thread safe calls. The first thread is the application calling down to doWrite() (locked at the application level) and the second thread is a container thread responding to a ping: Thread 1 (Application Synchronized) http-nio-8443-exec-5: doWrite (start) 909703826:81194941 java.lang.Thread.getStackTrace(Thread.java:1556) org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doWrite(WsRemoteEndpointImplServer.java:81) org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:453) org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessage(WsRemoteEndpointImplBase.java:341) org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:273) org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendBytes(WsRemoteEndpointImplBase.java:134) org.apache.tomcat.websocket.WsRemoteEndpointBasic.sendBinary(WsRemoteEndpointBasic.java:43) com.thingworx.communications.server.connection.jsr356.Jsr356ServerConnection.sendBinaryMessage(Jsr356ServerConnection.java:613) com.thingworx.communications.common.contexts.BaseContext.write(BaseContext.java:95) com.thingworx.communications.common.messaging.ThingworxMessage.writeContent(ThingworxMessage.java:39) com.thingworx.communications.server.modules.ServerCommunicationModuleBase.registerServerConnection(ServerCommunicationModuleBase.java:141) com.thingworx.communications.server.connection.jsr356.Jsr356ServerConnection.registerConnection(Jsr356ServerConnection.java:332) com.thingworx.communications.server.connection.jsr356.Jsr356ServerConnection.onMessage(Jsr356ServerConnection.java:304) sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) java.lang.reflect.Method.invoke(Method.java:498) org.apache.tomcat.websocket.pojo.PojoMessageHandlerWholeBase.onMessage(PojoMessageHandlerWholeBase.java:80) org.apache.tomcat.websocket.WsFrameBase.sendMessageBinary(WsFrameBase.java:592) org.apache.tomcat.websocket.WsFrameBase.processDataBinary(WsFrameBase.java:549) org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:301) org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:131) org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:71) org.apache.tomcat.websocket.server.WsHttpUpgradeHandler$WsReadListener.onDataAvailable(WsHttpUpgradeHandler.java:185) org.apache.coyote.http11.upgrade.AbstractServletInputStream.onDataAvailable(AbstractServletInputStream.java:198) org.apache.coyote.http11.upgrade.AbstractProcessor.upgradeDispatch(AbstractProcessor.java:96) org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:664) org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520) org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) java.lang.Thread.run(Thread.java:745) http-nio-8443-exec-5: onWritePossible (start) 909703826:81194941 java.lang.Thread.getStackTrace(Thread.java:1556) org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.onWritePossible(WsRemoteEndpointImplServer.java:97) org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doWrite(WsRemoteEndpointImplServer.java:89) org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:453)
Re: Intercepting WebSocket ping messages
On 30/03/17 21:13, Robert Lewis wrote: > Is there a way to intercept a ping message to send a pong? The API doesn't support this. > I need to do this synchronize sends to the endpoint. Could you clarify your requirement? Tomcat should handle pong messages automatically for you (as required by the spec). Mark - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Intercepting WebSocket ping messages
Is there a way to intercept a ping message to send a pong? I need to do this synchronize sends to the endpoint. I tried session.addMessageHandler(new javax.websocket.MessageHandler.Whole() { @Override public void onMessage(PongMessage message) { System.out.println("hi"); } }); And @OnMessage public void onPong(PongMessage message) {}