누구나 한번쯤 수강신청 시간 혹은 티켓팅 시간이 되었을 때 서버의 응답이 늦어져 애타는 마음으로 흰 화면만 바라본 경험이 있을 것이다. 갑작스런 접속자의 증가를 서버가 감당해내지 못한 것이다. 이를 막기 위해 서버의 수를 늘려(scale-out) 유저의 트래픽을 여러 군데의 서버로 나눠준다.
이때, 로그인 체크 여부를 세션을 통해 확인하도록 구현하였다고 가정해 본다. 세션은 서버 1대 당 하나의 저장소가 형성되므로 서버 1에서 유저 1의 로그인 처리를 했다면 유저 1이 만드는 트래픽은 항상 서버 1에서 처리되어야만 해당 유저가 로그인 한 유저라는 사실을 알 수 있다.
서버 1에만 유저 1의 세션 정보가 존재하므로 유저 1과 관련된 트래픽을 전부 서버 1로 보내면 되는 것 아닌가? 그렇다면 유저 2와 유저 3도 로그인 트래픽이 서버 1로 향했을 경우에 대해서도 생각해 보아야 한다. 유저 2와 유저 3마저 서버 1에 세션을 생성하게 되면 서버 2, 서버 3을 늘린 의미가 없어지게 된다. 이전과 동일하게 하나의 서버에 트래픽이 집중되는 문제가 남게 되는 것이다. 그래서 등장하게 된 개념이 세션 클러스터링이다. 세션 불일치 문제를 해결하기 위해 scale-out을 통해 생성된 서버에도 동일한 세션정보를 갖도록 관리하는 개념이다.
user1이 서버 1에 로그인을 했다면 서버 1로만 트래픽이 향하도록 처리하는 방식이다. Nginx의 경우 ip hash와 쿠키를 사용하여 해당 트래픽이 어느 서버로 향해야 하는지 관리한다.
이때, 쿠키를 사용하면서 발생하는 문제점이 존재한다. user1 session의 만료 시간이 1시간 남아 있더라도 sticky session을 구현하기 위해 사용한 쿠키의 만료 시간이 지나버리면 user1의 session은 더 이상 의미가 없어지게 된다. 쿠키 만료 시간이 지나버려 user1의 트래픽이 서버 1로 향하리란 보장이 없어져 버렸기 때문이다. 즉, user1의 트래픽이 서버 1로 향하지 못하게 되어 마이페이지 접속을 위해 재로그인이 필요하게 되는 상황이 발생하는 것이다.
이러한 문제로 인하여 client 쪽에서 쿠키의 유효시간을 설정하고, 해당 쿠키의 정보를 참조해 로드 밸런싱을 하게 하는 방법도 존재한다.
tomcat은 DeltaManager를 사용한 all-to-all 세션 복제 방식을 제시하고 있다.
위의 방식과 같이 어떤 서버에 접속해 세션을 생성하더라도 해당 세션 정보를 다른 서버에도 일괄적으로 복제한다. 따라서 하나의 서버가 없어지더라도 유저는 해당 상황을 인지하지 못하고 정상적으로 서비스를 이용할 수 있다.
하지만, 세션 저장소에 데이터가 저장될 때마다 모든 서버에 세션 정보를 저장해야 하므로 서버 수에 비례하여 네트워크 트래픽이 증가하는 성능 저하가 발생할 수 있다.
tomcat에서는 all-to-all 세션 복제 방식의 문제점을 해결하고자 primary-secondary 세션 복제 방식을 제시하기도 하였는데, 이 역시 성능적인 한계가 존재한다.
서버 1(primary)과 서버 2(secondary)에 세션 객체의 key-value 전체를 복제해두고 그 외의 서버에는 세션의 key에 해당하는 값만을 복제하는 방식으로, 객체 전체를 복제했던 방식인 all-to-all 방식보다는 시간이 절약된다는 장점이 존재한다. 하지만 primary 서버와 secondary 서버를 제외한 서버에 세션 정보를 요청하게 되는 경우 위의 그림과 같이 세션 key에 해당하는 세션 객체를 얻기 위해 primary 서버에 질의하는 과정이 추가적으로 필요하게 된다. 따라서 이 방법 역시 성능적 한계는 여전히 존재한다.
그나마 세션의 정합성 문제를 해결하기 위해 가장 많이 채택되는 방법으로 session storage를 두는 것이다. Redis, Memcached 등의 세션 저장소가 사용된다.
해당 방법은 하나의 독립된 세션 저장소에서 세션 데이터를 저장하고 있으므로 해당 저장소가 다운되면 모든 서버가 세션을 공유받을 수 없게 된다. 따라서 세션 저장소를 하나 더 구성하여 복제(secondary)해둘 필요가 있다.
[참조] https://kku-jun.tistory.com/44
[참조] https://hyuntaeknote.tistory.com/6
[참조] https://velog.io/@sileeee/%EC%84%B8%EC%85%98-%EB%B6%88%EC%9D%BC%EC%B9%98-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95
[참조] https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer
[참조] https://www.imperva.com/learn/availability/sticky-session-persistence-and-cookies