RestTemplateを使ったAPI接続で並列処理数が上がらずにハマった話
どんな話?
RestTemplateを使ってのAPI呼び出しで複数スレッドでの並列呼び出しを行っているのに、なぜか呼び出された側で5並列まででしか処理をされていないという事象が発生して調査してみましたという話。
色々試してみたりで新たに学んだことがあったので備忘録兼ねてまとめた内容。
状況
※以下、API接続の呼び出し元のとなるサービスを「サービスA」、APIを提供しているサービスを「サービスB」と表記します
- サービスA、BともにJava&spring-bootで作成されているアプリケーション
- サービスAでは少なくとも10スレッドでリクエストしようとしているアプリケーションのログを確認
- サービスBでは5を超えるスレッド数で処理できているAPIも存在している様子
- サービスAではRestTemplateはデフォルトの設定で利用
- javaのHttpURLConnectionのhttpclientが使われる(と思っていた)
- 後述するがこれが大きく影響していた
- サービスAではサービスBと別のサービスへのAPI接続も行っており、そちらではapacheの httpcomponentsのhttpclientを利用していた
調査してみて分かったことと原因
- サービスAのRestTemplateでは「javaのHttpURLConnection」ではなく、「apacheのhttpcomponents」が使われるようになっていた
- debugでRestTemplateの設定内容などを確認してみて判明した
- ここは推測だがdependencyとして「apacheのhttpcomponents」が定義されている場合にRestTemplateをデフォルトで利用すると、「apacheのHttpComponents」のhttpclientが利用されるようになるらしい
- 試しにapacheのhttpcomponentsをdependencyから外してAPI接続してみたところ、サービスBの処理が10スレッドで走った
- RestTemplateでapacheのhttpcomponentsをデフォルト設定で利用する際に、connection poolの設定の中でmaxPerRoute)という値があり、これが5で設定されるようになっていた
- そのため、同一接続先への接続上限数が5になっており、サービスBで最大5並列まででしか処理されていなかった
- 上記のmaxPerRouteの設定を試しに10に変更してみたら、サービスBの処理が10スレッドで走った
まとめ
- 複数スレッド走らせる場合のテストはちゃんとやらないとダメ(特に今回はローカルでも再現可能な事象だったこともありこれに尽きる)
- IDEのデバッグ機能の活用大事
- RestTemplate理解したつもりになっていたけどよく分かっていなかった・・
- ドキュメント見たり、挙動見たり今回のことを通して学びました