users@jersey.java.net

[Jersey] Jersey SSE scalability on the client

From: Svilen Genchev <svileng_at_gmail.com>
Date: Wed, 18 Feb 2015 16:17:46 +0200

Hi All,

I am looking into using Jersey SSE to replace current polling mechanics of
thousands of REST resources.The polling approach does not scale very well
with increasing the number of registered nodes.

I have a single client which manages a lot of servers in the sense that
using the client one can register up to 10 000 nodes/servers, whereas each
node has a set of REST resources.
Some of those resources are polled lets say on a 30 second interval
currently in order to keep the client up-to-date with information obtained
from the REST resources. The information is usually in the form of free
memory, disk space, cpu usage, etc.
Think monitoring of some JVM process (with a servlet container and Jersey)
running on a disparate hosts over HTTP/REST.
While since it is mostly a monitoring data,It is not that critical to the
client to be on par with the servers state down to the second (currently
the polling is using 30 seconds interval), however on the other hand, some
very important functionality of the client depends on whether a particular
REST server is online and in what state it is.

The data that is being polled itself is not supposed to change very often,
so I started looking into SSE with the idea that the client/server are
using some smart NIO approach in order not to keep the process busy if
there is no data/events currently to be transmitted on the wire.


So I've downloaded the latest jersey distro (2.18 I think) and started
looking at it. I quickly got the basic SSE example running.


The SSE resource is exactly as from the example, while the client is
something like this. COUNT_EVENT_SOURCE can be as much as 10 000:

public static void main(String[] args) {
        Client client =
ClientBuilder.newBuilder().register(SseFeature.class)
                .build();

        for (int i = 0; i < COUNT_EVENT_SOURCE; i++) {

            WebTarget target = client.target(Constants.ENDPOINT);

            EventSource eventSource = EventSource.target(target).build();

            final int count = i;
            EventListener listener = new EventListener() {
                @Override
                public void onEvent(InboundEvent inboundEvent) {
                    System.out.println("listener no. " + count + " event
name: " + inboundEvent.getName()
                            + "; " + inboundEvent.readData(String.class));
                }
            };
            eventSource.register(listener, "message-to-client");

            eventSource.open();

        }
}

I fired up a jvisualvm and observed that for each client a new thread is
being created which is kept alive as long as the connection to the SSE
resource is fine.

So if I have a client that wants to use SSE for communication with as much
as 10 000 SSE resources residing on different hosts/ports this would mean
that I would have 10 000 long living threads for each of the SSE resources
constantly taking up CPU time and 10 000 long living client sockets as well
right?

Which again does not seem like a very scalable approach...

Can a Thread Pool with some reasonable size be used instead?
In general, do you think that SSE is a good solution for a use case like
this one?

Thanks for reading this! :)

Regards,
Svilen