Перед нами стоит задача преобразовать REST-сервис на основе пользовательского кода в Web API. Служба имеет значительное количество запросов и работает с данными, загрузка которых может занять некоторое время, но после загрузки их можно кэшировать и использовать для обслуживания всех входящих запросов. В предыдущей версии службы один поток отвечал за загрузку данных и их попадание в кеш. Чтобы предотвратить исчерпание рабочих потоков IIS, клиенты будут получать ответ «вернуться позже», пока кеш не будет готов.
Мое понимание Web 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 с LazyThreadSafetyMode.ExecutionAndPublication гарантирует, что только первый поток/запрос выполняет код инициализации, следующие запросы блокируются до завершения инициализации.
Сможет ли веб-API обработать 1000 запросов, ожидающих завершения инициализации, в то время как другие запросы, не попадающие в этот Lazy, обслуживаются и без исчерпания рабочих потоков IIS?