본문 바로가기
DevOps/AWS

AWS elasticBeanstalk 성능 향상기(2) - 성능 향상을 하는 방법

by mandarinko 2022. 12. 30.

 

이전글에서 성능 향상을 하게 된 이유에 대해서 이야기해보았습니다.

이번에는 직접적으로 성능 향상을 하는 방법에 대해 이야기해보려 합니다.

 

에러는 왜?

수정을 하기 위해서는 왜 문제가 발생했는지를 알아야합니다. 이전 내용을 잠시 다시 떠올려보겠습니다.

  • 내부 로컬 포트간의 통신도 TCP통신을 해야한다.
  • TCP통신을 통해 데이터를 전송하고 연결을 끊는 작업중 TIME_WAIT에 걸려서 소켓을 원할하게 사용할 수 없다.
  • TCP통신을 위해 한번 연결 후 해당 연결을 다시 사용하지 않아서 문제가 발생한다.

위의 문제를 해결하는 방법은 이제 얼추 추론이 가능합니다. TCP연결을 재사용한다!!

한번 연결을 맺어놓고 다시 사용하면 TIME_WAIT이 많이 걸리지 않을것입니다.

 

TIME_WAIT 해결하기

TIME_WAIT을 해결하는 방법을 2가지 정도 찾아보았습니다.

  1. 가용 로컬 포트 늘려주기
  2. TCP연결 재사용

AWS의 ElasticBeanstalk에서는 .ebextension폴더를 이용해서 환경이 배포되거나 재시작 하는경우에 실행할 command를 지정할 수 있습니다.

 

00-system-tuning.config파일에

commands:
  01:
    command: "echo \"10240 65535\" > /proc/sys/net/ipv4/ip_local_port_range"
  02:
    command: "sysctl -w \"net.ipv4.tcp_timestamps=1\""
  03:
    command: "sysctl -w \"net.ipv4.tcp_tw_reuse=1\""

위와 같이 설정을 해줍니다.

  1. 포트를 10240 ~ 65535을 사용하겠다. -> 가용 로컬 포트 늘려주기
  2. net.ipv4.tcp_timestamps 옵션은 이전에는 부하를 막기 위해 0으로 두고 사용하였지만 net.ipv4.tcp_tw_reuse 옵션을 사용하기 위해서는 활성화 해주어야 하고 net.ipv4.tcp_timestamps = 1 로 설정해준다.
  3. 로컬 포트에서 TCP연결을 재사용 하기 위해서 net.ipv4.tcp_tw_reuse = 1 로 설정해준다.

다만 위의 설정을 했다고 해서 TIME_WAIT이 다수 발생하지 않는것은 아닙니다.

단지 TIME_WAIT의 상태에 있는 소켓중 사용할 수 있는 소켓을 사용하는 것입니다. TIME_WAIT이 발생하지는 않는다는 것을 알아야 합니다.

 

근본적으로 TIME_WAIT 줄이기

keepalive 설정

지금까지 이야기 한 keepalive가 중요한 부분입니다.

Nginx와 app server는 TPC 통신을 한다고 이전 글에서 이야기 하였습니다. TPC 통신은 연결을 시작하기 위해서 TCP handshake를 해야 합니다.

TIME_WAIT 상태에 있는 소캣중 사용할 수 있는 소캣을 사용할 수 있게 설정을 했다고 하더라도 매연결마다 TCP handshake를 해야하기 때문에 응답 지연이 발생할 수 있습니다. 물론 TCP handshake가 응답 지연을 무조건 발생시킨다고는 할 수 없습니다. 다만 하지 않아도 되는 TCP handshake를 계속 한다면 성능의 낭비가 생길것이며, 대용량 요청이 들어오는 경우에 불필요한 TCP handshake가 응답지연을 발생시킬 수 있습니다.

 

그러면 불필요한 TCP handshake를 하지 않는 방법에 대해 알아보도록 하겠습니다.

