주니어 개발자 1호

sticky session에 대한 주관적 생각 본문

Server 관련

sticky session에 대한 주관적 생각

No_1 2023. 6. 25. 13:35

기본적으로 alb를 통해 서버로 요청을 보내면 부하 분산을 이루면서 여러 서버 중 여유있는 서버로 트래픽을 보내게 되어요. 하지만 동일한 서버가 아니기에 동일한 session이 아닐거에요. 이를 해결하기 위해 많은 기법이 있겠지만 sticky session이 있다는 것을 알게되었어요. 하지만, 이 방식은 ALB에 부담을 준다고 하길래 왜? 부담을 주는지 궁금해서 찾아보게 되었어요. 하지만 동작 원리를 찾아내는 것 까지는 못했어요. 그렇지만 그 과정과 내용을 공유해보고자해요.

 

세션 관리 이슈는 Scale Up ( 수직적 확장 )을 통해 단일 Instance로만 운영이 될 때는 문제가 없을거에요.

서버가 한대이다 보니 LB를 통해 찾아가는 컴퓨터가 하나라서 1:1 관계이거든요.

 

 

언제?

보통 Scalu Out ( 수평적 확장 ) 을 할 때, 이런 이슈를 접하실거에요. 서버의 사양 증설이 아닌, 서버 운영 Instance 개수를 유동적으로 조정함으로써 2대 이상의 서버를 운영할 때 동일한 Session을 보장하기 위한 고민을 해요.

사진과 각각의 Ec2 Instance에는 각각의 Session이 있어요. clinet가 요청을 할 때 1번, 2번서버 어디로 갈지 모르게 되어요. 로그인 정보를 만약 session에 저장을 했다면, 이는 보장되지 않을거에요. 이를 해결하기 위해 크게 두가지 방법이 있어요. 우선 저는 실무에서는 데이터의 일관성 보장 하기 위해 redis로 공통의 세션을 대체해서 사용했어요.

sticky session

첫번쨰는 sticky session하는 방법이에요, ALB를 통해 cookike, header등으로 구분해서 client를 한 곳의 server로 보내는 역할을 하게 할 수 있어요. 장점으로는 다른 리소스(Redis)등을 사용하지 않고 구성할 수 있을거에요.

redis

두번째는 Backplane에 Redis등으로 묶음 처리하는 방법이에요. 서버의 session 대신 cache memory를 사용해서 일종의 세션역할을 하게 만들어주어요. 사진을 보면 이해가 될 것 같아요. 장점으로는 ALB에서 트래픽을 좀 더 유연하게 제어할 수 있어요.

 

L4 , L7 LB

기본적으로 L4 LB에서는 IP를 기반으로 가능할거에요. 왜냐하면 OSI 4계층의 정보로만 분산이 되는 LB라서, 가지고 있는 정보가 IP이하의 정보뿐이거든요.

L7의 LB에서는 OSI 7계층 응용계층이에요. 이때는 request안에 담긴 내용을 온전히 다 볼 수 있어요. 그렇기에 path, headers, query, params등으로 구별이 가능해져서 이걸 기반으로 부하분산을 이룰 수 있어요.

그리고 aws의 기준으로 sticky session에 대한 내용이에요.

🔗LINK: https://docs.aws.amazon.com/ko_kr/elasticloadbalancing/latest/classic/elb-sticky-sessions.html#enable-sticky-sessions-application

With CORS (cross-origin resource sharing) requests, some browsers require SameSite=None; Secure to enable stickiness. In this case, Elastic Load Balancing creates a second stickiness cookie, AWSELBCORS, which includes the same information as the original stickiness cookie plus this SameSite attribute. Clients receive both cookies.

If an instance fails or becomes unhealthy, the load balancer stops routing requests to that instance, and chooses a new healthy instance based on the existing load balancing algorithm. The request is routed to the new instance as if there is no cookie and the session is no longer sticky.

If a client switches to a listener with a different backend port, stickiness is lost.

Elastic Load Balancing creates a cookie, named AWSELB, that is used to map the session to the instance.

Requirements

  • An HTTP/HTTPS load balancer.
  • At least one healthy instance in each Availability Zone.

Compatibility

  • The RFC for the path property of a cookie allows underscores. However, Elastic Load Balancing URI encodes underscore characters as %5F because some browsers, such as Internet Explorer 7, expect underscores to be URI encoded as %5F. Because of the potential to impact browsers that are currently working, Elastic Load Balancing continues to URI encode underscore characters. For example, if the cookie has the property path=/my_path, Elastic Load Balancing changes this property in the forwarded request to path=/my%5Fpath.
  • You can't set the secure flag or HttpOnly flag on your duration-based session stickiness cookies. However, these cookies contain no sensitive data. Note that if you set the secure flag or HttpOnly flag on an application-controlled session stickiness cookie, it is also set on the AWSELB cookie.
  • If you have a trailing semicolon in the Set-Cookie field of an application cookie, the load balancer ignores the cookie.

 

Sticky Session에 대한 주관적인 생각

ALB는 7계층 LB로 Cookie, Header, Param, Query등을 기준으로 트래픽제어가 가능함을 알게 되었어요. 이를 토대로 유저의 IP, 심어둔 Cookie를 기준으로 부하 분산을 이룰 수 있는데. 이렇게 된다면 트래픽의 제어권이 유저에게 넘어간다는 생각이 들어요. 해당 유저가 App의 기능을 많이 사용하는 유저인지, 단순히 접속만 하고 끊은 유저인지 모르는 시점에서 서버를 고정시켜버리니 부하분산을 이루는 주체가 개발자에게 있기보다는 유저에게 있다는 느낌을 받았어요. 이를 제어할 수 있는 Sticky Session 설계가 아니라면 조심스러울 것 같아요.

 

소규모 트래픽으로는 음, 도전적으로 테스트용도로 사용해볼만하겠다라는 생각도 들었는데. 대규모에서 핸들링 하기에는 버겁다는 생각도 많이 들어요. 패킷 들어오는 것만 해도 엄청난데 거기서의 짧은 연산도 병목지점이라는 점에서는 더더욱 서비스의 크기가 커질 수 록 조심스러울 것 같아요.

 

그럼 언제 사용해보는게 좋을까? 라는 시점에서도 고민을 해 봤어요. 사실 잘 안떠올라요. Redis를 사용못한다면 MongoDB, NoSQL등으로 대체하여 사용할 수 있을거라는 생각이 들어요.

메인 기능이 아닐때. 여러개의 Container, Instance등이 존재할 때. Session의 효율성을 지켜야할 때.

언제가 있을까요, 잘 모르겠어요. Redis를 사용하지 못한다고 해도 Main기능이 아니라면 NoSQL등으로 대체한다면..? 그리고 Mian Production 기능이라면 더더욱 LB에 대한 부담을 덜어내야 할 것 같다는 생각도 들어요.

 

추가적으로 저의 궁금증요소에 도움을 주신 분들이 있었어요. 짧은 글로만으로도 많은 고민을 하게 해주는.. 가이드 같은 느낌.. 감사해요 🥹