2017-05-18 6 views
0

同じマシン(この場合はCentOS)で動作している他のTomcatサーバーに展開されているアプリケーションとHttpURLConnectionプログラムを接続しています。つまり、両方のTomcatが同じマシン上で実行されている異なるTomcatにデプロイされた2つのアプリケーション間でHttpConnectionが作成されます。HttpUrlConnectionがCentOS上で動作しているときに100%CPUを使用しています

すべてがうまく動作し、1回のリクエストで200ミリリス以内の応答が得られます。 しかし、JMeter経由で無限ループのために100個のリクエストを並列に実行してアプリケーションをロードすると、CPUの処理が高まります。

public String sendHttpGetReq(String urlParameters,String msisdn, InNodeConfig inNodeConfig, InNodeDetails inNodeDetails) 
{ 
    Logger.sysLog(LogValues.info, this.getClass().getName(),"["+msisdn+"] Inside sendHttpGetReq"); 
    String response = ""; 
    //response = "{\"id\":\"584371732\",\"status_billing\":\"INSUFFICIENT_FUNDS\",\"status_sms\":\"NO_SMS\"}"; 
    String url = ""; 
    URL obj = null; 
    HttpURLConnection con = null; 
    try 
    { 
     url = "http://"+inNodeConfig.getServerIp()+":"+inNodeConfig.getServerPort()+inNodeConfig.getServiceUri(); 
     url = url+urlParameters; 
     Logger.sysLog(LogValues.info, this.getClass().getName(),"["+msisdn+"] url = "+url); 
     obj = new URL(url); 
     con = (HttpURLConnection) obj.openConnection();  

     con.setDoOutput(true); 
     con.setRequestMethod("GET"); 
     con.setConnectTimeout(Integer.parseInt(inNodeConfig.getConTimeOut())); 
     con.setReadTimeout(Integer.parseInt(inNodeConfig.getConTimeOut())+1000); 

     int responseCode = con.getResponseCode(); 
     Logger.sysLog(LogValues.info, this.getClass().getName(),"["+msisdn+"] HTTP Response Code : " + responseCode); 
     Logger.sysLog(LogValues.info, this.getClass().getName(),"["+msisdn+"] HTTP Response message : " + con.getResponseMessage()); 

     if(responseCode == 202 || responseCode == 200) 
     { 
      BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); 
      String inputLine; 
      StringBuffer responseBf = new StringBuffer(); 

      while ((inputLine = in.readLine()) != null) { 
       responseBf.append(inputLine); 
      } 
      in.close(); 

      Logger.sysLog(LogValues.info, this.getClass().getName(),"["+msisdn+"] Response received = "+responseBf.toString()); 

      response = responseBf.toString(); 
      responseBf = null; 
      if(inNodeDetails.getOperator().equalsIgnoreCase("digicel")) 
      { 
       if(response.startsWith("Received")) 
       { 
        response = "ok"; 
       } 
       else if(response.startsWith("{")) 
       { 
        // {"id":"185688","status_billing":"INSUFFICIENT_FUNDS","status_sms":"FAILED"} 
        Logger.sysLog(LogValues.APP_DEBUG, this.getClass().getName(),"["+msisdn+"] Parsing json response."); 
        Gson gson = new Gson(); 
        JsonResponse jsonResponse = gson.fromJson(response, JsonResponse.class); 

        if(jsonResponse.getStatus_billing().equalsIgnoreCase("ok") || jsonResponse.getStatus_billing().contains("SUCCESS")){ 
         response="ok"; 
        } 
        else if(jsonResponse.getStatus_billing().equalsIgnoreCase("INSUFFICIENT_FUNDS")) 
        { 
         Logger.sysLog(LogValues.APP_DEBUG, this.getClass().getName(),"["+msisdn+"] Response received for INSUFFICIENT_FUNDS."); 
         response = "low balance"; 
        } 
        else if(jsonResponse.getStatus_billing().equalsIgnoreCase("FAILED")) 
        { 
         Logger.sysLog(LogValues.APP_DEBUG, this.getClass().getName(),"["+msisdn+"] Failure Response received for some other reason."); 
         response = "nok"; 
        }   
        else 
        { 
         if(inNodeDetails.getCountry().equalsIgnoreCase("JAM")||inNodeDetails.getCountry().equalsIgnoreCase("HAI")){ 
          response=jsonResponse.getStatus_billing(); 
         } 
         else{ 
          gson = null; 
          jsonResponse = null; 
         } 

        } 
       } 
       else 
       { 
        if(inNodeDetails.getCountry().equalsIgnoreCase("HAI") && response.contains("EXCEPTION")) 
        { 
         response = "ok"; 
        } 
        else 
        { 
        Logger.sysLog(LogValues.APP_DEBUG, this.getClass().getName(),"["+msisdn+"] Unknown response."); 
        response = "nok"; 
        } 
       } 
      } 
     } 
     else if(responseCode == 502 || responseCode == 500) 
     { 
      if(inNodeDetails.getCountry().equalsIgnoreCase("HAI") || inNodeDetails.getCountry().equalsIgnoreCase("JAM")) 
      { 
       response = "ok"; 
      } 
      else 
      { 
       response = "nok"; 
      } 

     } 
     else 
     { 
      response = "nok"; 
      /*Map<String,List<String>> responseMap = con.getHeaderFields(); 
      for (Map.Entry entry : responseMap.entrySet()) { 
       Logger.sysLog(LogValues.APP_DEBUG, Utility.class.getName(), "header key = "+entry.getKey() + " value = " + entry.getValue()); 
      }*/ 
     } 

     return response; 
    } 
    catch(SocketTimeoutException ex) 
    { 
     Logger.sysLog(LogValues.APP_DEBUG, Utility.class.getName(), "Read Timeout occurs for msisdn = "+msisdn); 
     return "ReadTimeout"; 
    } 
    catch(ConnectTimeoutException ex1) 
    { 
     Logger.sysLog(LogValues.APP_DEBUG, Utility.class.getName(), "ConnectTimeoutException occurs for msisdn = "+msisdn); 
     return "ConnectionTimeout"; 
    } 
    catch(ConnectException ex2) 
    { 
     Logger.sysLog(LogValues.APP_DEBUG, Utility.class.getName(), "ConnectException occurs for msisdn = "+msisdn); 
     return "ConnectionTimeout"; 
    } 
    catch(JsonSyntaxException ex3){ 
     response=null; 
     return response; 
    } 
    catch(MalformedJsonException ex4){ 
     response=null; 
     return response; 
    } 
    catch(Exception e) 
    { 
     Logger.sysLog(LogValues.error, this.getClass().getName(),"["+msisdn+"] Internal Error occured"+coreException.GetStack(e)); 
     return response; 
    } 
    finally 
    { 
     response = null; 
     url = null; 
     obj = null; 
     con.disconnect(); 
     Logger.sysLog(LogValues.APP_DEBUG, this.getClass().getName(),"Calling GC."); 
     System.gc(); 
    } 
    //return response; 

} 

