-
비동기 api 요청이 동기적으로 작동할 때 (ASP.NET SessionState 접근 문제)개발/이슈 처리 2024. 3. 13. 18:53
세 줄 요약:
1. 브라우저 자바스크립트에서 비동기 api 요청을 했는데 동기적으로 응답이 도착했다.
2. 왜 그런가 봤더니 ASP.NET 서버는 기본적으로 세션 동시 접근을 막기 위해 SessionID가 동일한 요청들에 lock을 걸어 직렬화(serialized)하고 있었던 것.
3. 동일한 세션에서 발생하는 동시다발적 요청의 비동기 처리가 필요하다면 해당 컨트롤러에 `[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]`를 걸어주자.
저희 DB에는 사이트 이용자의 여정을 기록한 로그 테이블이 있습니다.
그 로그를 가져와서 보여주는 기능을 구현하고 있었는데요.
많은 데이터를 가져오다 보니 api 호출의 응답이 1~2초 정도 걸리는 상황이었습니다.
(물론 아직 개발 단계라 쿼리 최적화를 하지 않아서 더 느린 것이기도 했습니다)
이 호출을 기다리느라 사용자가 다른 일을 하지 못하면 안 되겠죠.
그래서 해당 부분을 비동기로 따로 요청했습니다.
아래 그림에서 `유입 Referrer` 부분이 해당 부분인데요, 데이터를 가져오는 동안에는 우선 스켈레톤을 보여주고, 다 가져왔을 때 데이터가 렌더링됩니다.
빨리 가져올 수 있는 다른 데이터는 빠르게 로드되기 때문에, 페이지를 빨리빨리 넘기며 신청자 정보를 볼 수 있겠죠.
그래야만 했는데, 막상 실행했을 때는 기대한 결과가 아니었습니다.
제가 기대했던 실행 순서는
페이지 1 클릭 ->
페이지 1 신청자 정보 먼저 로드 ->
(페이지 1 유입 Referrer가 로드되기 이전에) 페이지 2 클릭 ->
페이지 2 신청자 정보 먼저 로드 ->
페이지 2 유입 Referrer 로드
였습니다.
유입 Referrer는 비동기 요청이기 때문에 페이지 이동에 영향이 없어야 정상입니다.
그런데 실제 실행 결과는
페이지 1 클릭 ->
페이지 1 신청자 정보 먼저 로드 ->
(페이지 1 유입 Referrer가 로드되기 이전에) 페이지 2 클릭 ->
페이지 1 유입 Referrer 로드 -> // 이 단계가 완료될때까지 페이지 2 신청자 정보가 로드되지 않음
페이지 2 신청자 정보 먼저 로드 ->
페이지 2 유입 Referrer 로드
였습니다...
처음에는 자바스크립트 비동기 처리를 잘못 했나? 싶어서 프론트 쪽을 봤지만,
네트워크 기록을 봤을 때 요청은 비동기로 잘 갔습니다.
서버에서 기다리는 시간이 문제였습니다.
원래는 두번째 `JsonGetUserData`도 요청되는 즉시 68ms 정도의 처리 시간에 응답이 돌아와야 정상입니다.
(첫 응답시간이 68ms 였으므로)
아무튼 서버가 응답을 동기적으로 주고 있다는 건데... 왜 그런가 한참 찾다가 문제를 발견했습니다.
ASP.NET은 같은 세션에 동시에 접근하는 것을 막기 위해서, 같은 SessionID에서 발생하는 요청에 lock을 걸어놓는다는 것이었습니다!
그러니 요청이 순차적으로 처리될 수 밖에요.
시간이 오래 걸리는 작업을 하는 컨트롤러를 따로 만들어 주고, SessionStateBehavior를 읽기 전용으로 설정해 주었습니다.
[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)] public class ApiController : Controller { }
세션을 수정할 필요가 없는 컨트롤러는 이렇게 읽기 전용으로 설정해 두어도 무방하겠습니다.
# See Also
- https://stackoverflow.com/questions/69477329/asp-net-session-locking
- https://stackoverflow.com/questions/4318965/asp-net-session-request-queuing
'개발 > 이슈 처리' 카테고리의 다른 글
Safari Invalid Date 문제 (new Date()에 공백 파싱 이슈) (1) 2024.01.02