Как использовать SignalR, чтобы уведомить веб-клиентов ASP.NET в MVC 3, которые были выполнены задачи в msmq
Как можно использовать SignalR для реализации уведомлений в системе .NET 4.0, состоящей из ASP.NET приложение MVC 3 (которое использует проверку подлинности форм), база данных SQL Server 2008 и служба MSMQ WCF (размещенная в WAS) для обработки данных? Среда выполнения состоит из IIS 7.5, работающего на Windows Server 2008 R2 Standard Edition.
Я только играл с образцами и не имею обширных знаний о SignalR.
Вот некоторый фон
Веб-приложение принимает данные от пользователя и добавляет их в таблицу. Затем он вызывает одностороннюю операцию (с ключом базы данных) службы WCF для обработки данных (задача). Веб-приложение возвращается на страницу, сообщающую пользователю, что данные были отправлены, и они будут уведомлены о завершении обработки. Пользователь может посмотреть на страницу "индекс" и посмотреть, какие задачи завершены, завершены неудачно или находятся в процессе выполнения. Они могут продолжать отправлять больше задач (что не зависит от предыдущих данных). Они могут закрыться их браузер и вернется позже.
Служба WCF на основе MSMQ считывает запись из базы данных и обрабатывает данные. Это может занять от миллисекунд до нескольких минут. После завершения обработки данных запись обновляется с соответствующим статусом (ошибка или сбой) и результатами.
Большую часть времени служба WCF не выполняет никакой обработки, однако когда это происходит, пользователи обычно хотят знать, когда это сделано как можно скорее. Пользователь все равно будет использовать другие части веб-приложения, даже если они не имеют данных для обработки службой WCF.
Вот что я сделал
В основной навигационной панели у меня есть индикатор (похожий на Facebook или Google+), чтобы пользователь уведомлял их, когда статус задач изменился. Когда они нажимают на него, они получают краткое описание того, что было сделано, а затем могут просматривать результаты, если они хотят.
Используя jQuery, я опрашиваю сервер на предмет изменений. Проверка действия контроллера чтобы узнать, есть ли какие-либо процессы, которые были изменены (завершены или завершены неудачно), и вернуть их в противном случае, подождите пару секунд и проверьте снова, не возвращаясь к клиенту. Чтобы избежать тайм-аута на клиенте, он вернется через 30 секунд, если не было никаких изменений. Скрипт jQuery немного подождет и повторит попытку.
Задачи
Производительность снижается с каждым пользователем, который просматривает страницу. Им нет необходимости делать что-то конкретное. Мы заметили что использование памяти Firefox 7+ и Safari увеличивается с течением времени.
Использование SignalR
Я надеюсь, что переключение на SignalR может уменьшить опрос и, таким образом, уменьшить требования к ресурсам, особенно если ничего не изменилось с точки зрения задач в базе данных. Мне трудно заставить службу WCF уведомлять клиентов, что она закончила обработку задачи, учитывая тот факт, что она использует аутентификацию на основе форм.
Задавая этот вопрос, я надеюсь, что кто-то даст мне лучшее представление о том, как они переработают мою схему уведомления с помощью SignalR, если вообще будут.
1 ответ:
Если я правильно понимаю, вам нужен способ связать задачу с данным пользователем/клиентом, чтобы вы могли сообщить клиенту, когда его задача завершена.
Документация SignalR API говорит мне, что вы можете вызывать методы JS для конкретных клиентов на основе идентификатора клиента (https://github.com/SignalR/SignalR/wiki/SignalR-Client в теории вы могли бы сделать что-то вроде:
- сохраните идентификатор клиента, используемый SignalR, как часть метаданных задачи:
- поставьте задачу в очередь как нормальный.
- Когда задача обработана и снята с очереди:
- обновите базу данных, указав ее статус.
- используя идентификатор клиента, сохраненный как часть этой задачи, используйте SignalR для отправки клиенту уведомления:
Вы должны иметь возможность получить соединение, которое использует ваш клиент, и отправить ему сообщение:
string clientId = processedMessage.ClientId //Stored when you originally queued it. IConnection connection = Connection.GetConnection<ProcessNotificationsConnection>(); connection.Send(clientId, "Your data was processed");Предполагается, что вы сопоставили это соединение и клиент использовал это соединение для запуска запроса на обработку данных в первом место. Ваша "основная панель навигации" имеет JS, который запустил соединение с конечной точкой
ProcessNotificationsConnection, которую вы сопоставили ранее.EDIT: From https://github.com/SignalR/SignalR/wiki/Hubs
public class MyHub : Hub { public void Send(string data) { // Invoke a method on the calling client Caller.addMessage(data); // Similar to above, the more verbose way Clients[Context.ClientId].addMessage(data); // Invoke addMessage on all clients in group foo Clients["foo"].addMessage(data); } }
Comments