2011-11-17 12 views
16

W jaki sposób można użyć SignalR do implementacji powiadomień w systemie .NET 4.0, który składa się z aplikacji ASP.NET MVC 3 (która korzysta z formularzy uwierzytelnianie), baza danych SQL Server 2008 i usługa WCF MSMQ (hostowana w WAS) do przetwarzania danych? Środowisko wykonawcze składa się z IIS 7.5 działającego w systemie Windows Server 2008 R2 Standard Edition.Jak używać SignalR do powiadamiania klientów WWW z ASP.NET MVC 3, że zadania MSMQ zostały zakończone?

Grałem tylko z próbkami i nie posiadam rozległej wiedzy na temat SignalR.

Oto tło

Aplikacja internetowa przyjmuje dane od użytkownika i dodaje go do stołu. Następnie wywołuje operację jednokierunkową (z kluczem bazy danych) usługi WCF w celu przetworzenia danych (zadanie). Aplikacja sieciowa powraca na stronę informującą użytkownika o tym, że dane zostały przesłane i zostaną powiadomione po zakończeniu przetwarzania. Użytkownik może przejrzeć stronę "indeksu" i zobaczyć, które zadania zostały zakończone, nie powiodły się lub są w toku. Mogą nadal przesyłać więcej zadań (co jest niezależne od poprzednich danych). Mogą zamknąć przeglądarkę i wrócić później.

Usługa WCF na podstawie MSMQ odczytuje rekord z bazy danych i przetwarza dane. Może to zająć od milisekund do kilku minut. Po zakończeniu przetwarzania danych rekord jest aktualizowany o odpowiedni status (błąd lub niepowodzenie) i wyniki.

W większości przypadków usługa WCF nie wykonuje żadnego przetwarzania, jednak kiedy to robi, użytkownicy zazwyczaj chcą wiedzieć, kiedy jest ona wykonana tak szybko, jak to możliwe. Użytkownik nadal będzie korzystać z innych części aplikacji internetowej, nawet jeśli nie ma danych do przetworzenia przez usługę WCF.

To co mam zrobić

W pierwotnym pasku nawigacyjnym, mam wskaźnik (podobny do Facebook czy Google+) dla użytkownika, aby powiadomić ich, gdy status zadań uległ zmianie. Po kliknięciu otrzymają podsumowanie tego, co zostało zrobione, a następnie mogą wyświetlić wyniki, jeśli chcą.

Korzystając z jQuery, odpytuję serwer w poszukiwaniu zmian. Akcja kontrolera sprawdza, czy istnieją jakieś zmodyfikowane procesy (zakończone lub nieudane) i zwróć je w inny sposób, czekając na kilka sekund i sprawdzając ponownie bez zwracania się do klienta. Aby uniknąć przekroczenia limitu czasu na kliencie, powróci on po 30 sekundach, jeśli nie było żadnych zmian. Skrypt jQuery czeka chwilę i próbuje ponownie.

Problemy

wydajność spada z każdym użytkownikiem, które wyświetlają stronę. Nie ma potrzeby, aby cokolwiek robili w szczególności. Zauważyliśmy, że wykorzystanie pamięci Firefox 7+ i Safari rośnie z czasem.

Korzystanie SignalR

Mam nadzieję, że przejście do SignalR może zmniejszyć odpytywanie, a tym samym zmniejszyć wymagania zasobów szczególnie jeśli nic się nie zmieniło zadanie mądry w bazie danych. Mam problem z pobraniem usługi WCF do powiadamiania klientów o tym, że jest ona wykonywana podczas przetwarzania zadania, ponieważ korzysta z uwierzytelniania opartego na formularzach.

Zadając to pytanie, mam nadzieję, że ktoś da mi lepszy wgląd w to, jak przeprojektują mój schemat powiadamiania za pomocą SignalR, jeśli w ogóle.

+0

Wszelkie sugestie dla [to] (http://stackoverflow.com/q/34090045/2404470) – xameeramir

Odpowiedz

8

Jeśli dobrze rozumiem, potrzebny jest sposób powiązania zadania z danym użytkownikiem/klientem, aby można było powiedzieć klientowi, kiedy jego zadanie zostało zakończone.

Dokumentacja interfejsu API SignalR mówi, że można wywoływać metody JS dla konkretnych klientów na podstawie identyfikatora klienta (https://github.com/SignalR/SignalR/wiki/SignalR-Client). Teoretycznie można zrobić coś takiego:

  1. przechowywania identyfikatora klienta używany przez SignalR jako część metadanych zadanie:
  2. kolejki zadanie jako normalne.
  3. Gdy zadanie jest przetwarzane i de-kolejce:
    • Aktualizacja bazy danych o statusie.
    • użyciu identyfikatora klienta przechowywane w ramach tego zadania, należy SignalR wysłać taki klient powiadomienia:

powinien być w stanie odbierać połączenia, że ​​klient korzysta i wysłać im wiadomość :

string clientId = processedMessage.ClientId //Stored when you originally queued it. 
IConnection connection = Connection.GetConnection<ProcessNotificationsConnection>(); 
connection.Send(clientId, "Your data was processed"); 

Zakłada, że ​​mapowałeś to połączenie, a klient użył tego połączenia, aby najpierw uruchomić żądanie przetwarzania danych. Twój "podstawowy pasek nawigacyjny" ma JS, który rozpoczął połączenie z punktem końcowym ProcessNotificationsConnection, który wcześniej zmapowałeś.

EDIT: Od 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); 
    } 
} 
+0

Klient API non-JS nie pozwala mi wysłać określoną grupę lub klienta wiadomość. W rezultacie nie ma żadnej wartości, aby wysłać ją do procesu w tle. Jednakże wysyłam identyfikator z powrotem do strony internetowej, która następnie otrzymuje "identyfikator" "właściciela" i wysyła powiadomienie do grupy SignalR z tym "identyfikatorem". Gdy użytkownicy łączą się i rozłączają, dodajem klientów do grupy. – bloudraak

+0

Jeśli pracujesz w hubie, robi to. Zobacz zmodyfikowaną odpowiedź. – PabloC

+0

Twoja odpowiedź zadziałała, jednak w końcu zdecydowałem się zrzucić SignalR dla niestandardowego rozwiązania, które transparentnie obsługuje zabezpieczenia. Dlatego użytkownik może wysyłać tylko powiadomienia do użytkowników upoważnionych do wyświetlania takich wiadomości. To wymaganie nigdy nie było częścią pierwotnego pytania, więc oznaczyłem twoje jako odpowiedź. – bloudraak

Powiązane problemy