ASP.NET MVC 4에서의 비동기 메서드 사용Using Asynchronous Methods in ASP.NET MVC 4

Rick Andersonby Rick Anderson

이 자습서에서는 Microsoft Visual Studio의 무료 버전인 웹의 Visual Studio Express 2012를 사용 하 여 비동기 ASP.NET MVC 웹 응용 프로그램을 빌드하는 기본 사항에 대해 설명 합니다.This tutorial will teach you the basics of building an asynchronous ASP.NET MVC Web application using Visual Studio Express 2012 for Web, which is a free version of Microsoft Visual Studio. Visual Studio 2012을 사용할 수도 있습니다.You can also use Visual Studio 2012.

Github에서이 자습서에 대 한 전체 샘플을 제공 https://github.com/RickAndMSFT/Async-ASP.NET/A complete sample is provided for this tutorial on github https://github.com/RickAndMSFT/Async-ASP.NET/

.Net 4.5 를 조합 하 여 ASP.NET MVC 4 컨트롤러 클래스를 사용 하면 Task<actionresult>형식의 개체를 반환 하는 비동기 작업 메서드를 작성할 수 있습니다.The ASP.NET MVC 4 Controller class in combination .NET 4.5 enables you to write asynchronous action methods that return an object of type Task<ActionResult>. .NET Framework 4에서는 작업 이라고 하는 비동기 프로그래밍 개념을 도입 했으며 ASP.NET MVC 4는 작업을 지원 합니다.The .NET Framework 4 introduced an asynchronous programming concept referred to as a Task and ASP.NET MVC 4 supports Task. 작업은 작업 형식 및 system.object 네임 스페이스의 관련 형식으로 표시 됩니다.Tasks are represented by the Task type and related types in the System.Threading.Tasks namespace. .NET Framework 4.5는 이전 비동기 방법 보다 훨씬 더 복잡 한 작업 개체 작업을 수행 하는 waitasync 키워드를 사용 하 여이 비동기 지원을 기반으로 합니다.The .NET Framework 4.5 builds on this asynchronous support with the await and async keywords that make working with Task objects much less complex than previous asynchronous approaches. Wait 키워드는 코드 조각이 다른 코드 부분에서 비동기적으로 대기 해야 함을 나타내는 구문상의 약어입니다.The await keyword is syntactical shorthand for indicating that a piece of code should asynchronously wait on some other piece of code. Async 키워드는 메서드를 작업 기반 비동기 메서드로 표시 하는 데 사용할 수 있는 힌트를 나타냅니다.The async keyword represents a hint that you can use to mark methods as task-based asynchronous methods. Wait, asyncTask 개체의 조합을 사용 하면 .net 4.5에서 비동기 코드를 훨씬 쉽게 작성할 수 있습니다.The combination of await, async, and the Task object makes it much easier for you to write asynchronous code in .NET 4.5. 비동기 메서드에 대 한 새 모델을 작업 기반 비동기 패턴 () 이라고 합니다.The new model for asynchronous methods is called the Task-based Asynchronous Pattern (TAP). 이 자습서에서는 waitAsync 키워드 및 작업 네임 스페이스를 사용 하는 비동기 프로그래밍에 대해 잘 알고 있다고 가정 합니다.This tutorial assumes you have some familiarity with asynchronous programing using await and async keywords and the Task namespace.

WaitAsync 키워드 및 작업 네임 스페이스 사용에 대 한 자세한 내용은 다음 참조를 참조 하세요.For more information on the using await and async keywords and the Task namespace, see the following references.

스레드 풀에서 요청을 처리 하는 방법How Requests Are Processed by the Thread Pool

웹 서버에서 .NET Framework는 ASP.NET 요청을 처리 하는 데 사용 되는 스레드 풀을 유지 관리 합니다.On the web server, the .NET Framework maintains a pool of threads that are used to service ASP.NET requests. 요청이 도착하면 해당 요청을 처리하기 위해 풀에서 하나의 스레드가 디스패치됩니다.When a request arrives, a thread from the pool is dispatched to process that request. 요청이 동기적으로 처리 되는 경우 요청이 처리 되는 동안 요청을 처리 하는 스레드가 사용 중이 고 해당 스레드가 다른 요청을 처리할 수 없습니다.If the request is processed synchronously, the thread that processes the request is busy while the request is being processed, and that thread cannot service another request.

