동기화 작업 대신 비동기 WebAPI 작업을 만들어야하는 이유는 무엇입니까?
내가 만든 웹 API에서 다음 작업이 있습니다.
// GET api/<controller>
[HttpGet]
[Route("pharmacies/{pharmacyId}/page/{page}/{filter?}")]
public CartTotalsDTO GetProductsWithHistory(Guid pharmacyId, int page, string filter = null ,[FromUri] bool refresh = false)
{
return delegateHelper.GetProductsWithHistory(CustomerContext.Current.GetContactById(pharmacyId), refresh);
}
이 웹 서비스에 대한 호출은 다음과 같이 Jquery Ajax 호출을 통해 수행됩니다.
$.ajax({
url: "/api/products/pharmacies/<%# Farmacia.PrimaryKeyId.Value.ToString() %>/page/" + vm.currentPage() + "/" + filter,
type: "GET",
dataType: "json",
success: function (result) {
vm.items([]);
var data = result.Products;
vm.totalUnits(result.TotalUnits);
}
});
이 방법으로 이전 작업을 구현하는 일부 개발자를 보았습니다.
// GET api/<controller>
[HttpGet]
[Route("pharmacies/{pharmacyId}/page/{page}/{filter?}")]
public async Task<CartTotalsDTO> GetProductsWithHistory(Guid pharmacyId, int page, string filter = null ,[FromUri] bool refresh = false)
{
return await Task.Factory.StartNew(() => delegateHelper.GetProductsWithHistory(CustomerContext.Current.GetContactById(pharmacyId), refresh));
}
그러나 GetProductsWithHistory ()는 꽤 긴 작업이라고합니다. 내 문제와 상황을 감안할 때 webAPI 작업을 비동기식으로 만들면 어떤 이점이 있습니까?
특정 예에서 작업이 전혀 비동기 적이 지 않으므로 수행중인 작업은 비동기 오버 싱크입니다. 하나의 스레드를 해제하고 다른 스레드를 차단하고 있습니다. 모든 스레드가 GUI 응용 프로그램과 달리 스레드 풀 스레드이기 때문에 그럴 이유가 없습니다.
“동기 오버 동기화”에 대한 논의에서 내부적으로 동기식으로 구현되는 API가있는 경우 동기 메소드를 래핑하는 비동기 상대방을 노출해서는 안된다고 강력히 제안했습니다
Task.Run
.
에서 해야 내가 비동기 메서드에 대한 동기 래퍼를 노출?
그러나 async
스레드가 결과를 기다리는 스레드를 차단하는 대신 실제 비동기 작업 (일반적으로 I / O)이있는 곳에서 WebAPI를 호출 하면 스레드가 스레드 풀로 돌아가서 다른 작업을 수행 할 수 있습니다. 무엇보다도 애플리케이션이 적은 리소스로 더 많은 것을 할 수 있고 확장 성이 향상됩니다.
한 가지 접근 방식은 (고객 응용 프로그램에서이를 성공적으로 사용했습니다) Windows 서비스가 작업자 스레드로 긴 작업을 실행하도록하고 IIS 에서이 작업을 수행하여 차단 작업이 완료 될 때까지 스레드를 해제 할 수 있습니다. 결과는 테이블 (jobId로 식별 된 행)에 저장되고 사용 후 몇 시간 후에 정리 프로세스가 정리됩니다.
"문제와 상황을 설명하면 webAPI 작업을 비 동기화하면 어떤 이점이 있습니까?"라는 질문에 대답하려면 "긴 작업"이라고 생각하면 ms가 아니라 몇 초가 걸리는 것 같습니다.이 방법은 IIS 스레드를 해제합니다. 분명히 자체 리소스를 사용하는 Windows 서비스를 실행해야하지만이 방법은 느린 쿼리로 인해 시스템의 다른 부분에서 스레드를 훔치는 것을 방지 할 수 있습니다.
// GET api/<controller>
[HttpGet]
[Route("pharmacies/{pharmacyId}/page/{page}/{filter?}")]
public async Task<CartTotalsDTO> GetProductsWithHistory(Guid pharmacyId, int page, string filter = null ,[FromUri] bool refresh = false)
{
var jobID = Guid.NewGuid().ToString()
var job = new Job
{
Id = jobId,
jobType = "GetProductsWithHistory",
pharmacyId = pharmacyId,
page = page,
filter = filter,
Created = DateTime.UtcNow,
Started = null,
Finished = null,
User = {{extract user id in the normal way}}
};
jobService.CreateJob(job);
var timeout = 10*60*1000; //10 minutes
Stopwatch sw = new Stopwatch();
sw.Start();
bool responseReceived = false;
do
{
//wait for the windows service to process the job and build the results in the results table
if (jobService.GetJob(jobId).Finished == null)
{
if (sw.ElapsedMilliseconds > timeout ) throw new TimeoutException();
await Task.Delay(2000);
}
else
{
responseReceived = true;
}
} while (responseReceived == false);
//this fetches the results from the temporary results table
return jobService.GetProductsWithHistory(jobId);
}
'programing tip' 카테고리의 다른 글
Visual Studio에서 Interop 유형 포함 참과 거짓의 차이점은 무엇입니까? (0) | 2020.08.06 |
---|---|
바이트에 대한 적절한 최대 절전 모드 주석 (0) | 2020.08.06 |
NameNotFoundException 웹뷰 (0) | 2020.08.06 |
버전 관리 저장소를 어떻게 구성합니까? (0) | 2020.08.06 |
Django에서 정적 STATIC_URL과 STATIC_ROOT의 차이점 (0) | 2020.08.06 |