2015-03-01 5 views
2

У меня есть сайт на Rackspace, который выполняет расчет, расчет может занять от 30 секунд до нескольких минут. Первоначально я реализовал это с помощью SignalR, но ему пришлось вырвать его из-за чрезмерного использования CC. Сайты Hosted Rackspace действительно не предназначены для такого использования. Билл прошел через крышу.MVC 5/.NET 4.5 - Долгосрочный процесс

Базовый код, как показано ниже, отлично работает на моем тестовом сервере, но, конечно же, получает ошибку тайм-аута в Rackspace, если расчет занимает более 30 секунд из-за того, что их наблюдатель убил его. (старый код) Мне сказали, что операция должна записываться в поток, чтобы сохранить его. В старые времена я бы начал поток и опросил сайт до тех пор, пока поток не будет выполнен. Если есть лучший способ, я бы предпочел взять его.

Кажется, что с .NET 4.5 я могу использовать HttpTaskAsyncHandler для этого. Но я не понимаю. Ниже (новый код) я понимаю обработчик, который вы использовали бы, используя старый код при использовании и помещая его в задачу ProcessRequestAsync. Когда я пытаюсь вызвать CalcHandler/Calc, я получаю ошибку 404, которая, скорее всего, связана с маршрутизацией. Я пытался следовать этой ссылке, но не мог заставить ее работать. Имя добавления - «myHandler», но ссылка на пример - «фид», как мы получили от одного к другому. Они упомянули, что создали библиотеку классов, но может ли код быть в том же проекте, что и текущий код, как?

http://codewala.net/2012/04/30/asynchronous-httphandlers-with-asp-net-4-5/

Как примечание стороны, будет HttpTaskAsyncHandler позвольте мне сохранить запрос в живых до тех пор, пока не будет завершен, если он занимает несколько минут? В основном я должен использовать что-то еще для того, что я пытаюсь выполнить.

Старый код

[Authorize] 
[AsyncTimeout(5000)] // does not do anything on RackSpace 
public async Task<JsonResult> Calculate(DataModel data) 
{ 
    try 
    { 
     using (var db = new ApplicationDbContext()) 
     { 
      var result = await CalcualteResult(data); 
      return Json(result, JsonRequestBehavior.AllowGet); 
     } 
    } 
    catch (Exception ex) 
    { 
     LcDataLink.ProcessError(ex); 
    } 

    return Json(null, JsonRequestBehavior.AllowGet); 
} 

новый код

public class CalcHandler : HttpTaskAsyncHandler 
{ 
    public override System.Threading.Tasks.Task ProcessRequestAsync(HttpContext context) 
    { 
     Console.WriteLine("test"); 
     return new Task(() => System.Threading.Thread.Sleep(5000)); 
    } 
    } 
+0

Кажется, самым прямым решением является удаление/повышение ограничения тайм-аута запроса RackSpace. На стороне примечание «AsyncTimeout» должно использоваться в сочетании с «CancellationToken» - он не будет убивать ваш запрос, как синхронный таймаут; он попросит его отменить, установив «CancellationToken». –

+0

Я согласен с тем, что Rackspace увеличивает время ожидания, но это не вариант. Есть ли у вас ссылка или пример использования CancellationToken с MVC 5 и .NET 4.5? –

+0

http://www.asp.net/mvc/overview/performance/using-asynchronous-methods-in-aspnet-mvc-4#CancelToken –

ответ

0

Это не лучший подход. Обычно вам нужно создать отдельный процесс («рабочая роль» в Azure).

Этот процесс будет обрабатывать длительные операции и сохранять результат в базе данных. С помощью SignalR (или путем вызова метода api каждые 20 секунд) вы обновите статус этой операции на стороне клиента (ваш браузер).

Если этот процесс занимает слишком много времени для расчета, ваш сервер станет потенциально уязвимым для атак DDoS.

Кроме того, это зависит от конфигурации, но длительные операции могут быть убиты самим сервером. По умолчанию, если я не ошибаюсь, после 30 минут исполнения.

+1

Извините, но я не понимаю, как это относится к моему вопросу. Это запросы, которые занимают не более двух минут. У .NET 4.5 есть лучший способ реализации этого запроса API или просто вернуться к старому стандарту? Был ли я неясен в моем вопросе? –