system.net.httpClient() with TIME_WAIT due to pooling?

We are using system.net.httpClient() with PUT to call some Microsoft REST APIs. It gets triggered every few seconds.with system.util.invokeAsynchronous() and appears to work fine. We have logging setup and anything not returning a 200 gets logged (1-2 per week). But it seems like a lot of TCP ports are being left open in TIME_WAIT state (Windows OS).

I think I remember hearing system.net.httpClient() has connection pooling and other things going on behind the scenes so maybe it's trying to re-use some open ports instead of having to re-do the entire connection each time. The high port number connections appear to be cycling and closing but there are always about 100-200 of them open at any one time. Can anyone confirm this is the case and if so, are there any pooling configurations we can make?

Are you creating a new httpClient object for every request? If so, stop doing that. Use a project library script outer level object to hold a single one and use it everywhere.

2 Likes

Are you reusing the client object returned by system.net.httpClient() or creating a new one each time? If creating a new one each time, try reusing the object instead.

EDIT: Phil beat me to it

2 Likes

I'm sorry but I don't understand exactly what that means.
We have a Gateway Event Script tag change script that executes system.util.invokeAsynchronous() with a function from the Project Library that includes the PUT with system.net.httpClient()

Don't:

def someAsyncFunction():
	client = system.net.httpClient()
	client.doSomething()

Do:

client = system.net.httpClient()

def someAsyncFunction():
	client.doSomething()

(With all of this in the project library).

3 Likes

Is that function calling system.net.httpClient() every time. If so, don't. Put

someClient = system.net.httpClient()

in that library script outside any function def. That will make one httpClient instance and hold it in between project edits. Use someClient in the function wherever you are current calling system.net.httpClient().

Edit: Paul was faster.

2 Likes

Yep, you guys called it. We're using someClient = system.net.httpClient() inside of the def. We'll move it. Thanks for the explanation.

As a note, in 8.3, if you're solely using system.net.httpClient() (all defaults), you'll be able to substitute calls directly for an automatic instance.
That is:

8.1

client = system.net.httpClient()
client.get(someUrl)

Can become:

8.3

system.net.httpClient.get(someUrl)

So you don't need to define (potentially multiple) default system.net.httpClient instances in all your project library scripts.

2 Likes