기타/인프라 구축과정

[문제점] - HelloWorld Project

배발자 2023. 6. 5.
반응형

 

문제점 I. SSE 연결 지연 현상 HTTP1.1 - Http2.0 문제점 해결

 

 

Server-sent Events 기법은 Web Browser의 간섭없이 Server에서 Web Browser 단방향으로 Event를 전송하는 기법이다. 즉, Web Browser가 Server의 Event를 Subscribe를 통해서 Server의 Event를 전송받는 기법이다. Web Browser에서 Server로는 Event를 전송할 수 없다. 위의 그림은 Server-sent Events 기법을 나타내고 있다. Web Browser는 Server에게 특정 Event를 Subscribe하는 요청 전송한다. 이후에 Server에서는 해당 Event가 발생시 Web Browser에게 해당 Event를 전송한다.

 

하지만, 문제점이 발생했다. 

 

SSE을 활용한 Webflux 알림 서비스가 정상적으로 작동은 되지만, 매우 느린속도로 진행되었다. 즉, 알림 푸시 데이터를 추가하였을 때, 약, 10~20초의 딜레이가 발생하였다. 실제 데이터 수신은 되었기때문에, 비지니스 로직에 대한 문제점은 아니라고 판단하였고, 네트워크 관련된 문제가 아닐까 생각되었다. 

 

블로그 검색 끝에 다음과 같은 글을 접하게 되었다. 

 

Server-sents Events는 HTML5의 표준에 포함되어 있으며 HTTP Protocol 기반으로 동작한다. HTTP 1.1 Protocol로도 동작은 가능하지만 가능하면 HTTP 2.0 Procotol을 통해 이용하는 것을 권장한다. 대부분의 Web Browser는 하나의 Server를 대상으로 최대 6개의 TCP Connection을 허용하기 때문에 HTTP 1.1 Protocol을 통해서는 최대 6개의 Event만 Subscribe가 가능하기 때문이다. 반면에 HTTP 2 Protocol을 이용하면 HTTP 2 Protocol의 TCP Connection Multiplexing 기능을 통해서 하나의 TCP Connection을 통해서 다수의 Event를 Subscribe 할 수 있게된다.

 

해당 글을 보고나서 서버의 Nginx config 파일에서 다음과 같이 수정하였다. 

   listen 443 ssl http2; 

 

Nginx는 기본적으로 HTTP/1/1을 지원한다. 그렇기때문에,  Nginx 설정에서 'http2'를 포함한 'listen' 지시문을 활용하여 HTTP/2를 활성화하였다. 

 

sudo service nginx restart

 

설정 파일을 수정후 nginx 서비스에 변경사항을 적용하였고 이후, 알림 데이터를 수신할 때 Delay 없이 정상적으로 수신이 가능하였다. 

 

 

문제점 2. Nginx 문제점 (301 -> 308) 

 

{
    "timestamp": "2023-04-28T01:37:38.185+00:00",
    "path": "/",
    "status": 405,
    "error": "Method Not Allowed",
    "requestId": "957e52f6-7"
}

 

서버에 POST 메소드로 데이터를 계속 요청을 보내도 위와 같은 상태를 반환하였다. 

 

Nginx 문제가 있는지 확인하기위해  /var/log/nginx/error.log (또는 지정한 로그 파일 경로)를 확인하였다. 그런데 분명히 POST 메소드로 요청을 보냈는데 계속해서 GET 메소드로 요청되는 것을 확인하였다. 

 

계속해서 삽집을 하다가 물 한방울을 얻을 수 있는 블로그를 찾아냈다. 

해당 블로그에서는 Nginx config 설정 파일에서 301번 status code는 GET만을 인식하는 문제점이 있다고 말했다. 

 

이 글을 읽고 필자가 구축한 nginx 설정 파일을 확인해본 결과, nginx의 config 파일에 301번 status code를 통해 리다이렉션을 보내도록 하고 있었다.

 

참고한 블로그에서는 301 대신 308로 수정해야 정상적으로 작동된다고하여 다음과 같이 수정하였다. 

 

server{
    if ($host = 도메인주소) {
        return 308 https://$host$request_uri;
    } # managed by Certbot
sudo service nginx restart

 

수정 후 해당 명령어를 통해 nginx에 변경 사항을 적용하니, 문제점이 해결되었다. 

 

 

301번 Moved Permanetly는 redirect시킬 때 method를 GET으로 바꾸어서 전송한다. 반면, 308번 Permanent Redirect는 전송 받은 HTTP Method를 유지한다. 


따라서 301번을 사용한다면 HTTP 프로토콜을 통해POST로 날아왔던 요청이 HTTPS 프로토콜을 통해 GET 메소드로 변경되면서 컨트롤러나 라우터에 매핑되는 URI가 없으면 오류가 나게된다. 

 

 

문제점 3. Nginx SSE 연결 유지 문제점 Default 60 seconds

 

도메인:8085 -> notify 서버 어플리케이션 컨테이너로 직접 연결하면 sse로 연결이 되는데 nginx를 거쳤다가 가면 1분뒤에 결과가 정상적으로 출력이 되고 끊어진다. 

 

이유는 Nginx의 기본 'proxy_read_timeout' 설정값이 60초로 설정되어있기 때문이다. 

 

그렇기때문에 별다른 설정을 하지 않으면, 60초가 지나면, Nginx는 백엔드 서버와의 연결을 끊는 것이다. 이는 무응답 상태의 백엔드 서버로 인해 Nginx가 무한정 대기하는 것을 방지하기 위한 조치라고 한다. 

 

서버-센트 이벤트(Server-Sent Events, SSE) 연결이 1분 후에 끊기는 문제를 해결하기 위해서, Nginx 설정에 proxy_read_timeout 값을 조정해야한다. 기본값은 60초이므로, 이 값을 늘려서 연결이 더 오래 유지되도록 할 수 있다.

 

nginxCopy code
location /notify/ {

    proxy_pass http://notify/;
    proxy_read_timeout 1800; # 또는 원하는 시간(초 단위)으로 설정
}

 

위 예제에서 proxy_read_timeout 값을 1800초 (30분) 설정을 하여 SSE 연결이 30분동안 유지된다. 필요에 따라 이 값을 조정하여 원하는 시간 동안 연결을 유지할 수 있다. SSE를 사용하는 경우에 'proxy_read_timeout'의 값을 적절히 설정하는 것이 중요하다고 생각하며, 백엔드 서비스의 성능, 애플리케이션의 요구사항, 그리고 네트워크 지연 등을 고려하여 결정해야한다. 

 

현재 진행하는 프로젝트에서 트래픽 문제라던지 그 외 추가 이슈 상황이 발생하지 않기때문에, 초동조치를 위와 같이 적용하여 문제점을 해결 및 유지하였다. 만약, 위와 같은 해결 로직이 문제점을 낳는다면 다른 방법을 찾아봐야한다고 생각한다. 

 

반응형

댓글