[3.28.7]Sometimes WebSocket connection can not establish

68 views
Skip to first unread message

takehar...@mobilus.co.jp

unread,
Feb 23, 2018, 1:17:54 AM2/23/18
to Xitrum web framework
Hi Ngoc-san

We are attempt to upgrade Xitrum from 3.25 to 3.28 on production.

With 3.28.7, some WebSocket connection can not established for several seconds(or minutes) after boot.
It will not occur if we repeat the test with the server running.
And we can not reproduce with 3.25.0
Is there any necessary warm up time or configuration?



Server code(Using HEAD(3.28.7) or f0f1606(3.25.0) from master branch of xitrum-new project )
@WEBSOCKET("echo")
class EchoWebSocketActor extends WebSocketAction {
  def execute() {
    log.debug("onOpen")
    context.become {
      case WebSocketText(text) =>
        log.info("onTextMessage: " + text)
        respondWebSocketText(text.toUpperCase)

      case WebSocketBinary(bytes) =>
        log.info("onBinaryMessage: " + ScalaRunTime.stringOf(bytes))
        respondWebSocketBinary(bytes)

      case WebSocketPing =>
        log.debug("onPing")

      case WebSocketPong =>
        log.debug("onPong")
    }
  }

  override def postStop() {
    log.debug("onClose")
    super.postStop()
  }
}


Client code(scala)
import org.asynchttpclient.DefaultAsyncHttpClientConfig
import org.asynchttpclient.DefaultAsyncHttpClient
import org.asynchttpclient.ws.WebSocketUpgradeHandler
import org.asynchttpclient.ws.WebSocketListener
import org.asynchttpclient.ws.WebSocket

object TestMain {
  val URL = "ws://localhost:8000/echo"

  private val client = {
    val TIMEOUT_MS = 5 * 1000
    val conf = new DefaultAsyncHttpClientConfig.Builder()
      .setConnectTimeout(TIMEOUT_MS)
      .setRequestTimeout(TIMEOUT_MS)
      .setReadTimeout(TIMEOUT_MS)
      .setConnectTimeout(TIMEOUT_MS)
      .setWebSocketMaxFrameSize(10 * 1024 * 1024)
      .build()
    new DefaultAsyncHttpClient(conf)
  }

  def main(args: Array[String]) {
    for (i <- 0 until 1000) {
      print(s"${i},")
      test()
    }
  }

  def test() {
    val l = new MyWebSocketListener
    val h = new WebSocketUpgradeHandler.Builder().addWebSocketListener(l).build()
    val ws = client.prepareGet(URL).execute(h).get()
    ws.sendCloseFrame().get()
  }

  class MyWebSocketListener extends WebSocketListener {
    override def onError(t: Throwable): Unit = {}
    override def onClose(websocket: WebSocket, code: Int, reason: String): Unit = {}
    override def onOpen(websocket: WebSocket): Unit = {}
  }
}

Client code throw
java.util.concurrent.ExecutionException: java.util.concurrent.TimeoutException: Request timeout to 192.168.1.180/192.168.1.180:8000 after 5000 ms



client code(Node.js)

const WebSocket = require('ws');

const started = [];
const errors = [];

const x = function(i){
  // console.log(i)
  const ws = new WebSocket('ws://localhost:8000/echo');
  ws.on('open', () => {
    ws.send(i);
    started.push(i);
  });
  ws.on('close', () => {
    // console.log('close',i);
  });
  ws.on('error', (e) => {
    // console.log('error', i, e);
    errors.push(i);
  });

  setTimeout(() => {
    // console.log('end', i);
    ws.close();
  }, 5000);

}
for(var i = 0; i < 1000; i++ ){
  x(i);
}

setTimeout(()=>{
    console.log("started", started.length);
    console.log("errors", errors.length);
}, 10000);

client code throw

error 716 { Error: connect ECONNRESET 192.168.1.15:8000
    at Object.exports._errnoException (util.js:1022:11)
    at exports._exceptionWithHostPort (util.js:1045:20)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1087:14)
  code: 'ECONNRESET',
  errno: 'ECONNRESET',
  syscall: 'connect',
  address: '192.168.1.15',
  port: 8000 }


Best Regards.


Ngoc Dao

unread,
Feb 23, 2018, 2:57:02 AM2/23/18
to Xitrum web framework
> Server code(Using HEAD(3.28.7) or f0f1606(3.25.0) from master branch of xitrum-new project )

I've just updated xitrum's mater branch to use Netty 4.1.22:

Can you try it with xitrum-new?

Instruction (just in case):

* Download or update xitrum's mater branch, then publish xitrum 3.28.8-SNAPSHOT to your local machine with the command "sbt publishLocal".
* Then modify build.sbt of your project (based on xitrum-new as you said) to use the new version 3.28.8-SNAPSHOT published above.

押田丈治

