mock-server / mockserver

MockServer enables easy mocking of any system you integrate with via HTTP or HTTPS with clients written in Java, JavaScript and Ruby. MockServer also includes a proxy that introspects all proxied traffic including encrypted SSL traffic and supports Port Forwarding, Web Proxying (i.e. HTTP proxy), HTTPS Tunneling Proxying (using HTTP CONNECT) and SOCKS Proxying (i.e. dynamic port forwarding).
http://mock-server.com
Apache License 2.0
4.58k stars 1.07k forks source link

A memory leak caused by the reset method not removing subscribers ultimately leads to an OutOfMemoryError #1847

Open 1534196496 opened 7 months ago

1534196496 commented 7 months ago

Describe the issue A memory leak caused by the reset method not removing subscribers ultimately leads to an OutOfMemoryError

What you are trying to do Periodic reloading of Expectations.

MockServer version 5.15.0 To Reproduce ClientAndServer client = ClientAndServer.startClientAndServer(92); while (true) { client.when( request().withPath("/aaaa") ).withId("888") .respond( r -> response().withBody("1234") ); client.reset(); }

  1. How you are running MockServer (i.e maven plugin, docker, etc) java Client

  2. Code you used to create expectations ClientAndServer client = ClientAndServer.startClientAndServer(92); client .when(....) .respond(....)

  3. What error you saw oom

1534196496 commented 7 months ago

image

lnevaril commented 7 months ago

I was dealing with the same issue two weeks ago so I could provide more details. The problem occurs only when adding expectation of type ExpectationResponseCallback that leads to registration of WebSocketClient required for reading the request so it can be used for generating response. WebSocketClient is subscribed to MockServerEventBus to listen for STOP and RESET events. There is a single MockServerEventBus for each port stored in static final field EVENT_BUS_MAP within class MockServerClient. When calling org.mockserver.client.MockServerClient#reset, RESET event is propagated to each subscriber but the issue is that subscribers registered within MockServerEventBus are never cleared, therefore, WebSocketClients don't become eligible for garbage collection during the tests run.

In my case I was able to bypass the issue by using the method clear to clear logs and manually remove expectations by ids to avoid calling the reset method. Using org.mockserver.client.ForwardChainExpectation#respond(org.mockserver.mock.action.ExpectationResponseCallback) is necessary only for expectations that need the ability to read the request and by registering them only once it one can mitigate the problem. On the other hand, this state is far from ideal and subscribers in MockServerEventBus could be cleared once the event was propagated to them.