BeginProcessRequest ()에서 어떤 일이 발생합니까?
우리는 NewRelic을 사용하여 서버 측 애플리케이션 추적을 제공합니다.
우리는 일부 응용 프로그램이 메서드에서 지속적으로 약 100ms를 소비하는 것을 확인했습니다 System.Web.Mvc.MvcHandler.BeginProcessRequest()
.
이것은 사용자 지정 컨트롤러 코드가 호출되기 전에 발생합니다 (누적 방식이 아니라 개별적으로 기록됨).이 메서드에서 왜 그렇게 많은 시간을 소비하는지는 분명하지 않습니다.
이 방법에서 MVC는 어떤 일을합니까? 이것은 단순히 요청 대기열 일 수 있습니까?
[편집 :] 의심되는대로-아래 Scalayer의 답변이 정확했습니다. 모든 세션 종속성을 제거하고 최적화했으며 애플리케이션 확장 성과 안정성이 크게 향상되었습니다.
일반적으로 .NET에서는 스레드 민첩성이라고합니다.
주제 레이블 (예 :의 애플리케이션 코드 System.Web.HttpApplication.BeginRequest()
) 아래에있는 결과에 대해 아마보고 있는 것은 스레드 민첩성 문제입니다. 대부분의 경우 여기에 표시되는 시간은 반드시 코드가 실행되는 것은 아니지만 읽기 / 쓰기 잠금에서 스레드가 다시 해제되기를 기다리는 웹 컨텍스트입니다.
Application_BeginRequest()
"일시 중지"는 ASP.NET 웹 스택에서 꽤 널리 하나입니다. 일반적으로 BeginRequest에서로드 시간이 길면 ASP.NET 스레드 민첩성 및 / 또는 스레드 잠금을 처리하는 것입니다. 특히 IO 및 세션 기반 작업을 처리 할 때 그렇습니다. 이것이 나쁜 것이 아니라 .net이 스레드가 동시에 유지되도록하는 방법입니다.
시간 차이는 일반적으로 BeginRequest와 PreRequestHandlerExecute 사이에 발생합니다. 응용 프로그램이 세션에 여러 항목을 쓰는 경우 ASP.NET은 HttpContext.Current.Session
.
이것이 직면 할 수있는 문제인지 확인하는 좋은 방법은 스레드 ID를 확인하여 민첩성이 문제인지 확인하는 것입니다. ID는 주어진 요청에 따라 다릅니다.
예를 들면. 디버깅하는 동안 다음을 추가 할 수 있습니다 Global.asax.cs
.
protected void Application_BeginRequest(Object sender, EventArgs e) {
Debug.WriteLine("BeginRequest_" + Thread.CurrentThread.ManagedThreadId.ToString());
}
디버그 출력 창을 엽니 다 (Visual Studio :보기 >> 출력, "다음에서 출력 표시"드롭 다운에서 "디버그"선택).
디버깅하는 동안 오랫동안 본 페이지를 누르십시오. 그런 다음 출력 로그를 봅니다. 여러 개의 ID가 표시되면이 문제가 발생할 수 있습니다.
이것이 때때로 지연이 표시되지만 다른 시간에는 표시되지 않는 이유입니다. 애플리케이션 코드가 세션을 약간 다르게 사용하거나 세션 또는 IO 작업이 페이지마다 더 높거나 낮을 수 있습니다.
이 경우 사이트 또는 주어진 각 페이지에서 세션이 사용되는 방식에 따라 작업 속도를 높이기 위해 수행 할 수있는 몇 가지 작업이 있습니다.
세션을 수정하지 않는 페이지의 경우 :
<% @Page EnableSessionState="ReadOnly" %>
세션 상태를 사용하지 않는 페이지의 경우 :
<% @Page EnableSessionState="False" %>
앱이 세션 (web.config)을 사용하지 않는 경우 :
<configuration>
<system.web>
<sessionState mode="Off" />
</system.web>
</configuration>
따라서 다음 예를 살펴 보겠습니다.
사용자가 페이지를로드 한 다음 첫 번째 요청이 완료되기 전에 다른 페이지로 이동하기로 결정합니다. ASP.NET을로드하면 세션 잠금이 발생하여 첫 번째 페이지 요청이 완료 될 때까지 새 페이지 요청로드가 대기하게됩니다. ASP.NET MVC에서 각 작업은 동기화를 위해 사용자 세션을 잠급니다. 같은 문제가 발생합니다.
잠금이 해제되는 데 걸린 모든 시간은 사용자가 세션을 포기하고 돌아 오는 스레드가 더 이상 존재하지 않는 사용자를 찾고있는 경우는 말할 것도없고 새로운 유물을 통해보고됩니다.
덧붙여서 UpdatePanel 컨트롤은 동일한 동작을 유발합니다.
http://msdn.microsoft.com/en-us/magazine/cc163413.aspx
수행 할 수있는 작업 :
이 잠금 문제는 Microsoft에 SessionStateUtility 클래스가있는 이유 중 하나입니다.
http://msdn.microsoft.com/en-us/library/system.web.sessionstate.sessionstateutility.aspx
이 Redis 구현에서 볼 수 있듯이이 문제에 직면하면 기본 동작을 재정의 할 수 있습니다. https://github.com/angieslist/AL-Redis
.net 기반 웹 사이트에서 사용하는 기본 상태 공급자에 대한 많은 옵션이 있습니다. 그러나 일반적으로이 트랜잭션 시간은 스레드가 잠겨 있고 서버에 대한 요청이 완료되기를 기다리고 있음을 나타냅니다.
특정 컨트롤러가 단일 사용자의 요청을 병렬로 처리 할 수 있도록하려면 버전 3부터 MVC에 도입 된 SessionState라는 속성을 사용할 수 있습니다. 병렬성을 달성하기 위해 세션없는 컨트롤러를 사용할 필요는 없습니다. SessionStateBehavior의 Ready-only 옵션을 사용하면 세션 데이터를 기반으로 구현했을 수있는 보안 검사를 통과 할 수 있습니다.
[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class ParallelController : Controller
{
...
}
나는 또한 System.Web.Mvc.MvcHandler.BeginProcessRequest()
몇 가지 장기 실행 작업을 시도 할 때 지연이 있었고에서 그것을 보았습니다 NewRelic
. 이 속성은 문제를 해결하고이 컨트롤러에 대해 병렬 작업을 처리하는 기능을 제공합니다.
I encountered this same problem in an app that had very minimal use of sessions. After taking the accepted answer into account, and even temporarily removing SessionState completely for diagnostic purposes, I still had significant issues with performance in this 'Method'
Based on todd_saylor's comment in this thread, I did a lot of research on my own site and found that BeginProcessRequest
can be serve as New Relic's catch-all for miscellaneous performance losses that appear in different code areas. I was able to significantly reduce the time in this area, by profiling code on my local machine using Red Gate's ANTs Performance Profiler.
My local profiling revealed a few things:
- I was using Ninject as my DI container, which caused performance loss in its Object resolution. I replaced it with SimpleInjector and increased performance by an order of magnitude.
- I found that somewhere between AutoMapper's IQueryable Extensions
Project().To<>()
and the Linq's Sql Server provider, that the Dynamic Compiling and JITing of projections was responsible for 50% of my request time. Replacing that with CompiledQuerys made another significant dent.
Hope this helps someone else!
to anyone reading this experiencing IIS high CPU usage that is unexplained, take a look at this thread from NewRelic support forum I opened.
I have been dealing with this issue for over a week, until I realized it was their agent that was the root cause of the problem.
.NET agent causing high CPU usage on IIS
so first thing I suggest you try is removing the .NET agent and see if there's any change, before you dive into more complex experiments.
I post this answer on this particular question since I got here first while working on the issue, and thread agility set me on a long course that was not correct...(although very interesting by itself).
참고URL : https://stackoverflow.com/questions/17064380/what-happens-in-beginprocessrequest
'developer tip' 카테고리의 다른 글
SQL 성능 UNION 대 OR (0) | 2020.12.12 |
---|---|
Maven Java Home을 변경하는 방법 (0) | 2020.12.12 |
Typescript에서 따옴표를 사용하는 표준은 무엇입니까? (0) | 2020.12.12 |
덧셈 할당 + = 식의 동작 (0) | 2020.12.12 |
C ++에서 함수를 호출 할 때 얼마나 많은 오버 헤드가 있습니까? (0) | 2020.12.12 |