We have developed a MicroService which is accessed by a secondary system. Both systems use a Swagger/OpenApi API to communicate with one-another. We generate the client as "java" (underlying okhttp-Client).
When we are load-testing the system after some time we get java.lang.OutOfMemoryError: unable to create new native thread
on the client, although the system has plenty of memory configured (via -Xmx).
How can we avoid this? What is wrong?
OpenApi generates the "java"-Client such that each instance of ApiClient
wraps one instance of OkHttpClient
. The documentation of OkHttpClient
states, that each instance creates a ThreadPool
as well as a cache. It also states, that OkHttpClient
-Instances should be shared among multiple requests.
If you do not do this and generate one ApiClient
per call, you will sort of leak Thread
s. These are recovered, once a garbage-collection eliminates the unused ApiClient
instances, however, if your system is configured with plenty of memory, this gc-call might not occur frequently enough and you might end up with more requested native threads, than the underlying os can deliver.
The solution is to re-use ApiClient
-instances within your application or switch to a client based e.g. on Spring RestTemplate
.
For those curious: OkHttpClient
seems to reserve the threads to deal with async http/2 requests - which is kind of overkill, if your application does not actually do async calls.