Monitoring Virtual Threads via JMX / MBeans in Tomcat

2025-03-05 Thread Joash Jose
Dear Apache Tomcat Support Team,

I hope this message finds you well.

I am writing to inquire whether Apache Tomcat (tomacat version is 10.1.33 
running on Java 21)  exposes virtual thread metrics through JMX / MBeans. 
Specifically:

Virtual Thread Visibility:

Does Tomcat provide MBeans (e.g., under Catalina:type=Executor) to monitor 
virtual thread usage, such as active virtual thread counts, creation rate, or 
parking states?
If not, are there plans to add such metrics in future releases?
Or any alternate ways with which we can monitor this from tomcat side.?

Configuration Clarification:
We have configured Tomcat 10.1.33 with,


While this works, the existing ThreadPool MBeans show currentThreadsBusy=-1 and 
maxThreads=200 (incorrect in case of virtual threads). Is this expected 
behavior?

JVM vs. Tomcat Metrics:
We observe that the JVM’s java.lang.management.ThreadMXBean includes virtual 
threads, but this aggregates data across all applications on the JVM. Does 
Tomcat offer a way to isolate virtual thread metrics specific to Tomcat?

Regards,
Joash
-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Monitoring Virtual Threads via JMX / MBeans in Tomcat

2025-03-05 Thread Joash Jose
Dear Apache Tomcat Support Team,

I hope this message finds you well.

I am writing to inquire whether Apache Tomcat (tomacat version is 10.1.33 
running on Java 21)  exposes virtual thread metrics through JMX / MBeans. 
Specifically:

Virtual Thread Visibility:

Does Tomcat provide MBeans (e.g., under Catalina:type=Executor) to monitor 
virtual thread usage, such as active virtual thread counts, creation rate, or 
parking states?
If not, are there plans to add such metrics in future releases?
Or any alternate ways with which we can monitor this from tomcat side.?

Configuration Clarification:
We have configured Tomcat 10.1.33 with,


While this works, the existing ThreadPool MBeans show currentThreadsBusy=-1 and 
maxThreads=200 (incorrect in case of virtual threads). Is this expected 
behavior?

JVM vs. Tomcat Metrics:
We observe that the JVM’s java.lang.management.ThreadMXBean includes virtual 
threads, but this aggregates data across all applications on the JVM. Does 
Tomcat offer a way to isolate virtual thread metrics specific to Tomcat?

Regards,
Joash
-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: Async servlet and request recycle synchronization

2025-03-05 Thread François Rajotte
Hi Christopher,

Thanks for your comments.

Regarding the behavior of the non-container thread when an async
request gets cancelled, I don't really care exactly how it's handled.
Currently, my strategy is to let it finish if it had already started
processing when the request got cancelled. Or abort processing if the
request got cancelled before processing began.
It's the first case that's giving me headaches.

Using a shared object that handles coordination between the two worlds
certainly makes things clearer from an architectural perspective.
However, I still feel like there's a fundamental issue here, no matter
how the coordination is designed.

When the onComplete signal is received, I feel compelled to NOT return
from the method until I can be certain that my application will no
longer use HTTP request/response objects. I can forward that signal to
the coordinator, but I must still wait for the "all clear" response.
Otherwise, as soon as the onComplete method returns, the container
tomcat can (and will!) recycle the HTTP request/response objects that
the non-container thread may still be referencing/using.
If the non-container thread isn't trying to write the response out at
that exact moment, then it's a trivial case and I can just discard the
HTTP request/response objects and return immediately.
But if the non-container thread is actively writing the response out,
then I should wait for the non-container thread to complete
processing. The non-container thread may already be executing
tomcat/container code, so aborting it at the application level is
pretty much impossible to do reliably.

Thanks again for your valuable insight,

Regards,
François

On Tue, Mar 4, 2025 at 2:43 PM Christopher Schultz
 wrote:
>
> François,
>
> On 3/4/25 10:32 AM, François Rajotte wrote:
> > Hi,
> >
> > I'm looking for advice on how to properly synchronize asynchronous
> > servlets that use the Java servlet 3.0 async APIs.
> >
> > Especially, I'm trying to avoid having the servlet experience
> > IllegalStateExceptions when accessing HttpServletRequest and
> > HttpServletResponse objects that tomcat has recycled.
> >
> > The theory I'm working with is that:
> > The servlet is accessing the HttpServletRequest and
> > HttpServletResponse objects from non-container threads. For example,
> > we can assume that an asynchronous operation has completed on some
> > thread and we want to send the response.
> > At any time, tomcat may decide to "complete" the request and recycle
> > the HttpRequest and HttpResponse objects. For example, the socket
> > could be disconnected or timed out. Tomcat notifies the servlet that
> > this is happening by calling the AsyncListener.onComplete method.
> >
> > The non-container thread may be accessing the HttpServletRequest and
> > HttpServletResponse objects while Tomcat is about to recycle the
> > objects. So it seems that some sort of synchronization is required at
> > the servlet level to avoid accessing recycled objects.
> > The strategy I have implemented is to acquire a lock at the servlet
> > level when processing the AsyncListener.onComplete callback and also
> > when accessing the HttpServletRequest and HttpServletResponse objects
> > from non-container threads. That way, we can be sure that the
> > non-container thread will never access recycled objects.
> >
> > However, I've noticed that implementing synchronization at the servlet
> > level introduces deadlocks between application locks and internal
> > tomcat locks.
>
> This is exactly what I'd expect, given the explanation above.
>
> Be advised, I'm not an expert at servlet async. I'm only looking at this
> from an architectural perspective, here.
>
> First, if Tomcat were still "allowed" to terminate the async request,
> what would you like the non-container thread to do? Continue? Stop?
> Something else?
>
> > Here are two stack traces taken from tomcat 9.0.97:
> >
> > Non-container thread calling
> > HttpServletResponse.getOutputStream().close(), while holding an
> > application-level lock:
> > java.lang.Thread.State: BLOCKED (on object monitor)
> >  at 
> > org.apache.coyote.AsyncStateMachine.asyncError(AsyncStateMachine.java:421)
> >  - waiting to lock <0x0007fc5feec0> (a
> > org.apache.coyote.AsyncStateMachine)
> >  at 
> > org.apache.coyote.AbstractProcessor.setErrorState(AbstractProcessor.java:121)
> >  at 
> > org.apache.coyote.AbstractProcessor.handleIOException(AbstractProcessor.java:665)
> >  at 
> > org.apache.coyote.AbstractProcessor.action(AbstractProcessor.java:388)
> >  at org.apache.coyote.Response.action(Response.java:207)
> >  at 
> > org.apache.catalina.connector.OutputBuffer.close(OutputBuffer.java:258)
> >  at 
> > org.apache.catalina.connector.CoyoteOutputStream.close(CoyoteOutputStream.java:176)
> >
> > Container thread calling AsyncListener.onComplete(), AsyncListener
> > implementation trying to acquire the application-level lock:
> >  > non-container thread>
> >