3
votes

I am trying to understand the threading model for Tyrus websocket connection. Is Tyrus using one thread per websocket connection? Is there some thread pooling mechanism involved?

I tried to find a document that describe the internals of Tyrus implementation or any websocket implementation for Java on how thread model works, but I couldn't find any.

Any information on how thread model works to maintain websocket connections is helpful.

I am trying to optimize my server to be able to support thousands of websocket connections. Right now with only 1000 websocket connections JVM is using ~1800 threads!

Update 1:

I am using Tyrus 1.9 on Tomcat 8.

Server terminates about 500 websocket connections and also initiates 500 websocket connections to a different server. So we have about 1000 websocket connections on the server now.

One thing I noticed is TYRUS-275 issue which I guess is related to my case. It looks like that Tyrus client by default creates 3 threads per websocket connection. In my case I have around 500 connections so I should end up having around 1500 threads just for outgoing websocket connections.

It also looks like that if I enable shared container in Tyrus then I can benefit from using SELECTOR and WORKER thread pools.

client.getProperties().put(ClientProperties.SHARED_CONTAINER, true);
client.getProperties().put(GrizzlyClientProperties.SELECTOR_THREAD_POOL_CONFIG, ThreadPoolConfig.defaultConfig().setMaxPoolSize(3));
client.getProperties().put(GrizzlyClientProperties.WORKER_THREAD_POOL_CONFIG, ThreadPoolConfig.defaultConfig().setMaxPoolSize(10));

I am wondering now how to optimize the thread pools? How many SELECTOR and WORKER threads I need to have for 500 websocket connections? Is there a formula?

Update 2:

When I connect to JVM I see the following threads (listing interesting ones only):

- 24   x WebSocketServer-localhost-ROOT-xxxx [mostly parked]
- 1    x WebSocket background processing [mostly asleep]
- 10   x tyrus-1-thread-xx [mostly parked]
- 10   x tyrus-2-thread-xx [mostly parked]
- 1    x Tomcat JDBC Pool Cleaner [waiting]
- 1    x Signal Dispatcher [all running]
- 9    x nioEventLoopGroup-x-x [all running]
- 1    x main [all running]
- 177  x Keep-Alive-Timer [sleeping]
- 1    x java-sdk-htttp-connection-reaper [sleeping]
- 1    x http-apr-8080-Sendfile [waiting]
- 1    x http-apr-8080-Poller [running]
- 200  x http-apr-8080-exec-xxx [mostly parked with running slices]
- 1    x http-apr-8080-AsyncTimeout [sleeping]
- 1    x http-apr-8080-Acceptor-0 [running]
- ~630 x Grizzly(1) [mostly parked]
- ~634 x Grizzly(1) SelectorRunner [mostly running]
- ~635 x Grizzly(2) [moslty parked]

I guess Grizzly threads are the ones that Tyrus client is creating per websocket (BTW, I think I did not count Grizzly threads carefully. I think the count should be the same for all three of them). One selector two workers, correct?

I think http-apr-8080-exec-xxx are the threads created by tomcat. Are these threads taking care of incoming websocket connections? I am more interested to know about the following threads:

  • WebSocketServer-localhost-ROOT-xxxx
  • tyrus-x-thread-xx
  • nioEventLoopGroup-x-x
  • Keep-Alive-Timer
  • http-apr-8080-exec-xxx

Does anyone know what each set of threads do? Any document out there that explains this?

Also looks like that my Tomcat is set to use APR connector I was wondering using NIO or NIO2 can be a better idea in this situation?!

1
you should definitely use ClientProperties.SHARED_CONTAINER .. and you don't really need to set threadpools in that case, since grizzly will adjust them automatically. (634 selector runners is way to much, your current load can be handled by <5). - Pavel Bucek

1 Answers

3
votes

That depends on your environment. Tyrus (server!) itself should not create new threads, it just uses what containers (Glassfish, WebLogic, ... (Grizzly when running in standalone server mode)) provides.

Also, it depends on what you are doing in the Endpoints. If you are constantly receiving/sending messages in each connection, then there must be a thread for it. Otherwise, if you'll just connect and do nothing, Tyrus itself should not do anything, unless you are using heartbeat feature or something similar.

So, I cannot tell why your JVM is using that many threads (BTW are they all active? I doubt it..) - you need to provide much more info if you want to solve issues like that. You can start with providing code (executable would be best) for us to be able to reproduce what you see; feel free to move this to [email protected], it will probably end up in a conversation, which does not fit into "SO question/answer" model.