Slide 1

Slide 1 text

障害を回避する
 HttpClient 再入門
 uskey512 / Yusuke Uehara @JJUG CCC 2025 Spring 2025-06-07

Slide 2

Slide 2 text

自己紹介
 
 Yusuke Uehara
 X,GitHub : uskey512 
 STORES 株式会社 
 バックエンド8年/フロントエンド2年
 Spring Boot, React 開発・運用・監査対応
 2

Slide 3

Slide 3 text

発表のモチベーション
 自社サービスの継続的な開発・運用を通じて
 大小さまざまな障害が発生して、都度調査や対策を行ってきた
 
 影響の大きい障害が発生した際、原因であることが多かった通信周り
 事前にこの部分を深堀りしていれば回避・軽減出来たかもしれない…
 
 実際にあった障害の例をあげて紹介して
 似たような問題の発生を防ぐきっかけにしたい
 
 3

Slide 4

Slide 4 text

本発表の主なターゲット・ゴール
 主なターゲット
 ● Javaで外部サービスを利用するシステム開発を行うエンジニア
 ● HttpClient実装に少し詳しくなりたいエンジニア
 本発表では皆さんに20分で以下の情報を提供することをゴールとします
 ● HttpClientが何をしてくれるかが改めてわかる
 ● 代表的なHttpClientについて特徴や選定基準がわかる
 ● 実際に発生した障害の例を踏まえてより安全に使うためのポイントがわかる
 4

Slide 5

Slide 5 text

目次
 ● HttpClient 再入門 
 ○ HttpClientとはなにか・何をしてくれるか 
 ○ 代表的な実装の紹介と選定基準 
 ○ 障害になるポイント・機能・原因 
 ● 障害事例1. 意図通り動作しないタイムアウト
 ○ タイムアウトの設定と難解さ 
 ○ 対策と考慮すべきポイント 
 ● 障害事例2. 使っていないはずのHttpClient
 ○ 使っていないはずのHttpClientを見つける 
 ○ 対策と考慮すべきポイント 
 5

Slide 6

Slide 6 text

HttpClientとはなにか
 HTTPリクエストを送信してHTTPレスポンスを受信するためのライブラリ
 
 
 
 6

Slide 7

Slide 7 text

HttpClientとはなにか
 HTTPリクエストを送信してHTTPレスポンスを受信するためのライブラリ
 
 =ソケット通信+HTTPプロトコル+接続管理+その他
  の面倒を肩代わりしてくれるもの
 
 
 
 
 7

Slide 8

Slide 8 text

HttpClientとはなにか
 HTTPリクエストを送信してHTTPレスポンスを受信するためのライブラリ
 
 =ソケット通信+HTTPプロトコル+接続管理+その他
  の面倒を肩代わりしてくれるもの
 
 ただ、一言で大きい括りでHttpClientとまとめてしまうと
 指す範囲が広く様々な種類があるため、一旦全体を俯瞰して整理する
 
 8

Slide 9

Slide 9 text

HttpClientではない
 HttpURLConection
 HttpClientとはなにか -HttpClient/それ以外-
 9 Socket
 (SSLSocket)
 SocketChannel
 HttpClient (大きい括り) 
 Java 11
 HttpClient
 OkHttp
 Apache
 HttpClient
 RestClient
 Retrofit
 OpenFeign
 …
 …


Slide 10

Slide 10 text

HttpClientではない
 HttpURLConection
 HttpClientとはなにか -HttpClient/それ以外-
 10 Socket
 (SSLSocket)
 SocketChannel
 HttpClient (大きい括り) 
 Java 11
 HttpClient
 OkHttp
 Apache
 HttpClient
 RestClient
 Retrofit
 OpenFeign
 …
 …
 役割
 ・HTTPの操作を抽象化 
  ・接続管理
  ・データの送受信
 ・その他実用上で便利になる 
  様々な補助機能を追加 


Slide 11

Slide 11 text

HttpURLConection
 HttpClientとはなにか -HttpClient内での分類-
 11 Socket
 (SSLSocket)
 SocketChannel
 HttpClient
 高機能HttpClient / HttpClientラッパー 
 Java 11
 HttpClient
 OkHttp
 Apache
 HttpClient
 RestClient
 Retrofit
 OpenFeign
 …
 …


Slide 12

Slide 12 text

