はじめに
Javaで開発したアプリケーションをLinuxサーバ上で運用していると、「ネットワークが遅い」「接続数が増えるとレスポンスが落ちる」といった問題に直面することがあります。
これらの多くは、OS側のTCP設定やJava側のソケット制御の最適化不足によって発生します。
この記事では、Java × Linux環境でのネットワーク最適化に焦点を当て、接続管理・TCP設定・スレッドチューニング・I/Oモデル選択といった観点から、パフォーマンス向上の実践的なアプローチを解説します。
1. 接続管理の基本:ソケットの扱い方を理解する
1-1. ソケットオプションの見直し
JavaのSocketやServerSocketクラスでは、setReuseAddress()やsetTcpNoDelay()などの設定が可能です。
用途に応じてこれらを最適化することで、接続再利用や遅延の削減が期待できます。
ServerSocket server = new ServerSocket();
server.setReuseAddress(true); // TIME_WAIT回避に有効
server.bind(new InetSocketAddress(8080));
また、クライアント側でsetTcpNoDelay(true)を設定することで、Nagleアルゴリズムによる送信遅延を防げます。
Socket socket = new Socket();
socket.setTcpNoDelay(true);
1-2. 接続プーリングの活用
高頻度でHTTP通信やDBアクセスを行う場合、接続プーリングが有効です。
例えば、HTTP通信ではApache HttpClientやOkHttpのコネクションプールを活用します。
ConnectionPool pool = new ConnectionPool(10, 5, TimeUnit.MINUTES);
OkHttpClient client = new OkHttpClient.Builder()
.connectionPool(pool)
.build();
これにより、TCPハンドシェイクのコストを大幅に削減できます。
2. Linux カーネル側の最適化
2-1. 同時接続数の上限設定
大量の接続を扱う場合は、以下のパラメータを見直します。
# ファイルディスクリプタ上限
ulimit -n 65535
# 同時接続待ちキュー
sudo sysctl -w net.core.somaxconn=1024
# TCPバッファの拡張
sudo sysctl -w net.ipv4.tcp_rmem="4096 87380 6291456"
sudo sysctl -w net.ipv4.tcp_wmem="4096 65536 6291456"
これにより、同時接続性能とデータ転送効率が向上します。
2-2. TIME_WAIT の処理を最適化
短時間で大量の接続を捌く場合、TIME_WAITソケットが増えることがあります。
以下の設定で再利用・短縮を検討します。
sudo sysctl -w net.ipv4.tcp_tw_reuse=1
sudo sysctl -w net.ipv4.tcp_fin_timeout=30
ただし、セキュリティ要件(SSL/TLS利用など)によっては慎重な設定が必要です。
3. スレッドとI/Oモデルの最適化
3-1. ブロッキング vs ノンブロッキング I/O
Javaでは、java.netパッケージ(ブロッキングI/O)とjava.nio(ノンブロッキングI/O)を選択できます。
- 小規模でシンプルなサーバ → ブロッキングI/O
- 高並列・リアルタイム性重視 → NIO / Netty
NettyなどのNIOフレームワークを使うと、スレッド数を効率的に制御できます。
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup(4);
3-2. スレッドプールのサイズ調整
スレッド数が多すぎるとコンテキストスイッチが増加し、逆に性能が低下します。
CPUコア数に応じて、次のように設定するのが一般的です。
int threads = Runtime.getRuntime().availableProcessors() * 2;
ExecutorService executor = Executors.newFixedThreadPool(threads);
4. SSL/TLS 通信の最適化
SSL/TLS通信では、暗号化処理のオーバーヘッドが発生します。
Java 11以降では、TLS 1.3 と OpenSSL連携(OpenJSSEやConscrypt)を活用することで速度向上が可能です。
# TLS 1.3 を有効化 (JVMオプション)
-Djdk.tls.client.protocols=TLSv1.3
また、セッション再利用(Session Resumption)を有効にするとハンドシェイク負荷が減ります。
5. パフォーマンス計測とチューニング手順
5-1. ネットワークプロファイリング
Linuxでは、ss や iftop, nload などで接続状況を監視できます。
ss -s # TCP状態の統計
iftop -i eth0 # インターフェース別帯域監視
Javaアプリ側では、JVisualVMやMicrometerを使ってスレッド使用率・GC時間などを観測しましょう。
5-2. 継続的なベンチマーク
Apache JMeterやwrkを使って定期的にロードテストを行うことで、最適化の効果を定量的に把握できます。
まとめ
| チューニング対象 | 目的 | 主な設定・ツール |
|---|---|---|
| ソケット設定 | 接続再利用・遅延削減 | setReuseAddress, setTcpNoDelay |
| Linux TCPパラメータ | 同時接続性能向上 | somaxconn, tcp_rmem, tcp_tw_reuse |
| スレッド制御 | CPU効率最大化 | ExecutorService, NIO, Netty |
| SSL/TLS最適化 | 暗号化処理の高速化 | TLS1.3, OpenJSSE |
| モニタリング | 問題検出・可視化 | ss, iftop, JVisualVM |

