[22.08.17] Daily 회고록 (아키텍처, EC2, ALB와 NLB 환경 STOMP test)
일간 회고록(TIL)

[22.08.17] Daily 회고록 (아키텍처, EC2, ALB와 NLB 환경 STOMP test)

[일일회고]

현재 프로젝트에서 websocket을 stomp를 이용한 pub/sub 관계로 구성을 하고 있는데 stomp를 ec2에 올리니 문제가 많다.

여러 케이스들에서 테스트 해봤는데 각각의 환경에서 발생하는 문제가 달라 해결하는 과정이 길어지고 있다.

각 상황에 대해서 설명하고 나중에 해결될 시 글로 남기려고 한다.

프로젝트 아키텍처 구성안(미완성)

 

[환경]

EC2(ubuntu22.04, nginx, websocket관련 헤더 업데이트 완료)

AmazonMQ(ActiveMQ)

SSL(Certificate Manager)

ALB(80 - 443 redirect, 443 - ec2), NLB(80 - ec2, 443 - ec2)

Spring Application(8080, 내부에서 ActiveMQ 브로커 호출)

 

 

1. EC2로 직접 연결

ec2의 public ip로 직접 연결을 하면 로드 밸런서를 거치지 않고 접속한다. 접속을 하기 위해 기존에는 security group을 alb의 security group으로부터만 접근이 가능하도록 설정했기에 임시로 all tcp를 허용하고 테스트해봤다. ws와 wss를 모두 테스트하기 위해서 80, 443을 모두 열었고, ws:// wss://를 해보았는데 ws://만 정상작동하였다. wss에서는 정상 작동하지 않는데 원래는 alb에서 ssl 인증을 받고 80포트로 ec2에 보내주기 때문에 ec2 내부에 nginx config에서 443포트에 대한 설정이 없어 그런 것으로 보인다.

> apic-websocket-ws:// - O

> apic-stomp-ws:// - O

> apic-websocket-wss:// - X

> apic-stomp-wss:// - X

All TCP from my ip를 security group에 추가
연결 완료
구독도 잘 된다

2.  ALB를 통해 EC2로 연결

application load balancer를 통해서 EC2로 접근하게 되는데 alb는 application 레벨로 L7에서 동작한다. 그렇기 때문에 HTTP, HTTPS 프로토콜만 지원하는데 WS와 WSS는 HTTP,HTTPS와 같은 포트를 사용하지만 다른 프로토콜이다. HTTP를 기반으로 한다는 것의 의미는 웹소켓 연결을 맺는 과정에 HTTP가 개입한다는 의미다. Handshake 과정이 성공적으로 끝나면, HTTP를 웹소켓 프로토콜로 바꾸는 protocol switching과정을 진행한다. 이 과정이 끝나면 HTTP 대신 ws와 wss프로토콜이흐르게 된다. 그렇기 때문에 HTTP/HTTPS 프로토콜에는 접근조차 하지 못한다고 생각이 들었다. 그러나, websocket의 wss에서는 연결이 된다.

????

80포트가 ws://에서 접근한 것이기 때문에 받지 못한 것이라면 443포트에서도 받지 못해야하는데, 혹은 HTTPS에서 WSS를 수용할 수 있다면 stomp도 가능해야한다고 봤는데 stomp는 정상작동하지 않는다. websocket은 기능을 테스트하려면 stomp와 달리 핸들러가 필요한데 그 기능을 spring application에서 구현해놓지 않아 테스트해보지는 못했다. 결국 원하는 기능이 동작하지 않아 L4레벨에서 동작하는 network load balancer환경에서 작동해보았다.

> apic-websocket-ws:// - X

> apic-stomp-ws:// - X

> apic-websocket-wss:// - O

> apic-stomp-wss:// - X

 

3.  NLB를 통해 EC2로 연결

network load balancer를 통해서 EC2에 접근할 때는 alb와 다른 점이 몇 개 있었다. 일단 nlb는 alb와 달리 security group이 존재하지 않는다. L4에서 동작하기 때문에 네트워크 레벨에서 동작해서 그런 것으로 보이고 또한, HTTP/HTTPS만 설정할 수 있었던 alb와 달리 TCP/UDP/TLS로 포트 접근이 가능하다. 그래서 alb는 rest api 용도로도 사용되기 때문에 남겨두고 웹소켓 기능을 사용하기 위해 nlb를 추가로 사용하기 위해 서브도메인 stomp.exquiz.me를 만들어 route53에 연결했다. 