HttpURLConection
 HttpClientとはなにか -HttpClient内での分類-
 12 Socket
 (SSLSocket)
 SocketChannel
 HttpClient
 高機能HttpClient / HttpClientラッパー 
 Java 11
 HttpClient
 OkHttp
 Apache
 HttpClient
 RestClient
 Retrofit
 OpenFeign
 …
 …
 ・宣言的クライアント 
 ・RESTクライアント
 ・フレームワーク特化 
 内部でHttpClientを利用 
 ・通信の確立と維持管理 
 ・HTTP 送受信処理 
 ・補助機能 (各実装に依存) 


Slide 13

Slide 13 text

HttpURLConection
 HttpClientとはなにか -HttpClient内での分類-
 13 Socket
 (SSLSocket)
 SocketChannel
 HttpClient
 高機能HttpClient / HttpClientラッパー 
 Java 11
 HttpClient
 OkHttp
 Apache
 HttpClient
 RestClient
 Retrofit
 OpenFeign
 …
 …
 ・宣言的クライアント 
 ・RESTクライアント
 ・フレームワーク特化 
 内部でHttpClientを利用 
 ・通信の確立と維持管理 
 ・HTTP 送受信処理 
 ・補助機能 (各実装に依存) 
 今日のテーマはココ 


Slide 14

Slide 14 text

HttpClientは何をしてくれるか
 14

Slide 15

Slide 15 text

HttpClientは何をしてくれるか
 ● HTTPリクエスト/レスポンスの送受信
 ● コネクションプールと接続の再利用
 ● タイムアウト, バックオフ, リトライの統合
 ● TLS/SSLハンドシェイク, 証明書検証
 ● 非同期, 並列実行モデルの提供
 ● HTTP/2, HTTP/3対応
 ● 自動リダイレクト・Cookie管理
 ● 認証・プロキシ・ヘッダ共通処理
 ● 圧縮(gzip/deflate)の透過処理
 ● etc.
 15

Slide 16

Slide 16 text

代表的なHttpClient実装
 16

Slide 17

Slide 17 text

代表的なHttpClient実装
 Apache HttpClient
 ● 現代でも使われているHttpClientでは最も歴史がある 
 ● pros : 圧倒的な柔軟性と豊富な機能、拡張できるポイントが多い、知見が得やすい 
 ● cons : 最新プロトコルや新技術への追従が遅い、使用方法がやや冗長で複雑 
 OkHttp
 ● Square社が開発しているクライアント Androidでの事実上標準 
 ● pros : 便利なデフォルト設定・追加機能の充実など(EventListener, Cache) 
 ● cons : 設定の自由度はApacheに劣る、実装言語がKotlinでデバッグ時が辛いかも 
 Java11 HttpClient
 ● Java11で標準搭載された HTTPクライアント 
 ● pros : 非同期通信, HTTP/2, WebSocket対応など比較的新しい機能が使える 
 ● cons : 高度な認証・自動圧縮展開(gzip等)・リトライが無く、細かな設定が行えない 
 17

Slide 18

Slide 18 text

代表的なHttpClient実装 -選定基準-
 単なるREST APIを利用するだけならあまり差は無い前提で 
 Apache HttpClient
 ● 高度な認証を利用したい、特殊な要件に対応したい、過去資産があるなどの場合 
 ● 高い耐障害性を出すこともできるが設定はチューニング前提 
 OkHttp
 ● Androidでは一択。サーバサイドでも新規開発なら利用したい 
 ● デフォルト設定が堅実で障害に強い (自動リトライ・IPフォールバック) 
 Java11 HttpClient
 ● カスタマイズ性がそこまで必要ない、外部ライブラリへの依存を避けたい 
 ● 外部ライブラリのバージョン管理や脆弱性対策が不要になる 
 18

Slide 19

Slide 19 text

HttpClient のどこで障害が発生するのか
 19

Slide 20

Slide 20 text

HttpURLConection
 HttpClient のどこで障害が発生するのか
 20 Socket
 (SSLSocket)
 SocketChannel
 HttpClient
 高機能HttpClient / HttpClientラッパー 
 Java 11
 HttpClient
 OkHttp
 Apache
 HttpClient
 RestClient
 Retrofit
 OpenFeign
 …
 …


Slide 21

Slide 21 text

HttpURLConection
 HttpClient のどこで障害が発生するのか
 21 Socket
 (SSLSocket)
 SocketChannel
 HttpClient
 高機能HttpClient / HttpClientラッパー 
 Java 11
 HttpClient
 OkHttp
 Apache
 HttpClient
 RestClient
 Retrofit
 OpenFeign
 …
 …
 この部分


Slide 22

Slide 22 text

