2015 0002 0016
Embedded Jetty is one of the more popular servers for ring applications. JMX can be useful for poking around the guts of Jetty, as well as making runtime config changes. Unfortunately, enabling JMX for an embedded Jetty isn’t a straightforward config change, and the process for doing so in Clojure is largely undocumented. So this is the guide that I wish existed when I found the need to profile Jetty. If you’d rather skip the commentary, I’ve put up a minimal clojure jmx-enabled server for perusal.
Most essentially, the version of Jetty that comes bundled in
ring-jetty-adapter
is too old (currently 7.6.13) to expose
meaningful JMX hooks. Thankfully there’s a modern ring adapter
that you can add to your dependency list:
which serves as a drop-in replacement for the official
ring-jetty-adapter
. Another relevant dependency is Jetty’s JMX
artifact:
The jetty-jmx
version should match with the version of
jetty-server
provided by ring-jetty9-adapter
.
While editing project.clj
, it’s important enable JMX on the JVM
level, and select a port:
Finally, the running Jetty server must opt-in to JMX by pointing to the appropriate “MBean,” which can be imported with:
The server can then be started with:
which attaches the MBean to the running Jetty server. Since the
run-server
command calls .start
on the Server
object before
returning it, it’s important to configure :join? false
to allow
thread execution to continue, preventing the following
.addEventListener
and .addBean
from being blocked.
With all of this, it should now be possible to start the server and
connect to the JMX port using jconsole
:
jconsole localhost:8001
Relevant info will be under the MBeans
tab. Useful fields include
org.eclipse.jetty.util.thread.queuedthreadpool.threads
for how many threads are allocated, and
org.eclipse.jetty.util.thread.queuedthreadpool.queueSize
to find out how many requests are waiting on threads.