스레드 풀을 많은 사용량이 많은 스레드를 수용할 수 있을 만큼 충분히 크게 만들 수 있으므로이는 문제가 되지 않을 수 있습니다.This might not be a problem, because the thread pool can be made large enough to accommodate many busy threads. 그러나 스레드 풀의 스레드 수는 제한 됩니다 (.NET 4.5의 기본 최대값은 5000 임).However, the number of threads in the thread pool is limited (the default maximum for .NET 4.5 is 5,000). 장기 실행 요청의 동시성이 높은 대규모 응용 프로그램에서는 사용 가능한 모든 스레드가 사용 중일 수 있습니다.In large applications with high concurrency of long-running requests, all available threads might be busy. 이러한 상황을 스레드 고갈이라고 합니다.This condition is known as thread starvation. 이 조건에 도달 하면 웹 서버는 요청을 큐에 대기 시킵니다.When this condition is reached, the web server queues requests. 요청 큐가 가득 차면 웹 서버는 HTTP 503 상태 (서버 사용량이 많음)를 포함 하는 요청을 거부 합니다.If the request queue becomes full, the web server rejects requests with an HTTP 503 status (Server Too Busy). CLR 스레드 풀에는 새 스레드 주입에 대 한 제한이 있습니다.The CLR thread pool has limitations on new thread injections. 동시성이 버스 티 (즉, 웹 사이트에 갑자기 많은 수의 요청이 있을 수 있음), 대기 시간이 긴 백 엔드 호출로 인해 사용 가능한 모든 요청 스레드가 사용 중인 경우 제한 된 스레드 주입 속도로 인해 응용 프로그램의 응답 성능이 저하 될 수 있습니다.If concurrency is bursty (that is, your web site can suddenly get a large number of requests) and all available request threads are busy because of backend calls with high latency, the limited thread injection rate can make your application respond very poorly. 또한 스레드 풀에 추가 된 각 새 스레드에는 오버 헤드 (예: 1mb 스택 메모리)가 있습니다.Additionally, each new thread added to the thread pool has overhead (such as 1 MB of stack memory). 스레드 풀이 .NET 4.5 기본 최대값인 5로 증가 하는 대기 시간 호출을 처리 하는 동기 메서드를 사용 하는 웹 응용 프로그램은 응용 프로그램이 동일한 요청을 처리할 수 있는 것 보다 약 5gb의 메모리를 사용할 수 있습니다. 비동기 메서드 및 50 스레드만A web application using synchronous methods to service high latency calls where the thread pool grows to the .NET 4.5 default maximum of 5, 000 threads would consume approximately 5 GB more memory than an application able the service the same requests using asynchronous methods and only 50 threads. 비동기 작업을 수행 하는 경우 항상 스레드를 사용 하는 것은 아닙니다.When you're doing asynchronous work, you're not always using a thread. 예를 들어 비동기 웹 서비스 요청을 수행 하는 경우 ASP.NET는 비동기 메서드 호출과 대기 사이의 스레드를 사용 하지 않습니다.For example, when you make an asynchronous web service request, ASP.NET will not be using any threads between the async method call and the await. 대기 시간이 긴 서비스 요청에 스레드 풀을 사용 하면 메모리 사용 공간이 많고 서버 하드웨어 사용률이 저하 될 수 있습니다.Using the thread pool to service requests with high latency can lead to a large memory footprint and poor utilization of the server hardware.

비동기 요청 처리Processing Asynchronous Requests

시작 시 많은 수의 동시 요청을 확인 하거나 버스 티 부하가 있는 웹 앱 (동시성이 갑자기 증가할 경우)에서 웹 서비스 호출을 통해 응용 프로그램의 응답성이 향상 됩니다.In a web app that sees a large number of concurrent requests at start-up or has a bursty load (where concurrency increases suddenly), making web service calls asynchronous increases the responsiveness of the app. 하나의 비동기 요청을 처리하는 시간은 하나의 동기 요청을 처리하는 시간과 동일합니다.An asynchronous request takes the same amount of time to process as a synchronous request. 요청을 완료 하는 데 2 초가 필요한 웹 서비스 호출을 수행 하는 경우이 요청은 동기적으로 수행 되 든 비동기식으로 수행 될 때 2 초가 걸립니다.If a request makes a web service call that requires two seconds to complete, the request takes two seconds whether it's performed synchronously or asynchronously. 그러나 비동기 호출 중에는 첫 번째 요청이 완료 되기를 기다리는 동안 스레드가 다른 요청에 응답 하지 못하도록 차단 되지 않습니다.However during an asynchronous call, a thread isn't blocked from responding to other requests while it waits for the first request to complete. 따라서 비동기 요청은 장기 실행 작업을 호출 하는 동시 요청이 많은 경우 요청 큐 및 스레드 풀 증가를 방지 합니다.Therefore, asynchronous requests prevent request queuing and thread pool growth when there are many concurrent requests that invoke long-running operations.

동기 또는 비동기 작업 메서드 선택Choosing Synchronous or Asynchronous Action Methods

이 단원에서는 어떤 경우에 동기 또는 비동기 작업 메서드를 사용하는지에 대한 지침을 나열합니다.This section lists guidelines for when to use synchronous or asynchronous action methods. 단지 지침입니다. 각 응용 프로그램을 개별적으로 검사 하 여 비동기 메서드가 성능에 도움이 되는지 확인 합니다.These are just guidelines; examine each application individually to determine whether asynchronous methods help with performance.

일반적으로 다음과 같은 경우에는 동기 메서드를 사용 합니다.In general, use synchronous methods for the following conditions:

  • 작업이 단순하거나 단기 실행 작업인 경우The operations are simple or short-running.
  • 단순성이 효율성보다 더 중요한 경우Simplicity is more important than efficiency.
  • 작업이 광범위한 디스크 또는 네트워크 오버헤드를 유발하는 작업이 아닌 주로 CPU 작업인 경우.The operations are primarily CPU operations instead of operations that involve extensive disk or network overhead. CPU 관련 작업에 비동기 작업 메서드를 사용하는 경우 이점은 없고 오버헤드만 증가합니다.Using asynchronous action methods on CPU-bound operations provides no benefits and results in more overhead.

일반적으로 다음 조건에 대해 비동기 메서드를 사용 합니다.In general, use asynchronous methods for the following conditions:

  • 비동기 메서드를 통해 사용할 수 있는 서비스를 호출 하 고 있으며 .NET 4.5 이상을 사용 하 고 있습니다.You're calling services that can be consumed through asynchronous methods, and you're using .NET 4.5 or higher.
  • 작업이 CPU 관련 작업이 아닌 네트워크 또는 I/O 관련 작업인 경우The operations are network-bound or I/O-bound instead of CPU-bound.
  • 병렬 처리가 코드의 단순성보다 더 중요한 경우Parallelism is more important than simplicity of code.
  • 사용자에게 장기 실행 요청을 취소할 수 있는 메커니즘을 제공하려는 경우You want to provide a mechanism that lets users cancel a long-running request.
  • 스레드 전환의 혜택이 컨텍스트 전환 비용을 능가 하는 경우When the benefit of switching threads outweighs the cost of the context switch. 일반적으로 동기 메서드가 작업을 수행 하지 않고 ASP.NET request 스레드에서 대기 하는 경우 메서드를 비동기식으로 설정 해야 합니다.In general, you should make a method asynchronous if the synchronous method waits on the ASP.NET request thread while doing no work. 비동기 호출을 수행 하 여 ASP.NET request 스레드는 웹 서비스 요청이 완료 될 때까지 대기 하는 동안 작업을 수행 하지 않습니다.By making the call asynchronous, the ASP.NET request thread is not stalled doing no work while it waits for the web service request to complete.
  • 테스트를 통해 차단 작업은 사이트 성능의 병목 상태 이며 IIS는 이러한 차단 호출에 비동기 메서드를 사용 하 여 더 많은 요청을 수행할 수 있음을 보여 줍니다.Testing shows that the blocking operations are a bottleneck in site performance and that IIS can service more requests by using asynchronous methods for these blocking calls.

다운로드 가능한 샘플에서는 비동기 작업 메서드를 효율적으로 사용하는 방법을 보여 줍니다.The downloadable sample shows how to use asynchronous action methods effectively. 제공 된 샘플은 .NET 4.5을 사용 하 여 ASP.NET MVC 4의 비동기 프로그래밍에 대 한 간단한 데모를 제공 하도록 설계 되었습니다.The sample provided was designed to provide a simple demonstration of asynchronous programming in ASP.NET MVC 4 using .NET 4.5. 이 샘플은 ASP.NET MVC의 비동기 프로그래밍에 대 한 참조 아키텍처를 위한 것이 아닙니다.The sample is not intended to be a reference architecture for asynchronous programming in ASP.NET MVC. 샘플 프로그램은 작업을 호출 하는 ASP.NET Web API 메서드를 호출 합니다. 장기 실행 웹 서비스 호출을 시뮬레이션 하기 위해 지연 됩니다.The sample program calls ASP.NET Web API methods which in turn call Task.Delay to simulate long-running web service calls. 대부분의 프로덕션 응용 프로그램에는 비동기 작업 메서드를 사용 하는 경우 이러한 분명 한 이점이 표시 되지 않습니다.Most production applications will not show such obvious benefits to using asynchronous action methods.

모든 작업 메서드가 비동기 방식이어야 하는 응용 프로그램은 극소수입니다.Few applications require all action methods to be asynchronous. 필요한 작업량을 감안할 때, 몇 개의 동기 작업 메서드를 비동기 메서드로 변환하는 것이 효율성 증대에 최적인 경우가 많습니다.Often, converting a few synchronous action methods to asynchronous methods provides the best efficiency increase for the amount of work required.

응용 프로그램 예제The Sample Application

GitHub 사이트의 https://github.com/RickAndMSFT/Async-ASP.NET/ 에서 샘플 응용 프로그램을 다운로드할 수 있습니다.You can download the sample application from https://github.com/RickAndMSFT/Async-ASP.NET/ on the GitHub site. 리포지토리는 세 가지 프로젝트로 구성 됩니다.The repository consists of three projects:

  • Mvc4Async:이 자습서에 사용 된 코드를 포함 하는 ASP.NET MVC 4 프로젝트입니다.Mvc4Async: The ASP.NET MVC 4 project that contains the code used in this tutorial. WebAPIpgw 서비스에 대 한 Web API 호출을 수행 합니다.It makes Web API calls to the WebAPIpgw service.
  • WebAPIpgw: Products, Gizmos and Widgets 컨트롤러를 구현 하는 ASP.NET MVC 4 Web API 프로젝트입니다.WebAPIpgw: The ASP.NET MVC 4 Web API project that implements the Products, Gizmos and Widgets controllers. WebAppAsync 프로젝트 및 Mvc4Async 프로젝트에 대 한 데이터를 제공 합니다.It provides the data for the WebAppAsync project and the Mvc4Async project.
  • WebAppAsync: 다른 자습서에서 사용 되는 ASP.NET Web Forms 프로젝트입니다.WebAppAsync: The ASP.NET Web Forms project used in another tutorial.

Gizmo 그리려면 동기 작업 메서드The Gizmos Synchronous Action Method

다음 코드에서는 gizmo 그리려면 목록을 표시 하는 데 사용 되는 Gizmos 동기 작업 메서드를 보여 줍니다.The following code shows the Gizmos synchronous action method that is used to display a list of gizmos. 이 문서에서 gizmo는 가상 기계적 장치입니다.(For this article, a gizmo is a fictional mechanical device.)

public ActionResult Gizmos()
{
    ViewBag.SyncOrAsync = "Synchronous";
    var gizmoService = new GizmoService();
    return View("Gizmos", gizmoService.GetGizmos());
}

다음 코드에서는 gizmo 서비스의 GetGizmos 메서드를 보여 줍니다.The following code shows the GetGizmos method of the gizmo service.

public class GizmoService
{
    public async Task<List<Gizmo>> GetGizmosAsync(
        // Implementation removed.
       
    public List<Gizmo> GetGizmos()
    {
        var uri = Util.getServiceUri("Gizmos");
        using (WebClient webClient = new WebClient())
        {
            return JsonConvert.DeserializeObject<List<Gizmo>>(
                webClient.DownloadString(uri)
            );
        }
    }
}

GizmoService GetGizmos 메서드는 gizmo 그리려면 데이터 목록을 반환 하는 ASP.NET Web API HTTP 서비스에 URI를 전달 합니다.The GizmoService GetGizmos method passes a URI to an ASP.NET Web API HTTP service which returns a list of gizmos data. WebAPIpgw 프로젝트에는 Web API gizmos, widgetproduct 컨트롤러의 구현이 포함 되어 있습니다.The WebAPIpgw project contains the implementation of the Web API gizmos, widget and product controllers.
다음 이미지는 샘플 프로젝트의 gizmo 그리려면 뷰를 보여 줍니다.The following image shows the gizmos view from the sample project.

Gizmo 그리려면

비동기 Gizmo 그리려면 동작 메서드 만들기Creating an Asynchronous Gizmos Action Method

이 샘플에서는 새로운 asyncwait 키워드 (.Net 4.5 및 Visual Studio 2012에서 사용 가능)를 사용 하 여 컴파일러가 비동기 프로그래밍에 필요한 복잡 한 변환을 유지 관리할 수 있도록 합니다.The sample uses the new async and await keywords (available in .NET 4.5 and Visual Studio 2012) to let the compiler be responsible for maintaining the complicated transformations necessary for asynchronous programming. 컴파일러를 사용 하면 C#의 동기 제어 흐름 구문을 사용 하 여 코드를 작성할 수 있으며, 컴파일러는 스레드 차단을 방지 하기 위해 콜백을 사용 하는 데 필요한 변환을 자동으로 적용 합니다.The compiler lets you write code using the C#'s synchronous control flow constructs and the compiler automatically applies the transformations necessary to use callbacks in order to avoid blocking threads.

다음 코드는 Gizmos 동기 메서드 및 GizmosAsync 비동기 메서드를 보여 줍니다.The following code shows the Gizmos synchronous method and the GizmosAsync asynchronous method. 브라우저에서 HTML 5 <mark> 요소를 지 원하는 경우 노란색 강조 표시에서 GizmosAsync의 변경 내용이 표시 됩니다.If your browser supports the HTML 5 <mark> element, you'll see the changes in GizmosAsync in yellow highlight.

public ActionResult Gizmos()
{
    ViewBag.SyncOrAsync = "Synchronous";
    var gizmoService = new GizmoService();
    return View("Gizmos", gizmoService.GetGizmos());
}
public async Task<ActionResult> GizmosAsync()
{
    ViewBag.SyncOrAsync = "Asynchronous";
    var gizmoService = new GizmoService();
    return View("Gizmos", await gizmoService.GetGizmosAsync());
}

GizmosAsync 비동기 일 수 있도록 다음 변경 내용이 적용 되었습니다.The following changes were applied to allow the GizmosAsync to be asynchronous.

  • 메서드는 async 키워드로 표시 되어 있습니다. 그러면 컴파일러가 본문의 부분에 대 한 콜백을 생성 하 고 반환 되는 Task<ActionResult>을 자동으로 만들도록 지시 합니다.The method is marked with the async keyword, which tells the compiler to generate callbacks for parts of the body and to automatically create a Task<ActionResult> that is returned.
  • 비동기" "메서드 이름에 추가 되었습니다."Async" was appended to the method name. "Async"를 추가 하는 것은 필요 하지 않지만 비동기 메서드를 작성 하는 경우에는 규칙입니다.Appending "Async" is not required but is the convention when writing asynchronous methods.
  • 반환 형식이 ActionResult에서 Task<ActionResult>로 변경 되었습니다.The return type was changed from ActionResult to Task<ActionResult>. Task<ActionResult>의 반환 형식은 진행 중인 작업을 나타내며 비동기 작업의 완료를 기다리는 핸들을 사용 하 여 메서드의 호출자에 게 제공 합니다.The return type of Task<ActionResult> represents ongoing work and provides callers of the method with a handle through which to wait for the asynchronous operation's completion. 이 경우 호출자는 웹 서비스입니다.In this case, the caller is the web service. Task<ActionResult> ActionResult.의 결과로 진행 중인 작업을 나타냅니다.Task<ActionResult> represents ongoing work with a result of ActionResult.
  • Wait 키워드가 웹 서비스 호출에 적용 되었습니다.The await keyword was applied to the web service call.
  • 비동기 웹 서비스 API가 호출 된 경우 (GetGizmosAsync)The asynchronous web service API was called (GetGizmosAsync).

GetGizmosAsync 메서드 본문 내에서 다른 비동기 메서드인 GetGizmosAsync를 호출 합니다.Inside of the GetGizmosAsync method body another asynchronous method, GetGizmosAsync is called. GetGizmosAsync은 데이터를 사용할 수 있을 때 최종적으로 완료 되는 Task<List<Gizmo>>를 즉시 반환 합니다.GetGizmosAsync immediately returns a Task<List<Gizmo>> that will eventually complete when the data is available. Gizmo 데이터가 있을 때까지 다른 작업을 수행 하지 않으려는 경우 코드는 wait 키워드를 사용 하 여 작업을 기다립니다 합니다.Because you don't want to do anything else until you have the gizmo data, the code awaits the task (using the await keyword). Wait 키워드는 async 키워드로 주석이 지정 된 메서드에만 사용할 수 있습니다.You can use the await keyword only in methods annotated with the async keyword.

Wait 키워드는 태스크가 완료 될 때까지 스레드를 차단 하지 않습니다.The await keyword does not block the thread until the task is complete. 메서드의 나머지 부분을 작업의 콜백으로 등록 하 고를 즉시 반환 합니다.It signs up the rest of the method as a callback on the task, and immediately returns. 대기 작업이 최종적으로 완료 되 면 해당 콜백을 호출 하 고, 중단 된 위치에서 즉시 메서드 실행을 다시 시작 합니다.When the awaited task eventually completes, it will invoke that callback and thus resume the execution of the method right where it left off. WaitAsync 키워드 및 작업 네임 스페이스를 사용 하는 방법에 대 한 자세한 내용은 비동기 참조를 참조 하세요.For more information on using the await and async keywords and the Task namespace, see the async references.

다음 코드에서는 GetGizmosGetGizmosAsync 메서드를 보여 줍니다.The following code shows the GetGizmos and GetGizmosAsync methods.

public List<Gizmo> GetGizmos()
{
    var uri = Util.getServiceUri("Gizmos");
    using (WebClient webClient = new WebClient())
    {
        return JsonConvert.DeserializeObject<List<Gizmo>>(
            webClient.DownloadString(uri)
        );
    }
}
public async Task<List<Gizmo>> GetGizmosAsync()
{
    var uri = Util.getServiceUri("Gizmos");
    using (HttpClient httpClient = new HttpClient())
    {
        var response = await httpClient.GetAsync(uri);
        return (await response.Content.ReadAsAsync<List<Gizmo>>());
    }
}

비동기 변경은 위의 GizmosAsync 와 비슷합니다.The asynchronous changes are similar to those made to the GizmosAsync above.

  • 메서드 시그니처에 async 키워드로 주석이 추가 되었고, 반환 형식이 Task<List<Gizmo>>로 변경 되었으며, async 가 메서드 이름에 추가 되었습니다.The method signature was annotated with the async keyword, the return type was changed to Task<List<Gizmo>>, and Async was appended to the method name.
  • 비동기 Httpclient 클래스는 WebClient 클래스 대신 사용 됩니다.The asynchronous HttpClient class is used instead of the WebClient class.
  • Wait 키워드가 httpclient 비동기 메서드에 적용 되었습니다.The await keyword was applied to the HttpClient asynchronous methods.

다음 이미지는 비동기 gizmo 뷰를 보여 줍니다.The following image shows the asynchronous gizmo view.

async

Gizmo 그리려면 데이터의 브라우저 프레젠테이션은 동기 호출로 생성 된 뷰와 동일 합니다.The browsers presentation of the gizmos data is identical to the view created by the synchronous call. 유일한 차이점은 비동기 버전이 부하가 많은 경우 성능이 더 높을 수 있다는 것입니다.The only difference is the asynchronous version may be more performant under heavy loads.

여러 작업을 병렬로 수행Performing Multiple Operations in Parallel

비동기 작업 메서드는 작업에서 여러 독립적인 작업을 수행 해야 하는 경우 동기 메서드에 비해 상당한 이점이 있습니다.Asynchronous action methods have a significant advantage over synchronous methods when an action must perform several independent operations. 제공 된 샘플에서 PWG(Products, Widget 및 Gizmo 그리려면)에 대 한 동기 메서드는 세 개의 웹 서비스 호출 결과를 표시 하 여 products, widget 및 gizmo 그리려면의 목록을 가져옵니다.In the sample provided, the synchronous method PWG(for Products, Widgets and Gizmos) displays the results of three web service calls to get a list of products, widgets, and gizmos. 이러한 서비스를 제공 하는 ASP.NET Web API 프로젝트는 작업을 사용 합니다. 지연 시간을 시뮬레이션 하거나 네트워크 호출을 느리게 합니다.The ASP.NET Web API project that provides these services uses Task.Delay to simulate latency or slow network calls. 지연이 500 밀리초로 설정 된 경우 동기 PWG 버전이 1500 밀리초를 초과 하는 동안 비동기 PWGasync 메서드를 완료 하는 데 약간의 500 밀리초가 소요 됩니다.When the delay is set to 500 milliseconds, the asynchronous PWGasync method takes a little over 500 milliseconds to complete while the synchronous PWG version takes over 1,500 milliseconds. 동기 PWG 메서드는 다음 코드에 나와 있습니다.The synchronous PWG method is shown in the following code.

public ActionResult PWG()
{
    ViewBag.SyncType = "Synchronous";
    var widgetService = new WidgetService();
    var prodService = new ProductService();
    var gizmoService = new GizmoService();

    var pwgVM = new ProdGizWidgetVM(
        widgetService.GetWidgets(),
        prodService.GetProducts(),
        gizmoService.GetGizmos()
       );

    return View("PWG", pwgVM);
}

비동기 PWGasync 메서드는 다음 코드에 나와 있습니다.The asynchronous PWGasync method is shown in the following code.

public async Task<ActionResult> PWGasync()
{
    ViewBag.SyncType = "Asynchronous";
    var widgetService = new WidgetService();
    var prodService = new ProductService();
    var gizmoService = new GizmoService();

    var widgetTask = widgetService.GetWidgetsAsync();
    var prodTask = prodService.GetProductsAsync();
    var gizmoTask = gizmoService.GetGizmosAsync();

    await Task.WhenAll(widgetTask, prodTask, gizmoTask);

    var pwgVM = new ProdGizWidgetVM(
       widgetTask.Result,
       prodTask.Result,
       gizmoTask.Result
       );

    return View("PWG", pwgVM);
}

다음 이미지는 PWGasync 메서드에서 반환 된 뷰를 보여 줍니다.The following image shows the view returned from the PWGasync method.

pwgAsync

취소 토큰 사용Using a Cancellation Token

Task<ActionResult>를 반환 하는 비동기 작업 메서드는 취소할 수 있으며, Asynctimeout 특성과 함께 제공 되는 경우 CancellationToken 매개 변수를 사용 합니다.Asynchronous action methods returning Task<ActionResult>are cancelable, that is they take a CancellationToken parameter when one is provided with the AsyncTimeout attribute. 다음 코드에서는 시간 제한이 150 밀리초 인 GizmosCancelAsync 메서드를 보여 줍니다.The following code shows the GizmosCancelAsync method with a timeout of 150 milliseconds.

[AsyncTimeout(150)]
[HandleError(ExceptionType = typeof(TimeoutException),
                                    View = "TimeoutError")]
public async Task<ActionResult> GizmosCancelAsync(
                       CancellationToken cancellationToken )
{
    ViewBag.SyncOrAsync = "Asynchronous";
    var gizmoService = new GizmoService();
    return View("Gizmos",
        await gizmoService.GetGizmosAsync(cancellationToken));
}

다음 코드에서는 CancellationToken 매개 변수를 사용 하는 GetGizmosAsync 오버 로드를 보여 줍니다.The following code shows the GetGizmosAsync overload, which takes a CancellationToken parameter.

public async Task<List<Gizmo>> GetGizmosAsync(string uri,
    CancellationToken cancelToken = default(CancellationToken))
{
    using (HttpClient httpClient = new HttpClient())
    {
        var response = await httpClient.GetAsync(uri, cancelToken);
        return (await response.Content.ReadAsAsync<List<Gizmo>>());
    }
}

제공 된 샘플 응용 프로그램에서 취소 토큰 데모 링크를 선택 하면 GizmosCancelAsync 메서드가 호출 되 고 비동기 호출을 취소 하는 것을 보여 줍니다.In the sample application provided, selecting the Cancellation Token Demo link calls the GizmosCancelAsync method and demonstrates the cancellation of the asynchronous call.

높은 동시성/대기 시간이 긴 웹 서비스 호출을 위한 서버 구성Server Configuration for High Concurrency/High Latency Web Service Calls

비동기 웹 응용 프로그램의 이점을 실현 하려면 기본 서버 구성을 변경 해야 할 수 있습니다.To realize the benefits of an asynchronous web application, you might need to make some changes to the default server configuration. 비동기 웹 응용 프로그램을 구성 하 고 스트레스 테스트할 때 다음 사항에 유의 하세요.Keep the following in mind when configuring and stress testing your asynchronous web application.

  • Windows 7, Windows Vista 및 모든 Windows 클라이언트 운영 체제에는 최대 10 개의 동시 요청이 있습니다.Windows 7, Windows Vista and all Windows client operating systems have a maximum of 10 concurrent requests. 높은 부하 상태에서 비동기 메서드의 이점을 확인 하려면 Windows Server 운영 체제가 필요 합니다.You'll need a Windows Server operating system to see the benefits of asynchronous methods under high load.

  • 관리자 권한 명령 프롬프트에서 IIS에 .NET 4.5을 등록 합니다.Register .NET 4.5 with IIS from an elevated command prompt:
    %windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis-i%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis -i
    ASP.NET Iis 등록 도구 (Aspnet_regiis .exe)를 참조 하세요.See ASP.NET IIS Registration Tool (Aspnet_regiis.exe)

  • Http.sys 큐 제한을 기본값 1000에서 5000로 늘려야 할 수 있습니다.You might need to increase the HTTP.sys queue limit from the default value of 1,000 to 5,000. 설정이 너무 낮으면 http 503 상태를 포함 하는 http.sys 거부 요청이 표시 될 수 있습니다.If the setting is too low, you may see HTTP.sys reject requests with a HTTP 503 status. HTTP.SYS 큐 제한을 변경 하려면 다음을 수행 합니다.To change the HTTP.sys queue limit:

    • IIS 관리자를 열고 응용 프로그램 풀 창으로 이동 합니다.Open IIS manager and navigate to the Application Pools pane.
    • 대상 응용 프로그램 풀을 마우스 오른쪽 단추로 클릭 하 고 고급 설정을 선택 합니다.Right click on the target application pool and select Advanced Settings.
      고급advanced
    • 고급 설정 대화 상자에서 큐 길이 를 1000에서 5000로 변경 합니다.In the Advanced Settings dialog box, change Queue Length from 1,000 to 5,000.
      큐 길이Queue length

    위의 이미지에서 응용 프로그램 풀이 .NET 4.5을 사용 하 고 있더라도 .NET framework는 v 4.0으로 표시 됩니다.Note in the images above, the .NET framework is listed as v4.0, even though the application pool is using .NET 4.5. 이러한 불일치를 이해 하려면 다음을 참조 하십시오.To understand this discrepancy, see the following:

  • 응용 프로그램에서 웹 서비스 또는 System.NET를 사용 하 여 HTTP를 통해 백 엔드와 통신 하는 경우 Connectionmanagement/maxconnection 요소를 늘려야 할 수 있습니다.If your application is using web services or System.NET to communicate with a backend over HTTP you may need to increase the connectionManagement/maxconnection element. ASP.NET 응용 프로그램의 경우 자동 구성 기능으로 Cpu 수의 12 배까지 제한 됩니다.For ASP.NET applications, this is limited by the autoConfig feature to 12 times the number of CPUs. 즉, 쿼드 프로시저에서 IP 끝점에 대 한 최대 12 * 4 = 48 동시 연결을 사용할 수 있습니다.That means that on a quad-proc, you can have at most 12 * 4 = 48 concurrent connections to an IP end point. 이는 자동 구성에 연결되기 때문에 ASP.NET 응용 프로그램에서 maxconnection를 늘리는 가장 쉬운 방법은 global.asax 파일의 from Application_Start 메서드에서 프로그래밍 방식으로를 설정 하는 것입니다 .Because this is tied to autoConfig, the easiest way to increase maxconnection in an ASP.NET application is to set System.Net.ServicePointManager.DefaultConnectionLimit programmatically in the from Application_Start method in the global.asax file. 예제는 샘플 다운로드를 참조 하세요.See the sample download for an example.

  • .NET 4.5에서 MaxConcurrentRequestsPerCPU 에 대 한 5000의 기본값은 적절 해야 합니다.In .NET 4.5, the default of 5000 for MaxConcurrentRequestsPerCPU should be fine.