ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 비동기 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

     

    ASP.NET Session Locking

    I've just discovered that ASP.NET MVC controllers 'lock' the session when each call to the controller is made. So, if your call takes 1 minute to complete, then all calls get queued up until that 1

    stackoverflow.com

    - https://stackoverflow.com/questions/4318965/asp-net-session-request-queuing

     

    ASP.net session request queuing

    It seems to me that ASP.net queues up all requests that use the same Session ID. Let's say you've got 3 pages. Default.aspx protected void Page_Load(object sender, EventArgs e) { Session["asd...

    stackoverflow.com

     

    댓글

Copyright 2022. ProdYou All rights reserved.