2017-05-18 1 views
0

같은 컴퓨터 (이 경우 CentOS)에서 실행 중이지만 다른 Tomcat 서버에 배포 된 일부 응용 프로그램과 연결하는 HttPURLConnection 프로그램이 있습니다. 즉, 두 tomcats가 동일한 시스템에서 실행중인 다른 tomcats에 배포 된 두 응용 프로그램간에 HttpConnection이 만들어집니다.CentOS에서 실행될 때 HttpUrlConnection이

모든 것이 잘 작동하며 하나의 요청을 할 때 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 및 샘플러를 사용할 때 "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()를 주석 처리하면 작업이 빨라집니다. 당신의 도움을 주셔서 감사합니다. 너는 내 하루를 구했다. BTW가 있지만 프로덕션 환경에서 정상적으로 작동하는 이유는 무엇입니까? – KayV

+0

@KayV 프로덕션 환경에 대해 -XX : + DisableExplicitGC 플래그가 설정되어있을 수 있습니다. 그래도 VisualVM을 더 잘 사용하는 법을 배워야합니다. 그것은'System.gc()'가 책임 있다는 것을 직접적으로 보여 줬을 것입니다. (그것이 작동하는 방식을 알기에 충분히 오랫동안 사용 해왔다.) 또한, 당신은'System.gc()'를 호출해서는 안되며, 그 코드는 그렇지 않다. 'HttpURLConnection'을 직접 사용하는 것보다 더 나은 라이브러리를 사용할 수 있습니다. – Kayaman

+0

@Kayaman 스크린 샷을 확인하십시오. VisualVM 샘플러는 System.gc()에 대해 아무것도 보여주지 않습니다. 코드는 이전에 작성된 레거시 코드입니다. – KayV

관련 문제