HttpClient のどの機能で障害が発生するのか
 
 ● HTTPリクエスト/レスポンスの送受信
 ● コネクションプールと接続の再利用
 ● タイムアウト, バックオフ, リトライの統合
 ● TLS/SSLハンドシェイク, 証明書検証
 ● 非同期, 並列実行モデルの提供
 ● HTTP/2, HTTP/3対応
 ● 自動リダイレクト・Cookie管理
 ● 認証・プロキシ・ヘッダ共通処理
 ● 圧縮(gzip/deflate)の透過処理
 ● etc.
 22

Slide 23

Slide 23 text

HttpClient のどの機能で障害が発生するのか
 ● HTTPリクエスト/レスポンスの送受信
 ● コネクションプールと接続の再利用 
 ● タイムアウト, バックオフ, リトライの統合 
 ● TLS/SSLハンドシェイク, 証明書検証
 ● 非同期, 並列実行モデルの提供
 ● HTTP/2, HTTP/3対応
 ● 自動リダイレクト・Cookie管理
 ● 認証・プロキシ・ヘッダ共通処理
 ● 圧縮(gzip/deflate)の透過処理
 ● etc.
 23 この部分


Slide 24

Slide 24 text

HttpClient がきっかけで発生する障害の原因はなにか
 HttpClient単体が障害の直接の原因になることはほぼない
 外部で発生した問題に巻き込まれてしまって障害の原因になる
 
 障害の原因になりやすい理由
 ● タイムアウトやリトライなどの設定ミスは正常時はあまり問題にならない
 ○ いざという時にどのように動作して欲しいかの設定
 ● 通信関連で発生する問題には様々なパターンが存在する
 ○ 名前解決できない、500系のエラーが発生する、レスポンスが遅延する
 24

Slide 25

Slide 25 text

目次
 ● HttpClient 再入門
 ○ HttpClientとはなにか・何をしてくれるか 
 ○ 代表的な実装の紹介と選定基準 
 ○ 障害になるポイント・機能・原因 
 ● 障害事例1. 意図通り動作しないタイムアウト 
 ○ タイムアウトの設定と難解さ 
 ○ 対策と考慮すべきポイント 
 ● 障害事例2. 使っていないはずのHttpClient
 ○ 使っていないはずのHttpClientを見つける 
 ○ 対策と考慮すべきポイント 
 25

Slide 26

Slide 26 text

障害その1 - 意図通り動作しないタイムアウト - 
 外部サービスAPIのレスポンスタイムが悪化して連鎖的に障害発生
 
 HttpClientの設定で細かくタイムアウトは設定しているが
 期待したタイムアウトを超過してレスポンスを待ち続けてしまい
 コネクションプールが枯渇してしまっていた
 
 
 26

Slide 27

Slide 27 text

障害その1 - 意図通り動作しないタイムアウト - 1 
 
 
 
 前提
 ● Apache HttpClient を利用している
 ● 外部APIサーバへの接続は確立できていた
 ● ただし、レスポンス全体に時間がかかっている
 上記の設定でリクエストが打ち切られるのは何秒後になるか?
 27 RequestConfig config = RequestConfig.custom() .setConnectionRequestTimeout(2000) // 2秒 .setConnectTimeout(3000) // 3秒 .setSocketTimeout(10000) // 10秒 .build(); // 合計15秒?

Slide 28

Slide 28 text

障害その1 - 意図通り動作しないタイムアウト - 2 
 打ち切られない
 
 28

Slide 29

Slide 29 text

障害その1 - 意図通り動作しないタイムアウト - 2 
 打ち切られない
 ● connectionRequestTimeout
 ○ コネクションプールから接続を取得する際のタイムアウト 
 ○ HttpClient内での待ち時間 
 ● connectTimeout
 ○ 接続先サーバとTCPハンドシェイクが完了するまでのタイムアウト 
 ○ 接続先サーバとの通信を確立するための待ち時間 
 ● socketTimeout
 ○ Socketに流れてくるパケット間のタイムアウト 
 ○ 次のデータが送られてくるまでの待ち時間 
 29

Slide 30

Slide 30 text

障害その1 - 意図通り動作しないタイムアウト - 2 
 打ち切られない
 ● connectionRequestTimeout
 ○ コネクションプールから接続を取得する際のタイムアウト 
 ○ HttpClient内での待ち時間 
 ● connectTimeout
 ○ 接続先サーバとTCPハンドシェイクが完了するまでのタイムアウト 
 ○ 接続先サーバとの通信を確立するための待ち時間 
 ● socketTimeout
 ○ Socketに流れてくるパケット間のタイムアウト 
 ○ 次のデータが送られてくるまでの待ち時間 
 30

Slide 31

Slide 31 text

