사내 대시보드에 실시간 알림 붙이려고 socket.io 서버(노드)를 nginx 리버스프록시 뒤에 뒀는데요. 브라우저 개발자도구 네트워크 보면 처음 몇 초는 polling으로 붙었다가 websocket으로 업그레이드하는 순간 502가 뜹니다. 폴링으로는 그럭저럭 동작은 하는데 계속 롱폴링이라 찝찝해서요.
nginx conf는 대충 이렇게 잡았습니다.
location /socket.io/ {
proxy_pass http://127.0.0.1:3001;
proxy_set_header Host $host;
}노드쪽 로그엔 에러가 안 남고 nginx error.log에만 이런 줄이 찍혀요.
*128 upstream prematurely closed connection while reading response header from upstream, ... "GET /socket.io/?EIO=4&transport=websocket HTTP/1.1"구글링해서 proxy_read_timeout도 올려봤는데 그대로네요. 뭘 빠뜨린 걸까요?
댓글 4
location 안에 이 세 줄 넣어보세요.
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
기본 프록시가 HTTP/1.0으로 붙어서 Upgrade가 안 먹는 경우가 대부분이라 proxy_http_version 1.1이 핵심이에요. 그리고 Connection 헤더를 upgrade로 넘겨줘야 노드가 핸드셰이크를 완성합니다. 이거 넣으면 폴링에서 websocket으로 넘어갈 때 502 안 뜰 거예요.
http 블록(server 바깥)에 이렇게 두고,
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
location 안에선 proxy_set_header Connection $connection_upgrade; 로 쓰면 업그레이드 요청일 때만 upgrade, 아니면 close로 나갑니다. socket.io 한 곳만 쓰면 하드코딩도 실무상 괜찮지만 프록시 여러 개면 map이 관리하기 훨씬 편해요.