2012-04-16 5 views
12

커스텀 코드에 기반한 REST 서비스를 웹 API로 변환하는 작업에 직면했다. 이 서비스는 상당한 양의 요청을 가지고 있으며 데이터로드에 시간이 걸릴 수 있지만 일단로드되면 캐싱되어 모든 들어오는 요청을 처리하는 데 사용될 수 있습니다. 이전 버전의 서비스에는 데이터를로드하고 캐시로 가져 오는 스레드가 하나있었습니다. IIS가 작업자 스레드를 모두 사용하지 못하도록 클라이언트는 캐시가 준비 될 때까지 "나중에 다시 돌아옵니다"라는 응답을 받게됩니다.웹 API 병행 성 및 확장 성

웹 API에 대한 필자의 이해는 웹 서비스가 비동기 동작을 내장하고있어 결과적으로 요청 수가 홀드되는 실제 스레드의 수와 직접적으로 관련이 없다는 것입니다.

서비스의 새로운 구현에서 캐시가 준비 될 때까지 요청을 대기시킨 다음 유효한 응답을 할 계획입니다. 나는 설명하기 위해 코드의 매우 거친 스케치를 만든 :

public class ContactsController : ApiController 
{ 
    private readonly IContactRepository _contactRepository; 

    public ContactsController(IContactRepository contactRepository) 
    { 
     if (contactRepository == null) 
      throw new ArgumentNullException("contactRepository"); 
     _contactRepository = contactRepository; 
    } 

    public IEnumerable<Contact> Get() 
    { 
     return _contactRepository.Get(); 
    } 
} 

public class ContactRepository : IContactRepository 
{ 
    private readonly Lazy<IEnumerable<Contact>> _contactsLazy; 

    public ContactRepository() 
    { 
     _contactsLazy = new Lazy<IEnumerable<Contact>>(LoadFromDatabase, 
      LazyThreadSafetyMode.ExecutionAndPublication); 
    } 

    public IEnumerable<Contact> Get() 
    { 
     return _contactsLazy.Value; 
    } 

    private IEnumerable<Contact> LoadFromDatabase() 
    { 
     // This method could be take a long time to execute. 
     throw new NotImplementedException(); 
    } 
} 

코드의 디자인에 너무 많은 값을 넣지 마십시오 - 단지 문제를 설명하기 위해 건설하고 우리가 그것을 어떻게하지 않다 실제 해결책. IContactRepository는 IoC 컨테이너에 싱글 톤으로 등록되고 컨트롤러에 주입됩니다. Lazy with LazyThreadSafetyMode.ExecutionAndPublication은 초기화 코드가 실행되는 첫 번째 스레드/요청 만 보장하며 다음 rquests는 초기화가 완료 될 때까지 차단됩니다.

Web API는 초기화가 완료 될 때까지 대기하는 1000 개의 요청을 처리 할 수 ​​있습니까? 그렇지 않으면이 Lazy를 타격하지 않는 다른 요청은 서비스 중이며 IIS에는 작업자 스레드가 부족하지 않습니다.

답변

10

액션에서 Task<T>을 반환하면 백그라운드 스레드 (ThreadPool)에서 코드를 실행하고 IIS 스레드를 릴리스 할 수 있습니다. 따라서이 경우에는, 나는 그렇지 않으면 스레드 그냥 앉아서 아무것도하지 않는 것 작업을 시작 반환하는 것을 잊지

public Task<IEnumerable<Contact>> Get() 

public IEnumerable<Contact> Get() 

을 변경합니다.

게으른 구현이 유용 할 수 있지만 웹 API의 동작과 관련이 거의 없습니다. 그래서 나는 그것에 대해 논평하지 않을 것이다. 게으르거나 유무에 관계없이 작업 기반의 반환 유형은 장기 실행 작업을 수행하는 방법입니다.

저는이 블로그 게시물이 유용 할 것 같아요 : herehere입니다.