TCP handshake를 줄이기 위해서는 Nginx에서 keepalive설정을 해주어야 합니다. keepalive설정은 지정된 수만큼의 연결을 하고 이후에 지정된 시간만큼(마지막 사용으로 부터 시간 측정) 새로 연결하지 않고 한번 연결한 소캣을 이용하는 방법입니다.

 

설정하는 방법은 아래와 같습니다.

etc/nginx/nginx.conf 파일에 아래와 같이 설정해야 합니다.

upstream was { // upstream 지정
        server 127.0.0.1:8080;
        keepalive 1024; //연결 갯수
    }

    server {
        listen        80 default_server;
        access_log    /var/log/nginx/access.log main;

        location / {
            proxy_pass          http://was; // upstream 사용
            proxy_http_version  1.1;

            proxy_set_header    Connection          $connection_upgrade;
            proxy_set_header    Upgrade             $http_upgrade;
            proxy_set_header    Host                $host;
            proxy_set_header    X-Real-IP           $remote_addr;
            proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
        }

 

 

Nginx keepalive와 node keepalive 그리고 간헐적 에러

Nginx는 downstream, upstream의 역할을 모두 할 수 있습니다. 다만 현재 Nginx와 app server간의 연결을 보고 있기에 Nginx는 downsteram이라고 생각하고 app server을 upstream이라고 보면 되겠습니다.

 

또한 Nginx는 downstream의 경우에 kaapalive를 적용하고 시간을 설정해주지 않으면 자동으로 유지 시간이 60초로 설정이 됩니다.

다만 upstream인 app server는 node(express)기반의 서버의 경우 기본적으로 5초의 kaapalive를 갖고 있습니다. (공식문서)

nodejs server.keepAliveTimeout

nginx의 keepalive는 TPC keepalive와는 조금 다르게 동작합니다. nginx의 keepalive은 상대방이 살아있는지 확인하지 않고 상대방으로부터 FIN을 받으면 연결을 종료한다고 간략하게 정리하겠습니다. 자세한 글은 여기에 잘 정리되어 있습니다.

 

잘 생각해보면 Nginx의 keepalive은 60초 nodejs의 keepalive는 5초인데, 여기서 간헐적으로 발생할 수 있는 에러에 대해서 이야기 해보려 합니다. Nginx upstream default keepalive

 

Nginx의 keepalive 시간보다 이전이면서 nodejs의 keepalive시간에 도달하기 직전 시간을 4.999..초 라고 생각을 해보겠습니다.

4.999초에 Nginx는 seq를 보내고 ack응답을 기다리게 됩니다. 이 시점에 5초가 되어서 nodejs측에서 TCP연결 종료를 위해 FIN을 보냈다고 생각을 해보면 ack를 기다리고 있는 Nginx에서는 FIN을 응답받게 되고, Nginx에서 HTTP 502에러를 반환하게 됩니다.

 

따라서 downstream의 keepalive의 시간보다 upstream의 keepalive시간을 길게 가져가는것이 좋겠습니다.

여기서는 nodejs의 keepalive를 Nginx의 기본 keepalive인 60초 보다는 길게 설정하는것이 좋습니다.

 

추가로 Nginx가 upstream인 경우 즉, 로드밸런서와의 연결에서 keepalive 기본 값은 75초 입니다.

Nginx downstream default keepalive

TCP 데이터 전송 packet

 

그럼 이렇게 AWS ElasticBeanstalk 성능 향상기를 마치도록 하겠습니다. 틀린 부분이 있다면 댓글로 남겨주시면 감사하겠습니다 :) 

 

참고 사이트

https://tech.kakao.com/2016/04/21/closewait-timewait/

https://jojoldu.tistory.com/319 

https://jojoldu.tistory.com/322

https://brunch.co.kr/@alden/11

https://iximiuz.com/en/posts/reverse-proxy-http-keep-alive-and-502s/

https://brunch.co.kr/@alden/9