Параллелизм и масштабируемость веб-API

Перед нами стоит задача преобразовать 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?

12
задан Hendrik W. Hansen 16 April 2012 в 12:19
поделиться