I'm building a notification system which allows clients to connect to a web-server and then get notified by server side events. I currently use Wildfly 16.0 standalone (on Windows) as web-server. I got server side events working with the example code below.

@GET @Path("register") @Produces("text/event-stream") public void subscribe(@Context SseEventSink sseEventSink, @HeaderParam(HttpHeaders.LAST_EVENT_ID_HEADER)) { while (true) { OutboundSseEvent sseEvent = this.eventBuilder .data("some data") .reconnectDelay(3000) .build(); CompletionStage<?> cs = sseEventSink.send(sseEvent); cs.whenComplete((x, y) -> { System.out.println("Completed " + x); if (y != null) y.printStackTrace(); }); Thread.sleep(5 * 1000); } sseEventSink.close(); } 

This solution is working for up to 120 connected clients with minimal server load, after that no new connections can be established.

I use ApacheBench, Version 2.3 for testing.

 ab -A 123:123 -c 120 -n 120 

If i go higher than 120 concurrent connections no one else can connect. This seems to me, that there is an active connection or stream or thread limit in place. If one user disconnects, another than can connect. I tried to set max-connections on the http-listener in the standalone.xml. This had no effect. I than simply added a zero to every connection / thread / pool option i could find. Still, no change.

Where to look next?

1

3 Answers

I think you are not facing a connection limit problem, but instead wildfly runs out of I/O threads. If you run an 8-core CPU, it would match your mentioned about 120 concurrent clients: from

Specify the maximum number of threads for the worker task thread pool.If not set, default value used which is calculated by formula cpuCount * 16

Increase the value with jboss-cli.sh:

/subsystem=io/worker=default:write-attribute(name=task-max-threads, value=1024) 

Or in standalone.xml:

<subsystem xmlns="urn:jboss:domain:io:3.0"> <worker name="default" task-max-threads="1024"/> <buffer-pool name="default"/> </subsystem> 
1

I believe that you are running out of connections because your subscribe method never returns because of that while (true) { ... } loop.

The following works for me:

@Singleton @Path("") public class BroadcastService { @Context private Sse sse; private SseBroadcaster broadcaster; @PostConstruct void initialise() { this.broadcaster = sse.newBroadcaster(); } @PreDestroy void shutdown() { this.broadcaster.close(); } @GET @Path("register") @Produces(MediaType.SERVER_SENT_EVENTS) public void subscribe(@Context SseEventSink sseEventSink) { this.broadcaster.register(sseEventSink); } @Schedule(second = "*/5", minute = "*", hour = "*", persistent = false) public void broadcastData() { OutboundSseEvent sseEvent = this.sse.newEventBuilder() .data("some data") .reconnectDelay(3000) .build(); this.broadcaster.broadcast(sseEvent); } } 

I tested with:

ab -c 2000 -n 4000 

and was still able to:

curl retry: 3000 data: some data retry: 3000 data: some data 

You can add max-connections connections attribute to http-listner tag. e.g.

<http-listener name="default" max-connections="1000" socket-binding="http" redirect-socket="https" enable-http2="true"/> 

With this you will be able to increase the maximum number of connections.

Note: This actually limits connections, without the attribute the implication is "unlimited"

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.