websocket으로 전달될 정보에는 큰 보안 위험 요소가 없기 때문에 일단 80,443포트 모두 리다이렉션 없이 EC2로 연결하도록 구성하였고 테스트해봤다.

apic-websocket-ws
apic-websocket-wss
apic-stomp-ws

> apic-websocket-ws:// - O

> apic-stomp-ws:// - O

> apic-websocket-wss:// - O

> apic-stomp-wss:// - X

위와 같이 wss-stomp만 제외하고 동작한다. 왜 wss-stomp만 동작하지 않을까.. 정작 제일 중요한 정보만 동작하지 않는다. nlb에서 80,443포트로 받으면 80포트로 변환하여 타겟 그룹인 EC2로 전송하여 EC2에서 8080포트로 변환하여 activemq로 연결해주는데 이 과정을 거치면 80,443 포트 둘 다 같은 타겟그룹으로 가기 때문에 같은 결과를 보여야한다고 예상했다. 그러나 stomp-ws에서만 정상작동하고 1번 환경에서 추측한 결과와 달랐다.  websocket은 핸들러를 두지 않았기 때문에 websocket 결과를 무시한다고 치면 교집합은 wss-stomp가 동작하지 않는다 인 것 같다. 

 

4.  SockJS를 이용한 ALB/NLB를 통해 EC2로 연결(해결?)

기존에는 SockJS를 사용하지 않고 진행을 했는데 이번에는 SockJS를 사용하고 테스트를 해보았다. ws:// wss://로 시작하던 전과 달리 SockJS를 사용하면 http/https로 프로토콜이 바뀌어 동작한다.

SockJS란 순수 WebSocket에서 지원하지 않는 브라우저에서도 동작하게끔 도와주며, 서버/클라이언트 중간에 위치한 proxy가 upgrade 헤더를 해석하지 못해 서버에 전달하지 못하는 상황을 방지해주고, proxy가 유휴상태가 되어 Connection이 종료되는 상황을 방지해준다. 동작 방식으로는 WebSocket Emulation을 이용해서 우선 WebSocket으로 시도하고, 실패할 경우 Http Streaming, Long-Polling같은 HTTP 기반의 다른 기술로 전환해 다시 연결하는 것을 시도한다. 브라우저가 WebSocket을 지원하지 않는 경우에 대안으로 어플리케이션의 코드를 변경할 필요 없이 런타임에 필요할 때 대체를 한다.

 

GitHub - sockjs/sockjs-client: WebSocket emulation - Javascript client

WebSocket emulation - Javascript client. Contribute to sockjs/sockjs-client development by creating an account on GitHub.

github.com

StompConfig

> apic-websocket-http - X

> apic-websocket-https - X

> apic-stomp-http-alb - X

> apic-stomp-https-alb - O

> apic-websocket-http-nlb - O

> apic-stomp-https-nlb - O

그렇기 때문에 위의 것들과 달리 websocket은 http/https 위에서 동작하지 않으므로 apic으로 테스트가 불가능했고, stomp는 SockJS로 바꿨기 때문에 http/https에서 동작하였다. nlb는 현재 80,443을 모두 ec2로 연결했기 때문에 http/https에서 모두 동작하였지만 alb는 80포트가 443포트로 리다이렉션하기 때문에 그 과정에서 관련 헤더들이 유실되는지 alb로 연결되지 않았다. 어차피 https 위에서만 stomp가 동작하면 되기 때문에 nlb가 이제 필요없어졌지만, 웹소켓 기능과 rest api 기능의 api 도메인을 분리하기 위해서 도메인을 분리한채로 아키텍처를 유지하려고 한다. 

 

 

참고할만한 블로그

 

Configuring Websockets behind an AWS ELB – jverkamp.com

Recently at work, we were trying to get an application that uses websockets working on an AWS instance behind an ELB (load balancer) and nginx on the instance. If you’re either not using a secure connection or handling the cryptography on the instance (e

blog.jverkamp.com

 

 

WebSocket - SockJS

 

velog.io