ASP.NET (или IIS?) Поведение при одновременных запросах - PullRequest
1 голос
/ 24 марта 2012

Я разрабатываю веб-сервис с использованием ASP.NET MVC3. Один из методов HTTP API получает изображение из тела запроса POST и нуждается в его сохранении на диске для дальнейшей обработки. Начало метода выглядит так:

Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();

Interlocked.Increment(ref _generateCount);

byte[] fileBuffer;
using (Stream inputStream = Request.InputStream)
{
    if (inputStream.Length == 0)
    {
        Trace.WriteLine("Submitted file is empty", "Warning");
        inputStream.Close();
        Interlocked.Decrement(ref _generateCount);
        return new HttpStatusCodeResult(400, "Content is empty");
    }

    fileBuffer = new byte[inputStream.Length];
    inputStream.Read(fileBuffer, 0, (int)inputStream.Length);
    inputStream.Close();
}
stopwatch.Stop()
... (storing the fileBuffer on disk & quite CPU intensive processing on the file)

Я размещаю службу в небольшом экземпляре Azure.

Теперь странное поведение у меня возникает, когда я выполняю параллельные запросы к сервису. Допустим, я выдаю первый запрос, а второй - через 5 секунд. Как вы видите, я использую секундомер для мониторинга производительности. Для первого запроса ElapsedTime будет очень маленьким (менее одной секунды), но для второго он обычно читается ок. 14 секунд!

Обратите внимание, что среднее время обработки одного запроса составляет ок. 25 секунд (и достигает 40+ при обработке нескольких запросов), поэтому я читаю свой поток ввода через 14 секунд, хотя первый запрос еще не завершен.

Как я могу объяснить эту задержку?

Спасибо

1 Ответ

1 голос
/ 25 марта 2012

Если ваша конечная цель - сохранить файл на диске, почему вы загружаете его в память? Вы можете напрямую записать в выходной поток:

public ActionResult SomeAction()
{
    var stopwatch = Stopwatch.StartNew();
    if (Request.InputStream.Length == 0)
    {
        return new HttpStatusCodeResult(400, "Content is empty");
    }

    var filename = Server.MapPath("~/app_data/foo.dat");
    using (var output = System.IO.File.Create(filename))
    {
        Request.InputStream.CopyTo(output);
    }
    stopwatch.Stop();

    ...
}

Также обратите внимание, что если вы выполняете 2 одновременных запроса, которые пытаются записать в один и тот же файл на вашем сервере, вы можете получить поврежденные данные или ошибки, поскольку вы не можете одновременно записать в один и тот же файл.

...