障害その1 - 意図通り動作しないタイムアウト - 3 
 ● サーバに接続"は"できる
 ● レスポンス"も"返ってくる
 ● ただし、とても遅い
 
 このような場合、先の設定例では
 タイムアウトに引っかからない
 
 
 31

Slide 32

Slide 32 text

障害その1 - 意図通り動作しないタイムアウト - 3 
 ● サーバに接続"は"できる
 ● レスポンス"も"返ってくる
 ● ただし、とても遅い
 
 このような場合、先の設定例では
 タイムアウトに引っかからない
 
 本来欲しいのはリクエスト全体での
 タイムアウト設定
 Hard Timeout とも呼ばれる
 32

Slide 33

Slide 33 text

障害その1 - 意図通り動作しないタイムアウト - 4 
 リクエスト全体を制限するタイムアウトを設定する項目
 ● Apache HttpClient : 
 ● OkHttp : 
 ● Java 11 HttpClient : 
 
 
 33

Slide 34

Slide 34 text

障害その1 - 意図通り動作しないタイムアウト - 4 
 リクエスト全体を制限するタイムアウトを設定する項目
 ● Apache HttpClient : 無し
 ● OkHttp : callTimeout
 ● Java 11 HttpClient : HttpRequest.timeout
 
 HttpClient実装毎に設定できるタイムアウトは複数種類あるが
 それぞれ設定できる箇所や名前の意図するところが異なる
 他実装での設定が一対一で対応しない
 34

Slide 35

Slide 35 text

障害その1 - 意図通り動作しないタイムアウト - まとめ 
 タイムアウトやリトライなどの設定項目について
 
 ● 各種設定値のリファレンスやソースを注意して読む
 ○ 理解が不正確なまま書かれている二次資料も多い
 ○ 賢い生成AIでも間違える
 ● 異常時の処理について検証を行って実際の挙動を確認する
 ○ CharlesなどのProxyで試したりサーバを書いて試すなど
 ○ 本来はここまで試したい
 35

Slide 36

Slide 36 text

目次
 ● HttpClient 再入門
 ○ HttpClientとはなにか・何をしてくれるか 
 ○ 代表的な実装の紹介と選定基準 
 ○ 障害になるポイント・機能・原因 
 ● 障害事例1. 意図通り動作しないタイムアウト
 ○ タイムアウトの設定と難解さ 
 ○ 対策と考慮すべきポイント 
 ● 障害事例2. 使っていないはずのHttpClient 
 ○ 使っていないはずのHttpClientを見つける 
 ○ 対策と考慮すべきポイント 
 36

Slide 37

Slide 37 text

障害その2 - 使っていないはずのHttpClient -
 外部向けに提供しているAPIサーバの
 特定のエンドポイントでレスポンスタイムが悪化
 
 メール送信機能を含むAPI呼び出しでレスポンスタイムが悪化
 他のエンドポイントにも少しずつ波及し、スレッドが枯渇したことによって
 アプリケーションサーバ全体のレスポンスタイムが悪化
 
 
 
 37

Slide 38

Slide 38 text

障害その2 - 使っていないはずのHttpClient - 1
 一部機能内で明示的にHttpClientを利用している箇所は無かったが
 外部サービスのSDKを利用しており、その外部サービスがダウンしていた
 
 外部サービスSDKは更に別のSDKに依存しており
 依存先のSDKが内包しているApache HttpClientが完全に未設定
 外部サービスSDKには初期化時にHttpClientを差し替える機能があったものの
 ドキュメント化されておらず取りこぼしてしまっていた
 38

Slide 39

Slide 39 text

39

Slide 40

Slide 40 text

障害その2 - 使っていないはずのHttpClient - 2
 コード内で直接HttpClientを使っていなければ大丈夫!
 とはならないのが要注意ポイント
 
 ● 使ってるのREST APIじゃなくてGraphQLだから関係なさそう
 ● アプリケーションコード内でHttpClient使ってないし関係なさそう
 
 
 
 
 40

Slide 41

Slide 41 text

障害その2 - 使っていないはずのHttpClient - 2
 コード内で直接HttpClientを使っていなければ大丈夫!
 とはならないのが要注意ポイント
 
 ● 使ってるのREST APIじゃなくてGraphQLだから関係なさそう
 ● アプリケーションコード内でHttpClient使ってないし関係なさそう
 とはならない
 
 外部へ通信する処理を持つ ${任意の技術} のJavaライブラリについて
 通信部分の処理は内部のHttpClientに委譲されていることがしばしばある
 41

Slide 42

Slide 42 text

