2017-01-05 27 views
0

データプロバイダーに接続し、HttpClientを使用してXMLデータを無限ループで読み込みます。私たちはすでに、Javaコードで接続タイムアウトとソケットタイムアウトを設定しています。しかし、HTTPサーバー側で接続が閉じられると、アプリケーションは例外をスローせず、何もしないでハングします。この動作のために、サーバーが起動しているときにJavaコードは再接続しません。ソケット接続がサーバー側で既に閉じられているかどうかを確認する方法はありますか?httpClient:サーバー側で接続が既に閉じられているかどうかを確認する方法

さらに、https://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.htmlはSTALE接続をクローズする方法について述べていますが、私たちの問題は解決していません。

ありがとうございます!

コードスニペット:私はJavaで自動リソース管理の導入失効した接続の最大クリーニング1.7

https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

と考える

private static final HttpClientConnectionManager CONN_MGR = new BasicHttpClientConnectionManager(); 

public boolean connectToServer() { 
    disconnect(); 

    CredentialsProvider provider = new BasicCredentialsProvider(); 
    UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password); 
    provider.setCredentials(AuthScope.ANY, credentials); 

    RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(15 * 1000) 
      .setSocketTimeout(15 * 1000).build(); 

    HttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(provider) 
      .setSSLSocketFactory(sslsf) 
      .setConnectionManager(CONN_MGR) 
      .setDefaultRequestConfig(requestConfig).build(); 

    HttpGet request = new HttpGet(url); 

    try { 
     HttpResponse response = client.execute(request); 
     in = response.getEntity().getContent(); 
     reader = new BufferedReader(new InputStreamReader(in)); 
     connected = true; 

     return true; 
    } catch (Exception re) { 
     LOGGER.error("error", re); 
    } 

    return false; 
} 

public void process() { 
    String xml = null; 
    while (!shuttingDown) { 
     try { 

      /* if we know the server side closed the connection already here 
       we can simply return and scheduler will take care of anything else. */ 

      xml = reader.readLine(); 
      lastSeen = System.currentTimeMillis(); 
      if (StringUtils.isBlank(xml)) { 
       continue; 
      } 
      xml = xml.trim(); 

      // processing XML here 
     } catch (IOException | NullPointerException ie) { 
      /* We see SocketTimeoutException relatively often and 
      * sometimes NullPointerException in reader.readLine(). */ 
      if (!shuttingDown) { 
       if(!connectToServer()) { 
        break; 
       } 
      } 
     } catch (RuntimeException re) { 
      LOGGER.error("other RuntimeException", re); 
      break; 
     } 
    } 

    // the scheduler will start another processing. 
    disconnect(); 
} 

// called by the scheduler periodically 
public boolean isConnected() { 
    CONN_MGR.closeExpiredConnections(); 
    CONN_MGR.closeIdleConnections(15, TimeUnit.SECONDS); 
    long now = System.currentTimeMillis(); 
    if (now - lastSeen > 15000L) { 
     LOGGER.info("call disconnect() from isConnected()."); 
     disconnect(); 
    } 

    return connected; 
} 
+0

おそらく* IOException *を捕まえることによって? –

+0

IOExceptionまたはNullPointerExceptionがキャッチされたときのprocess()メソッドで、切断してから再接続します。 –

+0

私は単純なHTTPサーバーを作成し、コードと同じコードを使用してCONN_MGR.closeExpiredConnections()が役立つかどうかを確認しました。数分後、私のコードはまだxml = reader.readLine()に何のエラーも例外もなくハングするHTTPサーバーをシャットダウンします。 CONN_MGR.closeExpiredConnections()が呼び出されるたびに注意してください。ログファイルにメッセージを出力して、実際にメッセージを見ました。言い換えれば、CONN_MGR.closeExpiredConnections()は自分のコードで定期的に呼び出されますが、私のコードが再接続しないようにExceptionで終わることはありません。 –

答えて

0

が世話をしても、最悪の場合にされています接続を監視することによって実装プロバイダーが注意深く配慮してきた

A pache HttpClientは、HttpClientConnectionManagerおよび古い接続をクリーニングするジョブを実行する他のユーティリティクラスを使用します。

+0

ありがとう、Barath!もともと私は古い接続を閉じることは役に立たないと言いました。通常、process()は返されず、Springスケジューラによって呼び出されるので、間違いです。その理由のために、CONN_MGR。closeExpiredConnections()は定期的に呼び出されません。私はあなたにCONN_MGR.closeExpiredConnections()が役立つかどうかを知らせます。 –

+0

こんにちは@Barath!私の場合、CONN_MGR.closeExpiredConnections()は役に立ちません。詳細は私の投稿のコメントをご覧ください。 –

0

最後のキャッチブロックの後に、クリーンアップコードのfinallyブロックを追加します。

最後に{ CONN_MGR.shutdown(); }

それは

+0

あなたの答えをありがとう、アッシュ! –

+0

ようこそ。他の問題がある場合は教えてください –

0

接続マネージャ解放割り当てられたリソースをシャットダウンするドキュメントを1として我々はデータが15秒以上で来ていない別のスレッドからの接続を閉じることで、問題を回避しました。次のように具体的には、今をisConnected()メソッドは次のとおりです。もちろん

// called by the scheduler periodically 
public boolean isConnected() { 
    long now = System.currentTimeMillis(); 
    if (now - lastSeen > 15000L) { 
     disconnect(); 
    } 

    return connected; 
} 

、読取部のでしょうjava.net.SocketExceptionが:ソケットがまたはjava.lang.IllegalStateExceptionを閉じて:接続がまだときに割り当てられ、これが起こる。

この変更後、すべて正常に動作します。

関連する問題