2016-12-08 14 views
18

I asked this question около 5 лет назад о том, как «разгружать» дорогостоящие операции, когда пользователям не нужно ждать (например, auditng и т. Д.), Чтобы быстрее получить ответ на лицевой стороне.В asp.net-mvc, каков правильный способ делать дорогостоящие операции без влияния на других пользователей?

У меня есть связанный, но другой вопрос. На моем asp.net-mvc я создал несколько отчетов, где вы можете генерировать отчеты excel (i am using EPPlus) и отчеты о Powerpoint (i am using aspose.slides). Вот пример действие контроллера:

public ActionResult GenerateExcelReport(FilterParams args) 
    { 
     byte[] results = GenerateLargeExcelReportThatTake30Seconds(args); 
     return File(results, @"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml", "MyReport.xlsx"); 
    } 

Функциональность работает прекрасно, но я пытаюсь выяснить, если эти дорогостоящие операции (некоторые отчеты могут занять до 30 секунд, чтобы вернуться) оказывает воздействие других пользователей. В предыдущем вопросе у меня была дорогостоящая операция, которую пользователь DIDN «T должен ждать, но в этом случае ему придется ждать в качестве своего синхронного действия (нажмите« Создать отчет »и ожидайте, что пользователи получат отчет, когда его законченный)

в этом случае, я не забочусь о том, что основной пользователь должен подождать 30 секунд, но я просто хочу, чтобы убедиться, что я не негативно влияют другие пользователи из-за этой дорогостоящей операции, создания файлов и т.д.

Есть ли какая-либо лучшая практика здесь, в asp.net-mvc для этого случая использования?

+0

Асинхронные методы и действительно хорошие, попробуйте эту статью https://www.asp.net/mvc/overview/performance/using-asynchronous-methods-in-aspnet-mvc-4 – Emil

ответ

6

Вы можете попробовать комбинацию Hangfire и SignalR. Используйте Hangfire для запуска фоновой работы и отказа от HTTP-запроса. И как только генерация отчета будет завершена, используйте SignalR для создания push-уведомления.

SignalR notification from server to client

Альтернативный вариант заключается в реализации механизма опроса на стороне клиента. Отправьте вызов ajax, чтобы выполнить задание для работы с огнем, чтобы сгенерировать отчет. И затем начните опрос некоторых api, используя другой вызов ajax, который обеспечивает статус, и как только отчет будет готов, извлеките его. Я предпочитаю использовать SignalR вместо опроса.

Если обработка отчетов влияет на производительность на веб-сервере, выгрузите эту обработку на другой сервер. Вы можете использовать обмен сообщениями (ActiveMQ или RabbitMQ или какую-либо другую структуру по вашему выбору) или вызов api для отдыха, чтобы начать генерировать отчеты на другом сервере, а затем снова использовать обмен сообщениями или вызов api для уведомления о завершении создания отчетов на веб-сервере, наконец SignalR для уведомления клиента. Это позволит веб-серверу быть более отзывчивым.

UPDATE Что касается вашего вопроса

Есть ли лучшая практика здесь в asp.net-MVC для этого случая использования

Вы должны контролировать свои сверхурочно приложения. Мониторинг как клиентской, так и серверной. Есть несколько инструментов, на которые можно положиться, таких как newrelic, динамика приложений.Я использовал newrelic, и у него есть функции для отслеживания проблем как в браузере клиента, так и на стороне сервера. Именами продукта являются «NewRelic Browser» и «NewRelic Server». Я уверен, что есть другие инструменты, которые будут захватывать подобную информацию.

Проанализируйте сверхурочные показатели, и если вы видите какие-либо аномалии, тогда предпримите соответствующие действия. Если вы наблюдаете центральный процессор и всплески памяти на сервере, попробуйте захватить метрики на стороне клиента примерно в один и тот же таймфрейм. На стороне клиента, если вы заметили какие-либо проблемы с таймаутом, ошибки подключения, которые означают, что ваши приложения не могут подключиться к вашему приложению, пока сервер делает тяжелую работу. Затем попытайтесь определить узкие места на стороне сервера. Если не хватает места для настройки, настройте код, а затем перейдите к выполнению планирования пропускной способности сервера и выясните, как увеличить масштаб вашего оборудования или переместить фоновые задания из веб-серверов, чтобы уменьшить нагрузку. Просто захватить метрики с помощью этих инструментов может быть недостаточно, вам может потребоваться (регистрация журнала) вашего приложения для захвата дополнительных показателей для правильного мониторинга состояния приложения.

Here вы можете найти информацию о планировании емкости приложения .net от Microsoft.

-Vinod.

0

Вам необходимо следить за пользователями приложения, чтобы узнать, влияют, например, путем записи времени ответа

Если вы обнаружите, что это влияет на других пользователей, вам необходимо запустить задачу в другом процессе, возможно, на другой машине. Для этого вы можете использовать библиотеку Hangfire.

+0

спасибо. Я посмотрел на Hangfire, который, кажется, отличное решение, когда я запускаю дорогостоящую операцию, которую главный пользователь не волнует (например, аудит или внеполосное уведомление по электронной почте другим пользователям), но в этом случае основными пользователями являются ожидая конкретного ответа, поэтому я не вижу, как в этом случае работает фальшивка. – leora

+0

Как сказал Винод, используйте некоторую систему уведомлений или опрос, чтобы предупредить пользователя о завершении задания. – mcintyre321

2

