Skip to content

Jetty HttpConnections not closed with SSE on Jetty 12.0.7+ when clients close the connection #32629

Closed
@vakiovale

Description

@vakiovale

Description

Our Spring Boot 3.2.2 application experiences a memory leak leading to an OutOfMemoryError, with persistent org.eclipse.jetty.server.internal.HttpConnection objects found in the heap dump. This occurs when using Server-Sent Events (SSE) with Flux endpoints and is particularly evident after an EofException is thrown by Jetty after the client disconnects but the server attempts to continue emitting events. The issue has been replicated in a minimal project to demonstrate the behavior under specific configurations and versions.

Link to the example project on GitHub

The example application uses Spring Boot 3.2.4 (and Jetty 12.0.7) and has a Flux<ServerSentEvent> endpoint emitting heartbeats for a duration of 10 seconds.

Steps to Reproduce

  1. Clone the example project from the provided GitHub repository.
  2. Start the application using Java 17.0.9 on Spring Boot 3.2.4 with Jetty server 12.0.7.
  3. Use curl to connect to the SSE endpoint at localhost:9898/bug/hunt and then terminate the connection manually using Ctrl+C.
  4. Observe memory usage or take a heap dump to verify if HttpConnection instances remain in memory, especially after EofException occurs due to attempted heartbeat emissions.

Example

Doing this twice:

$ curl -v localhost:9898/bug/hunt
* processing: localhost:9898/bug/hunt
*   Trying [::1]:9898...
* Connected to localhost (::1) port 9898
> GET /bug/hunt HTTP/1.1
> Host: localhost:9898
> User-Agent: curl/8.2.1
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Fri, 12 Apr 2024 12:21:30 GMT
< Content-Type: text/event-stream
< Transfer-Encoding: chunked
< 
event:heartbeat: 0

event:heartbeat: 1

event:heartbeat: 2

^C

Taking a heap dump from the application (using IntelliJ IDEA's memory snapshot) and observing two instances of HttpConnection:
Screenshot from 2024-04-12 15-23-31

Expected Behavior

HttpConnection instances should be cleared from memory when the client disconnects, preventing any memory leaks.

Possible Solution

  • Downgrading to Jetty version 12.0.3 resolves the issue (works also when using Spring Boot 3.2.0)
  • Removing spring-boot-starter-web or setting the application to WebApplicationType.REACTIVE also mitigates the issue

Additional Context

  • We have observed the issue with Jetty versions 12.0.4, 12.0.7, and 12.0.8
  • We have not been able to reproduce this error outside of Spring Boot, and we are unsure of the underlying problem's source
  • Clarification Request: I would appreciate feedback on whether using spring-boot-starter-web together with reactive streams (like Flux) for SSE might be inherently problematic. We have simultaneously used spring-boot-starter-web and spring-boot-starter-webflux in our project, utilizing Flux<ServerSentEvent> endpoints without any issues. However, after upgrading our production environment from Spring Boot 3.0.5 to 3.2.2, we encountered this problem.

Thank you for your attention to this matter. I am more than happy to provide further details or additional information if needed.

Metadata

Metadata

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions