본문 바로가기
Http

HTTP keep-alive on/off 에 따라 다른 결과가 나오는 이슈

by ybs 2022. 5. 29.
반응형

문제 발생

HTTP request 받는 서버를 변경하면서 에러가 발생했다.

정상적인 경우라면 response body 에 key 값만 있어야 하는데, key 값(123456) 뒤에 에러메세지가 append 되고 있었다. 에러메세지는 HTTP response 에 해당하는 모든 정보였다.

123456HTTP%2F1.1+408+Request+Time-out%0D%0AContent-length%3A+110%0D%0A
Cache-Control%3A+no-cache%0D%0AConnection%3A+close%0D%0AContent-Type%3A+text%2F
html%0D%0A%0D%0A%3Chtml%3E%3Cbody%3E%3Ch1%3E408+Request+Time-out%3C%2Fh1%3E%0D%0A
Your+browser+didn%27t+send+a+complete+request+in+time.%0D%0A%3C%2Fbody%3E%3C%2Fhtml%3E%0D%0A

 

 

원인

결론부터 말하면, request를 보내는 client 가 HTTP request spec 에 맞지 않게 보내고 있었다. HTTP request spec은  아래와 같다. header 와 body 를 구분하기 위해 CRLF 가 사용되지만, body 가 끝난후에는 CRLF 를 추가하지 않는다.

Request-Line
*(( general-header | request-header | entity-header ) CRLF)
CRLF
[ message-body ]

 

하지만 에러가 발생하는 request 에서는 body 마지막에 CRLF 두개를 추가해서 전달하고 있었다.

0d0a 가 \r\n 이고 CRLF다.

 

어떻게 기존 서버에서는 문제없다가 새로운 서버에서만 에러가 발생했을까?

keep-alive 설정 차이 때문이었다. keep-alive 는 HTTP/1.1 기본스펙이다. 그래서 새로운 서버에서는 추가 설정없이 그대로 사용하고 있어서 커넥션이 계속 맺어져 있는 상태였다. body 마지막에 CRLF 가 있어서 서버는 body 데이터가 아직 안끝났다고 판단하고 reqeust 가 또 들어오는것으로 인지했다. 그래서 첫번째 response 는 정상적으로 전달했고 두번째 request 를 기다리다가 timeout이 발생했다. 즉 client에서는 첫번째 response 를 받고 두번째 response 를 계속 기다리다 에러가 발생한 것이다.

 

기존 nginx 서버에서는 keep-alive 사용을 안하고 있어서 문제가 발생 하지 않았다. 디폴트 옵션인 keep-alive 를 왜 꺼놨는지 따로 기록해놓은게 없었기 때문에 미리 파악하기는 불가능했다.  

 

해결방법

client 가 HTTP request spec 에 안맞는 요청을 보냈기 때문에 client 에서 수정 하는게 맞지만 그럴 수 없었다. API 연동 가이드 문서를 보니까 body 에 해당하는 $queryString 뒤에 CRLF 를 두개 추가하고 있었기 때문이었다.

...
fwrite($nc_sock, "Content-type: application/x-www-form-urlencoded; charset=utf-8\r\n");
fwrite($nc_sock, "Content-length: ".strlen($queryString)."\r\n");
fwrite($nc_sock, "\r\n");
fwrite($nc_sock, $queryString."\r\n");
fwrite($nc_sock, "\r\n");

 

잘못된 가이드로 이미 많은 client 들이 저렇게 request 를 보내고 있었고 지금까지 에러없이 동작했던 API 였기 때문에 서버쪽에서 keep-alive 설정을 끌 수밖에 없었다. 대신 성능상의 이슈가 있으니 문제가 되는 특정 path 만 keep-alive 를 끄기로 했다.

반응형