В целом можно считать хорошей практикой запускать длительные запущенные задачи в фоновом режиме и дать какое-то уведомление пользователю, когда работа выполнена. Поскольку вы, вероятно, знаете, что время выполнения веб-запроса ограничено 90 секундами, поэтому, если ваша долговременная задача может превысить это, у вас нет выбора, кроме как запустить какой-либо другой поток/процесс. Если вы используете .net 4.5.2, вы можете использовать HostingEnvironment.QueueBackgroundWorkItem для выполнения длинных запущенных задач в фоновом режиме и использовать SignalR, чтобы уведомить пользователя о завершении выполнения задачи. В случае, если вы создаете файл, вы можете сохранить его на сервере с уникальным идентификатором и отправить пользователю ссылку для его загрузки. Вы можете удалить этот файл позже (например, с помощью некоторых служб Windows).

Как уже отмечалось другими, некоторые более продвинутые бегуны фоновой задачи, такие как замедленное воспламенение, Quartz.Net и другие, но общее понятие одно и то же - запуск задач в и уведомлять фоном пользователя, когда это делается. Вот несколько хороших article о разных приложениях для выполнения фоновых задач.

0

Используя этот ответ, вы можете объявить задачу с низким приоритетом

lowering priority of Task.Factory.StartNew thread

public ActionResult GenerateExcelReport(FilterParams args) 
{ 
    byte[] result = null; 
    Task.Factory.StartNew(() => 
    { 
     result = GenerateLargeExcelReportThatTake30Seconds(args); 
    }, null, TaskCreationOptions.None, PriorityScheduler.BelowNormal) 
     .Wait(); 

    return File(result, @"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml", "MyReport.xlsx"); 
} 
+0

На самом деле это не проблема. –

1

Я считаю, что это инструмент/библиотека, такие как Hangfire то, что ваш ищет. Во-первых, это позволит вам указать запуск задачи в фоновом потоке (в том же приложении/процессе). Использование различных методов, таких как SignalR, позволяет получать уведомления в режиме реального времени в режиме реального времени.

Однако, что-то, что я установил после использования Hangfire в течение почти года, разбил нашу работу (и реализацию) на другой сервер, используя this documentation. Я использую внутреннее приложение ASP.NET MVC для обработки заданий на другом сервере. Таким образом, единственным узким местом производительности является то, что оба сервера используют одно и то же хранилище данных (например, базу данных). Если вы блокируете базу данных, единственный способ ее минимизации - минимизировать блокировку указанного ресурса, независимо от используемой вами методологии.

Я использую интерфейсы для запуска заданий, которые хранятся в общей библиотеке:

public interface IMyJob 
{ 
    MyJobResult Execute(MyJobSettings settings); 
} 

И, спусковой крючок, найденная в фронтальном применении:

//tell the job to run 
var settings = new MyJobSettings(); 
_backgroundJobClient.Enqueue<IMyJob>(c => c.Execute(settings)); 

Затем на моем фоне сервере Я пишу реализацию (и крюк в нем в Autofac IOC container я использую):

public class MyJob : IMyJob 
{ 
    protected override MyJobResult Running(MyJobSettings settings) 
    { 
     //do stuff here 
    } 
} 

I ч aven't слишком много перепутал с попыткой заставить SignalR работать на двух серверах, поскольку я еще не сталкивался с этим конкретным случаем использования, но теоретически это возможно.

2

Вам необходимо использовать async and await of C#.

С вашего вопроса я решил, что вы просто обеспокоены тем фактом, что запрос может занять больше ресурсов, чем нужно, вместо масштабируемости. Если это так, сделайте действия вашего контроллера асинхронными, а также все операции, которые вы вызываете, если они связаны с вызовами, которые блокируют потоки. например если ваши запросы проходят через провода или операции ввода-вывода, они будут блокировать поток без async (технически, вы будете, так как вы будете ждать ответа до продолжения). С помощью async эти потоки становятся доступными (ожидая ответа), и поэтому они могут потенциально обслуживать другие запросы других пользователей.

Я предполагал, что вы не блуждаете, как масштабировать запросы. Если да, дайте мне знать, и я могу предоставить подробную информацию об этом (слишком много, чтобы писать, если это необходимо).

0

Очередь заданий в таблице, и у вас есть фоновый опрос о том, что таблица, чтобы решить, какое очень большое задание нужно запустить дальше. Затем вашему веб-клиенту необходимо будет опросить сервер, чтобы определить, когда задание будет завершено (возможно, проверив флаг в базе данных, но есть и другие методы.) Это гарантирует, что у вас не будет более одного (или сколько бы вы ни были решить, подходит) из этих дорогостоящих процессов, выполняемых одновременно.

Hangfire и SignalR могут помочь вам здесь, но механизм массового обслуживания действительно необходим, чтобы избежать серьезных сбоев, когда, скажем, пять пользователей просят этот же процесс одновременно. Подходы, упомянутые в том, что устранение новых потоков или фоновых процессов, по-видимому, не обеспечивают какого-либо механизма для минимизации потребления процессора/памяти, чтобы не прерывать других пользователей из-за потребления слишком большого количества ресурсов.

5

Все это отличные идеи о том, как переместить работу из цикла запроса/ответа. Но я думаю, что @leora просто хочет знать, будет ли долговременный запрос неблагоприятно воздействовать на других пользователей приложения asp.net.

Ответ отрицательный. asp.net является многопоточным. Каждый запрос обрабатывается отдельным рабочим потоком.

 Смежные вопросы

  • Нет связанных вопросов^_^