Как использовать 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, если вообще изменят.


person bloudraak    schedule 17.11.2011    source источник
comment
Любое предложение для этого   -  person Zameer Ansari    schedule 11.12.2015


Ответы (1)


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

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

  1. Сохраните идентификатор клиента, используемый SignalR, как часть метаданных задачи:
  2. Поставьте задачу в очередь как обычно.
  3. When the task is processed and de-queued:
    • Update your database with the status.
    • Используя идентификатор клиента, сохраненный как часть этой задачи, используйте 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: из 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);
     }
}
person PabloC    schedule 21.11.2011
comment
Клиентский API, отличный от JS, не позволяет мне отправлять сообщение определенной группе или клиенту. В результате нет смысла отправлять его в фоновый процесс. Однако я отправляю идентификатор обратно на веб-сайт, который затем получает идентификатор владельца и отправляет уведомление группе SignalR с этим идентификатором. Когда пользователи подключаются и отключаются, я добавляю клиентов в группу. - person bloudraak; 16.12.2011
comment
ваш ответ сработал, однако в конце концов я решил отказаться от SignalR для пользовательского решения, которое прозрачно поддерживает безопасность. Поэтому пользователь может отправлять уведомления только тем пользователям, которым разрешено просматривать такие сообщения. Это требование никогда не входило в исходный вопрос, поэтому я отметил ваше как ответ. - person bloudraak; 07.02.2012
comment
@WernerStrydom Вы выбрали другую библиотеку или написали весь код с нуля? Не могли бы вы пролить больше света на вашу окончательную реализацию? - person helloworld; 20.05.2012
comment
Я использую длинный опрос. Многие браузеры отключили сокеты HTML5, поэтому другие механизмы (например, flash) имеют многочисленные ограничения. - person bloudraak; 20.05.2012
comment
@WernerStrydom SignalR использует лучший поддерживаемый транспорт, который работает на клиенте. Таким образом, вам не нужно беспокоиться о том, что поддерживают браузеры, так как это обрабатывается прозрачно. Кроме этого, я не уверен, что еще вам нужно. - person davidfowl; 21.05.2012
comment
@dfowler Безопасность и уведомления, которые работают на ферме серверов. В то время, когда я писал этот вопрос, SignalR не поддерживал ни того, ни другого. Для меня не было реальной выгоды продолжать использовать SignalR. - person bloudraak; 21.05.2012
comment
Без проблем. Хорошо, что вы проявили должную осмотрительность. SignalR будет продолжать улучшаться, и я надеюсь, что вы сможете снова взглянуть на него в будущем :). - person davidfowl; 21.05.2012