HttpClient 및 Close_Wait

10752 단어
서버 A는 HttpClient를 통해 다른 시스템 B가 제공하는 서비스를 연결해야 하며, 일정 시간 실행한 후에 다음과 같은 이상을 던져야 한다:java.net.SocketException: Connection reset by peer: socket write error close_wait
서버 B에서 netstat 명령을 실행하면 대량의 연결이 CLOSE_WAIT 상태.
문제 분석:
간단히 말해서 CLOSE_WAIT 수가 너무 많은 것은 수동적인 연결 해제 처리가 부적절하기 때문이다.
내가 말한 장면은 서버 A가 서버 B 위의apache에게 파일 자원을 요청하는 것이다. 정상적인 상황에서 요청이 성공하면 자원을 캡처한 후에 서버 A가 연결을 닫으라는 요청을 한다. 이때 연결을 닫는 것이다. 연결 상태는 우리가 볼 수 있는 TIME_WAIT.만약에 이상이 생기면요?만약 요청한 자원 서버 B에 존재하지 않는다고 가정하면 이때 서버 B가 연결을 닫는 요청을 한다. 서버 A는 연결을 수동적으로 닫은 것이다. 만약에 서버 A가 연결을 수동적으로 닫은 후에 자신이 연결을 풀지 않았다면 CLOSE_WAIT 상태입니다.
그래서 문제는 여전히 절차 안에 있다는 것이 분명하다.
원본 코드 블록:

 
 
  
  
  
  
  1. try 
  2. client = HttpConnectionManager.getHttpClient(); 
  3. HttpGet get = new HttpGet(); 
  4. get.setURI(new URI(urlPath)); 
  5. HttpResponse response = client.execute(get); 
  6. if (response.getStatusLine ().getStatusCode () != 200) { 
  7. return null; 
  8. HttpEntity entity =response.getEntity(); 
  9.  
  10. if( entity != null ){ 
  11. in = entity.getContent(); 
  12. ..... 
  13. return sb.toString (); 
  14.  
  15. catch (Exception e) 
  16. e.printStackTrace (); 
  17. return null; 
  18. finally 
  19. if (isr != null){ 
  20. try 
  21. isr.close (); 
  22. catch (IOException e) 
  23. e.printStackTrace (); 
  24. if (in != null){ 
  25. try 
  26. <span style="color:#ff0000;">in.close ();</span> 
  27. catch (IOException e) 
  28. e.printStackTrace (); 

HttpClient는 우리가 자주 사용하는 InputStream을 사용합니다.close () 는 연결이 닫혔는지 확인하고 위의 코드를 분석합니다. 200이 아닌 연결이 나타나면 이 연결은 연결 탱크 안에서 영원히 경직됩니다. inputStream이 초기화되지 않아서 close () 방법을 사용하지 않습니다.
코드를 약간 수정하여 이상 상황을 더욱 엄밀하게 처리하면 문제를 해결할 수 있다.

 
 
  
  
  
  
  1. public static String readNet (String urlPath) 
  2. StringBuffer sb = new StringBuffer (); 
  3. HttpClient client = null
  4. InputStream in = null
  5. InputStreamReader isr = null
  6. HttpGet get = new HttpGet(); 
  7. try 
  8. client = HttpConnectionManager.getHttpClient(); 
  9. get.setURI(new URI(urlPath)); 
  10. HttpResponse response = client.execute(get); 
  11. if (response.getStatusLine ().getStatusCode () != 200) { 
  12. get.abort(); 
  13. return null; 
  14. HttpEntity entity =response.getEntity(); 
  15.  
  16. if( entity != null ){ 
  17. in = entity.getContent(); 
  18. ...... 
  19. return sb.toString (); 
  20.  
  21. catch (Exception e) 
  22. get.abort(); 
  23. e.printStackTrace (); 
  24. return null; 
  25. finally 
  26. if (isr != null){ 
  27. try 
  28. isr.close (); 
  29. catch (IOException e) 
  30. e.printStackTrace (); 
  31. if (in != null){ 
  32. try 
  33. in.close (); 
  34. catch (IOException e) 
  35. e.printStackTrace (); 

HttpGet을 호출하는 abort를 표시합니다. 그러면 이번 연결이 바로 중단됩니다. 이상이 발생했을 때 호출을 표시해야 합니다. 왜냐하면 이상이 InputStream in에서 값을 부여한 후에 던진 것이라고 누가 보증할 수 있기 때문입니다.
more:
우선 서버 프로그램이 CLOSE_에 있는 경우WAIT 상태라면 소켓이 수동적으로 닫힌다는 뜻입니다!
클라이언트 측이 현재 연결을 자발적으로 끊으면 쌍방이 이 TCP 연결을 닫는 데 총 4개의 패킷이 필요하기 때문이다.
Client –-> FIN  –-> Server
Client <–- ACK  <–- Server
 Client FIN_WAIT_2 ; Server  CLOSE_WAIT 。
Client <–- FIN  <–- Server
 Server  FIN Client,Server  LAST_ACK 。
Client –-> ACK  –-> Server
Client ACK, Server  CLOSED 。

Server 프로그램이 CLOSE_LAST_ 대신 WAIT 상태ACK 상태는 아직 클라이언트에게 FIN을 보내지 않았다는 것을 설명한다. 그러면 연결을 닫기 전에 많은 데이터를 보내거나 다른 일을 해야 하기 때문에 이 FIN 패키지를 보내지 않았을 수도 있다.
일반적으로 하나의 CLOSE_WAIT는 최소 2시간의 시간을 유지합니다. (이 시간은 외부 네트워크 서버가 일반적으로 조정합니다. 그렇지 않으면 너무 위험합니다.)만약 깡패가 특별히 프로그램을 썼다면, 너에게 CLOSE_WAIT, 소모
당신의 자원은 방출되는 순간을 기다리지 못하면 시스템이 붕괴를 해결합니다.
TCP/IP 매개 변수를 수정하여 이 시간을 단축할 수 있습니다: tcp_ 수정keepalive_*시리즈 파라미터는 이 문제를 해결하는 데 도움이 된다.
하지만 사실은 우리 프로그램 코드에 문제가 있어서,
more:
최근에 httpclient 전송 서비스를 했는데 서버에 항상 close_가 많더라고요.wait 상태의 연결, 그리고 이 연결이 닫히지 않아서 서버가 새로운 네트워크 연결을 만들 수 없어서 응답을 멈출 수 없습니다.
나중에 인터넷에서 검색해 보니 해결 방법도 간단합니다. 연결을 다시 사용하려면 연결 관리자를 사용해서 연결 관리자에서 연결을 얻고 정해진 시간에 연결 관리자로 빈 연결을 방출합니다.httpclient는 SimpleHttpConnectionManager를 자체적으로 가지고 있습니다.
Java 코드

 
 
  
  
  
  
  1. closeIdleConnections(long idleTimeout)  

이런 방법.
링크를 다시 사용할 필요가 없다면 httpmethod에서 만들 때 http 헤더 정보를 설정하면 됩니다
Java 코드

 
 
  
  
  
  
  1. httpmethod.setRequestHeader("Connection", "close");   

이렇게 하면 짜증나는 close_기다려.

좋은 웹페이지 즐겨찾기