developer tip

BeginProcessRequest ()에서 어떤 일이 발생합니까?

copycodes 2020. 12. 12. 11:27
반응형

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:

  1. 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.
  2. 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

반응형