1. ホーム
  2. grails

[解決済み】エラー java.net.SocketException の解決方法。開いているファイルが多すぎます

2022-02-14 06:43:08

質問

私はJMeterを使ってREST APIの負荷テストを行っています。

1000人の同時使用ユーザーにヒットすると、次のようなエラーが発生します。

Too many open files. Stacktrace follows:
java.net.SocketException: Too many open files
    at java.net.Socket.createImpl(Socket.java:397)
    at java.net.Socket.getImpl(Socket.java:460)
    at java.net.Socket.setSoTimeout(Socket.java:1017)
    at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:126)
    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
    at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
    at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:640)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
    at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:476)
    at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:441)
    at groovyx.net.http.HTTPBuilder.request(HTTPBuilder.java:390)

私のサーバーは、別のREST APIを叩いてデータを取得し、それを処理して、最終的にJSONレスポンスを返そうとします。

Linuxでオープンファイルの数を増やすにはどうしたらいいですか?

以下は、私が別のサーバーに対して行っている呼び出しです。

Map getResponse(Map data, String url){
    HTTPBuilder httpBuilder = new HTTPBuilder(url);
    httpBuilder.request(Method.POST, JSON) {
        headers.'Authorization' = AppConfig.config.appKey;
        headers.'Content-type' = 'application/json'
        body = data
        response.success = { resp, reader ->
            return reader as Map;
        }
        response.failure = { response, reader ->
            return null
        }
    }
}

解決方法は?

ファイルやソケットの最大数を開いていることが原因です。Linuxマシンでは、ファイルやソケットの最大オープン数は、デフォルトで1024です。これを変更する必要があります。以下を参照してください。 java.net.SocketException ファイルを開きすぎています。

以下のクエリを使用して、ターミナルから許可されたオープンファイルの最大数を確認することができます。

ulimit -n 

から これ :

何が起こっているかというと、基盤となるソケットが閉じられていないのです。 そして最終的にJVMは、システムのプロセスごとの制限にぶつかります。 ファイルディスクリプタを開く。

正しい解決策は、適切なタイミングでソケットを閉じるようにすることでしょう。 サーバーが閉じた時か、そのすぐ後だと思います。 接続の終わり)。 HttpURLConnectionではそれが難しいようです。 なんか混乱しちゃいますね。

  • disconnect() は、ただ単にすぐに閉じるようです -- あるいは閉じない。 Javadocsは意図的に曖昧にしています。 特にいつそれを行うか。

  • close()は正しい選択かもしれません。 の評価セクションは Java バグ#4147525 には次のように書かれています。 出力ストリーム。これにより、基礎となる キープアライブをしていない場合は、ソケットがクローズされます。 を正しくキャッシュし、再利用します。 接続はタイムアウトして自ら閉じます。 どうせ短時間で終わるし)."。

  • でも、そうでないかもしれない。 Bug #4142971 によると: "close()を呼び出すことは メソッドに影響を与えることはありません。 HTTP接続は持続的である。

明確な答えがない場合、おそらくHttpURLConnectionオブジェクトを をリストに追加し、テスト終了時に一度に切断する。 を実行します。 それでも実行の総サイズは制限されますが、少なくとも ディスクリプターの損失が蓄積されることはありません。

本当の答えは、HttpURLConnectionをあきらめ、その代わりに Jakarta Commons の HTTP クライアントを使用します。 ある人が次のように提案しました。 別の問題に関連して(バグ #4143518 ).