unread,
Feb 23, 2018, 4:17:09 AM2/23/18
to xitrum-f...@googlegroups.com
Thanks I tried 3.28.8-SNAPSHOT, but the result was the same with 3.28.8.

Screen capture.

Reproduce code is here.



--
You received this message because you are subscribed to the Google Groups "Xitrum web framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to xitrum-framework+unsubscribe@googlegroups.com.
Visit this group at https://groups.google.com/group/xitrum-framework.
To view this discussion on the web visit https://groups.google.com/d/msgid/xitrum-framework/04e9bf5a-2b6a-421a-a300-43f92ce72442%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--

------------------------------------------------------------------------------------
押田 丈治

モビルス株式会社
141-0031
東京都品川区西五反田1-21-8 KSS五反田ビル3F
電話番号:03-6417-9523 FAX:03-6417-9532
------------------------------------------------------------------------------------

Ngoc Dao

unread,
Feb 23, 2018, 8:09:43 AM2/23/18
to Xitrum web framework
I think there's problem with your test client code:
It tries to send close frame immediately (ws.sendCloseFrame().get()), without waiting for onOpen signal.

Try this example which is based on OkHttp library:

押田丈治

unread,
Feb 25, 2018, 7:54:16 PM2/25/18
to xitrum-f...@googlegroups.com
Thanks I try new one.
Is it take some seconds to open connection?
My node client test code wait 5 seconds before close.



For more options, visit https://groups.google.com/d/optout.

Ngoc Dao

unread,
Feb 25, 2018, 8:17:55 PM2/25/18
to Xitrum web framework
It should be fast to connect, much less than 5 seconds.

In your client test code, you should only send WebSocket message inside the onOpen handler, like in this example:

押田丈治

unread,
Feb 25, 2018, 8:47:38 PM2/25/18
to xitrum-f...@googlegroups.com
OkHttpClient against to 3.28.7 still has error.
But against to 3.25.0 has no error.

The difference between ↑ example is only readTimeout,connectTimeout,url

private void run() {
    OkHttpClient client = new OkHttpClient.Builder()
        .readTimeout(5000,  TimeUnit.MILLISECONDS)              //<- change 0 to 5000
        .connectTimeout(5000,  TimeUnit.MILLISECONDS)         //<- add this line
        .build();

    Request request = new Request.Builder()
        .url("ws://localhost:8000/echo")                                         // <- change url
        .build();
    client.newWebSocket(request, this);

    // Trigger shutdown of the dispatcher's executor so this process can exit cleanly.
    client.dispatcher().executorService().shutdown();
  }



[info] Running okhttp3.recipes.WebSocketEcho
java.net.SocketTimeoutException: timeout
at okio.Okio$4.newTimeoutException(Okio.java:230)
at okio.AsyncTimeout.exit(AsyncTimeout.java:285)
at okio.AsyncTimeout$2.read(AsyncTimeout.java:241)
at okio.RealBufferedSource.indexOf(RealBufferedSource.java:345)
at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:217)
at okhttp3.internal.http1.Http1Codec.readHeaderLine(Http1Codec.java:212)
at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:189)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:88)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:125)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:200)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:147)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:150)
at java.net.SocketInputStream.read(SocketInputStream.java:121)
at okio.Okio$2.read(Okio.java:139)
at okio.AsyncTimeout$2.read(AsyncTimeout.java:237)
... 23 more


For more options, visit https://groups.google.com/d/optout.

Ngoc Dao

unread,
Feb 25, 2018, 9:41:16 PM2/25/18
to Xitrum web framework
Maybe Netty or Xitrum has become slow to accept new WebSocket connections.
Let's investigate.

押田丈治

unread,
Feb 26, 2018, 1:22:01 AM2/26/18
to xitrum-f...@googlegroups.com

Ngoc Dao

unread,
Feb 26, 2018, 1:34:44 AM2/26/18
to Xitrum web framework
That's very good progress!

Can you compare the differences between the official WebSocket example of Netty, and the usage in Xitrum?
Maybe there's recent change in Netty's WebSocket feature, and Xitrum is not using the WebSocket feature correctly.

押田丈治

unread,
Feb 26, 2018, 4:57:06 AM2/26/18
to xitrum-f...@googlegroups.com
Ngoc-san

https://github.com/netty/netty/commit/0ae79c0823950c7127fa4801e2e331a3dee3edeb

That change is introduced from 4.0.35.(Xitrum-3.25 is using 4.0.30)
I'm not sure that change is effected to Xitrum.
But I changed WebSocketAction.scala like below and all connection successfully established.


Please check above.








For more options, visit https://groups.google.com/d/optout.

Ngoc Dao

unread,
Feb 26, 2018, 9:14:48 AM2/26/18
to Xitrum web framework
Thanks!

I'll release a new version soon.
Reply all
Reply to author
Forward
0 new messages