しかし、同じコードは、毎秒約50のリクエストで、本番環境では非常に細かい実行されている:

は、ここに私のコードです。

私がJVisualVMとSamplerを使用したとき、私はこのメソッド "sendHttpGetReq"が非常に長い時間と高いCPU処理を行っていることを知る必要がありました。しかし、コードからわかるように、コードがすべてのCPUをブロックする特定の理由は見つけられませんでした。ここで

は、サンプラーのスクリーンショットです: enter image description here

問題何ができるかを提案してください?

+2

プロファイラーで確認してください。 – Kayaman

+1

このコードをデバッグすることはできませんし、CPUの高性能化の原因となっている部分を教えてください。移動してコードをプロファイリングし、ボトルネックがどこにあるかをプロファイラーに伝える必要があります。 – nos

+0

@ Kayaman私はすでにjVisualVMとSamplerを使いました。この特定のコードが大きなCPU時間を費やしていることを知りました。質問も更新されました。 – KayV

答えて

1

最終的に呼び出されているSystem.gc()メソッドが問題の原因になると思います。 System.gc()にコメントして試してみることをお勧めします。

+0

あなたは正しいです。 System.gc()をコメントアウトすると、処理が速くなります。ご協力いただきありがとうございます。あなたは私の一日を救った。ところで、なぜ運用環境で正常に動作していますか? – KayV

+0

@ KayV本番環境では、 '-XX:+ DisableExplicitGC'フラグが1に設定されている可能性があります。本当に、あなたはVisualVMをより良く使うことを学ぶべきです。それは 'System.gc()'が責任を負うことをあなたに直接示しているでしょう(そうではないと主張していない、私はそれがどのように動作するかを知るのに十分長い間それを使ってきた)。また、 'System.gc()'を呼び出すべきではありません。 'HttpURLConnection'を直接使うよりも良いライブラリを使うことができます。 – Kayaman

+0

@Kayamanスクリーンショットをご覧ください。 VisualVMサンプラーは、System.gc()について何も表示していません。コードはこれまでに書かれたレガシーコードです。 – KayV

関連する問題