HttpURLConection
 障害その2 - 使っていないはずのHttpClient - 3
 42 Socket
 (SSLSocket)
 Socke HttpClient
 高機能HttpClient / HttpClientラッパー 
 Java 11
 HttpClient
 OkHt Apache
 HttpClient
 RestClient
 Retro OpenFeign
 GraphQLClient
 外部サービス SDK
 Apollo
 Kotlin
 Netflix
 DGS
 …
 AWS 
 Stripe
 SendGrid
 Spring GraphQL
 Client
 …


Slide 43

Slide 43 text

HttpURLConection
 障害その2 - 使っていないはずのHttpClient - 3
 43 Socket
 (SSLSocket)
 Socke HttpClient
 高機能HttpClient / HttpClientラッパー 
 Java 11
 HttpClient
 OkHt Apache
 HttpClient
 RestClient
 Retro OpenFeign
 GraphQLClient
 外部サービス SDK
 Apollo
 Kotlin
 Netflix
 DGS
 …
 AWS 
 Stripe
 SendGrid
 Spring GraphQL
 Client
 …
 ・高機能HttpClient 
 ・SaaS SDK 
 ・GraphQLClient
  やってることはほぼ同じ 


Slide 44

Slide 44 text

障害その2 - 使っていないはずのHttpClient - まとめ 
 通信を伴うライブラリ・SDKを利用するにあたって
 
 ● デフォルト設定を過信しない
 ○ 引数が少ないコンストラクタを警戒する
 ○ 外からどんな項目を設定できるのか調べる
 ○ 最適な値はそれぞれ異なるので適切な値は何かを考える
 ● 内部で何が動いているのかについてイメージする
 ○ 通信部がどうなっているか
 ○ どこにリスクがあるかを考える
 44

Slide 45

Slide 45 text

漏れのある抽象化の法則 (Joel on Software)
 すべての非自明な抽象化は、ある程度漏れるものだ 
 All non-trivial abstractions, to some degree, are leaky. 
 抽象化が隠してくれるはずの下層の細部が思わぬところで表に出てきてしまう
 45

Slide 46

Slide 46 text

漏れのある抽象化の法則 (Joel on Software)
 すべての非自明な抽象化は、ある程度漏れるものだ 
 All non-trivial abstractions, to some degree, are leaky. 
 抽象化が隠してくれるはずの下層の細部が思わぬところで表に出てきてしまう
 ● HTTPリクエストを送信したいだけなのに
 TCPレイヤのSocketやSocketTimeoutについて理解をする必要がある
 ● 外部サービスのSDKを利用して機能を便利に使いたいだけなのに
 HTTPレベルではどのような制御がされているかを調べる必要がある
 
 46

Slide 47

Slide 47 text

漏れのある抽象化の法則 (Joel on Software)
 すべての非自明な抽象化は、ある程度漏れるものだ 
 All non-trivial abstractions, to some degree, are leaky. 
 抽象化が隠してくれるはずの下層の細部が思わぬところで表に出てきてしまう
 ● HTTPリクエストを送信したいだけなのに
 TCPレイヤのSocketやSocketTimeoutについて理解をする必要がある
 ● 外部サービスのSDKを利用して機能を便利に使いたいだけなのに
 HTTPレベルではどのような制御がされているかを調べる必要がある
 → 抽象化の下層を追わざるを得ない状況は必ず来る
 47

Slide 48

Slide 48 text

漏れのある抽象化の法則 (Joel on Software)
 すべての非自明な抽象化は、ある程度漏れるものだ 
 All non-trivial abstractions, to some degree, are leaky. 
 抽象化が隠してくれるはずの下層の細部が思わぬところで表に出てきてしまう
 ● HTTPリクエストを送信したいだけなのに
 TCPレイヤのSocketやSocketTimeoutについて理解をする必要がある
 ● 外部サービスのSDKを利用して機能を便利に使いたいだけなのに
 HTTPレベルではどのような制御がされているかを調べる必要がある
 → 抽象化の下層を追わざるを得ない状況は必ず来る、と腹をくくれる!
 48

Slide 49

Slide 49 text

まとめ
 これまでの発表で以下の情報を提供しました
 ● HttpClientが何をしてくれるかが改めてわかる
 ○ HttpClientの分類を行い、どのような機能があるのかを改めて確認しました 
 ● 代表的なHttpClientについて特徴や選定基準がわかる
 ○ Apache HttpClient, OkHttp, Java11 HttpClientについて特徴と比較をしました 
 ● 障害の例を踏まえて実装時に気をつけるポイントがわかる
 ○ 2つの事例を踏まえて、HttpClientの設定時に気をつける箇所 
 外部サービスのSDKを利用する際に注意するべき箇所を紹介しました 
 
 49