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?!