Which means: don't create the httpClient inside a function. Create it as a top-level variable in a project library script, so it will live a long time.
Moved all my client instants to top-level variables yesterday afternoon, and ever since then my bounded socket count has been steady. Thought you would be interested perhaps. Worked a charm, thank you Phil.
If possible, a big note on the httpClient docs page strongly saying not to instantiate httpClient objects with function calls would probably be pertinent.
Took me about a week of digging before I realized where the problem was coming from, let alone what the problem was, as port exhaustion is a hard problem to catch in the logs for someone who hasn't dealt with it before, like me.
Otherwise, I could see other people creating httpClient objects at a slow rate, and then a month later when they run out of ephemeral ports the server starts having issues.
@PGriffith have you reproduced this? Are the HttpClient objects leaking? Or do they get GC'd but somehow don't clean themselves up?
I've tried various times in the past to get httpClients and/or promise/response/etc objects to cause resource leaks and never succeeded. One common thread in user reports seems to be Windows, but even testing on Windows I've never succeeded.
I do think there's an issue, but I don't think it's in our own code, I think it's underlying in the JDK. I'm planning to explore explicit closing or making our HttpClient a context manager or something once we're on 21.
A year ago, I ended up troubleshooting this situation and found it to be a bug in the JDK related to HTTP/2 connections, which are the default (see IGN-5334 on our side for more details). We added the version
argument on system.net.httpClient
so you could specify version=HTTP_1_1
, which solved the lingering CLOSE_WAIT
connections on Windows.