I was reviewing an ASP.NET Web Form application which has some scalability issues. Means, the application was becoming slow when the traffic on the site increases. When I check the application logs, I have found a huge amount of ThreadAbortException. The application was heavily using Response.Redirect(yes with endResponse= true), which was the root cause of scalability issue. Passing endResponse = false in Response.Redirect will solve this issue. But doing so causes the application behaves very strangely because the application was assuming that Response.Redirect will stop the current page execution. In addition, there are some security risks you need to handle because your application was assuming that the page events will never execute after redirect. In this article, I will tell you an easy way to tackle these problems and gain good performance.
ASP.NET Web Form application 에 대해 확장성 부분에 대해서 약간의 issue 가 있다고 합니다. 이런 issue 를 "ThreadAbortException" 라는 에러가 발생되고 나서 확인이 가능했다고 하는데요. 해당 개발자 분이 Response.Redirect 라는 함수를 사용하다보니 이런 이슈가 발생되었다고 합니다.
Response.Redirect 에 대해 msdn 을 찾아보면 ..
http://msdn.microsoft.com/ko-kr/library/a8wa7sdt(v=vs.110).aspx
페이지 처리기에서 이 메서드를 사용하여 한 페이지에 대한 요청을 종료하고 다른 페이지에 대해 새 요청을 시작할 때 endResponse를 false로 설정한 다음 CompleteRequest 메서드를 호출합니다. endResponse 매개 변수에 true를 지정한 경우, 이 메서드는 원래 요청에 End 메서드를 호출하여 원래 요청이 완료될 때 ThreadAbortException 예외를 throw합니다. 이 예외는 웹 응용 프로그램 성능에는 나쁜 영향을 미치며 이는 endResponse 매개 변수에 대해 false를 전달하는 것이 권장되는 이유입니다. 자세한 내용은 End 메서드를 참조하십시오.
아마 이 부분으로 인해 "ThreadAbortException" 라는 오류 덩어리가 잔뜩 쌓여서 시스템을 느리게 만든 장본인이 되고 말았죠.
따라서 이 부분에 대해 대응을 어떻게 해야 할지를 기술한 블로그 내용입니다.
아래 예제를 살펴보죠. 간단하게 페이지 호출이 발생시, condition 에 대해 false 가 되면 SomePage.aspx 페이지로 이동하는 코드를 기술한 내역입니다. 보기엔 문제 없어보이지만, thread-pool thread 을 중지로 인해 응용 프로그램의 확장성에 대해 영향을 주게 됩니다. 이럴때는 Response.Redirect("SomePage.aspx", false); 로 교체하면 문제 없습니다.
01 | protected void Page_Load(object sender, EventArgs e) |
03 | var condition = ......; |
06 | Response.Redirect("SomePage.aspx"); |
09 | protected void btnSave_Click(object sender, EventArgs e) |
이 스레드 중단(thread aborting) 으로 문제를 해결할 수 있지만, 현재 페이지의 수명주기를 멈추지는 못합니다.(will not stop the current page life cycle). 다시 이슈가 발생되었네요.~ 이를 보완하는 방법에 대해 알아보죠.
RedirectUser 라는 static 메소드를 하나 만들었습니다. 해당 코드를 보시면, 첫번째로 응용프로그램 확장 (application scalability)에 좋은 방법 및 추천 드리는 부분 입니다. 두번째는 여러 번 호출하는 경우에 이전 Response.Redirect를 (있는 경우)덮어 쓸 것입니다. 세번째는 바이 패스(by-pass) HTTP 파이프 라인(HTTP pipeline) (페이지 수명주기 파이프 라인은 아님)에 있는 모든 이벤트와 필터링에 ASP.NET 런타임을 일으키는 HttpApplication.CompleteRequest를 호출 할 것입니다.
대신 버튼 이벤트 (btnSave_Click) 에서 "Response.IsRequestBeingRedirected" 로 확인해야 할 필요가 있습니다.
그리고 Response.IsRequestBeingRedirected 속성을 이용하여 체크한 다음 모든 컨트롤을 넣는것을 추천드립니다.
(I also prefer that you should put all your controls inside Response.IsRequestBeingRedirected check,)
01 | public static class HttpResponseExtensions |
03 | public static void RedirectUser(this HttpResponse response, string url) |
05 | if (response.IsRequestBeingRedirected) |
07 | response.Redirect(url, false); |
08 | var context = HttpContext.Current;
|
11 | context.ApplicationInstance.CompleteRequest(); |
15 | public partial class WebForm : System.Web.UI.Page |
17 | protected void Page_Load(object sender, EventArgs e) |
19 | var condition = .....; |
22 | Response.RedirectUser("Unauthorized.aspx"); |
25 | protected void btnSave_Click(object sender, EventArgs e) |
27 | if (Response.IsRequestBeingRedirected) |
1 | <form id="form1" runat="server"> |
2 | <% if(!Response.IsRequestBeingRedirected){ %> |
3 | <asp:Button ID="btnSave" runat="server" Text="Save" xxOnClick="btnSave_Click" /> |
4 | <%--All the Other Controls--%> |
5 | <%--All the Other Controls--%> |
6 | <%--All the Other Controls--%> |
만약에 GridView, RadGrid 와 같은 복잡한 컴포넌트를 사용하게 될 경우, 특히 "selecting, inserting, updating and deleting events" 같은 기능을 사용할 경우엔 아래와 같이 "Response.IsRequestBeingRedirected" 가 true 인지 체크해야 합니다.
예제는 아래와 같습니다.
1 | protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e) |
3 | if (Response.IsRequestBeingRedirected) |
In this article, I showed you how to use Response.Redirect optimizely. I also showed some risks of using the optimized Response.Redirect and a technique to mitigate the risks. Hopefully you will enjoy my this article too.
해당 기고자는 Response.Redirect 에 대한 효율적으로 사용하는 방법을 보여주었으며, 위험을 완화하는데 있으며, 이를 최적화하는 방법에 대해 기술한 내용입니다.
감사합니다.
번역자 : 심재운 shimpark@gmail.com
첫댓글 예전에 그냥 평범하게 사용했었는데... 이런 이슈가 있었네요. 잘배우고 갑니다.
감사합니당 ㅎ