Как использовать SignalR для уведомления веб-клиентов из ASP.NET MVC 3 о том, что задачи MSMQ были выполнены - PullRequest
16 голосов
/ 18 ноября 2011

Как использовать 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 Ответ

8 голосов
/ 21 ноября 2011

Если я правильно понимаю, вам нужен способ связать задачу с данным пользователем / клиентом, чтобы вы могли сообщить клиенту, когда его задача завершена.

В документации по SignalR API указано, что вы можете вызвать JSметоды для конкретных клиентов на основе идентификатора клиента (https://github.com/SignalR/SignalR/wiki/SignalR-Client). Теоретически вы можете сделать что-то вроде:

  1. Сохранить идентификатор клиента, используемый SignalR, как часть метаданных задачи:
  2. Поставить задачу в обычном режиме.
  3. Когда задача обработана и выведена из очереди:
    • Обновите базу данных со статусом.
    • Использование идентификатора клиента, сохраненного какВ рамках этой задачи используйте 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, отображенной ранее.

РЕДАКТИРОВАТЬ: С 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);
     }
}
...