Nos enfrentamos a la tarea de convertir un servicio REST basado en código personalizado a API web. El servicio tiene una cantidad sustancial de solicitudes y opera con datos que podrían demorar un tiempo en cargarse, pero una vez cargados, pueden almacenarse en caché y utilizarse para atender todas las solicitudes entrantes. La versión anterior del servicio tendría un hilo responsable de cargar los datos y meterlos en el caché. Para evitar que el IIS se quede sin subprocesos de trabajo, los clientes obtendrían una respuesta de "volver más tarde" hasta que el caché estuviera listo.Concurrencia y escalabilidad de API web
Mi comprensión de la API web es que tiene un comportamiento asíncrono incorporado al operar en tareas y, como resultado, el número de solicitudes no se relaciona directamente con la cantidad de subprocesos físicos que se mantienen.
En la nueva implementación del servicio, estoy planeando dejar que las solicitudes esperen hasta que la memoria caché esté lista y luego hacer una respuesta válida. He hecho un boceto muy aproximada del código para ilustrar:
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();
}
}
favor, no ponga demasiado valor en el diseño del código - que sólo se construye para ilustrar el problema y no es así como lo hicimos en la solución real. IContactRepository se registra en el contenedor IoC como singleton y se inyecta en el controlador. The Lazy con LazyThreadSafetyMode.ExecutionAndPublication asegura que solo el primer subproceso/solicitud ejecute el código de inicialización, las siguientes rutas se bloquean hasta que finalice la inicialización.
¿Sería capaz la API web de manejar 1000 solicitudes en espera de que se complete la inicialización, mientras que otras solicitudes que no afectan a este Lazy se están ejecutando y sin que IIS se quede sin hilos de trabajo?