Отключение клиента SignalR .NET

Мы столкнулись с интересной проблемой. Вот как выглядит наша установка:

  • SignalR Server (приложение ASP.NET MVC) на Windows Server 2012.
  • Приложения Sencha HTML5 (клиенты SignalR) на одном сервере (Windows Server 2012).
  • .NET Windows Service на сервере Windows Server 2008 R2. Он также действует как клиент SignalR.

Изначально мы использовали SignalR 0.5.3 - когда мы начали замечать, что соединение службы Windows с сервером signal R разрывается. Частота этого колеблется от нескольких минут до нескольких часов. В большинстве случаев он повторно подключается, но время от времени не удается восстановить подключение, в результате чего служба Windows теряет подключение раз в пару дней. Но для этого нет установленного образца. Это не связано с перезапуском сервера / резервным копированием и т. Д. Мы добавили ведение журнала в службу Windows для отслеживания события StateChanged в клиентском соединении и обнаружили, что событие запускается, когда оно отключается и повторно подключается, но не когда оно не подключается повторно.

Затем мы наткнулись на эту тему: клиент постоянно переподключается

и решил обновить все до SignalR 1.0.1 (в какой-то момент нам все равно пришлось это сделать). Служба Windows также была обновлена ​​до framework 4.5 (от Framework 2.0), теперь ссылаясь на новый Microsoft.AspNet.SignalR.Client.dll. Это также позволило нам (используя недавно добавленное свойство подключения) определить, что служба Windows на самом деле использует протокол ServerSentEvents. При установке той же службы Windows на компьютере с Windows Server 2012 используется протокол WebSockets. Это соответствует этому потоку: Клиент SignalR .NET не работает ' t поддерживает WebSockets в Windows 7

Однако поведение службы на сервере Windows Server 2008 R2 не изменилось. Он по-прежнему отключается и снова подключается, и время от времени теряет связь. Из-за некоторых ограничений мы не можем использовать Windows Server 2012 для службы Windows и застряли на более старых ОС. Это не означает, что служба Windows, использующая протокол websockets, решит все наши проблемы (мы не тестировали это полностью).

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

Но это не помогло. Сейчас мы находимся в точке, где мы чувствуем, что исчерпали все возможные варианты. Предложения были бы весьма признательны. Спасибо.

=====================================

РЕДАКТИРОВАТЬ: ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ:

Хорошо, теперь у нас есть дополнительная информация. Мы добавили код в службу Windows (клиент SignalR) для входа на сервер SignalR каждые 30 минут (для проверки соединения).

Вот что происходит на стороне клиента каждые 30 минут:

WriteEvent(Now(), "INFO", "PING", "Performing logon procedure with SiteCode = " & msSiteCode & ".")
trans.Invoke("login", New String() {msSiteCode, "", "SERVER", "", ""})

где trans - это экземпляр серверного класса, унаследованного от Hub, а WriteEvent - это, по сути, трассировка для записи в файл журнала.

а на стороне клиента также есть метод isLoggedIn, как показано ниже:

Private Sub isLoggedIn(ByVal bLoggedIn As String)
        If bLoggedIn Then
            WriteEvent(Now(), "INFO", "", "SignalR Server: Authenticated")           
        Else
            WriteEvent(Now(), "ERROR", "", "SignalR Server: Authentication failed")
        End If
End Sub

На стороне сервера у нас есть метод входа в систему:

Public Sub login(ByVal sAccount As String, _
                     ByVal sCompanyCode As String, _
                     ByVal sClientId As String, _
                     ByVal sPassword As String, _
                     ByVal sModuleCode As String)
       Try
            'Some code omitted that validates the user and sets bValidated.

            If bValidated Then
                'Update user in cache
                ConnectionCache.Instance.UpdateCache(userId, Context.ConnectionId, UserCredential.Connection_Status.Connected)
                Clients.Caller.isLoggedIn(True)

                Dim connectionId As String = ConnectionCache.Instance.FindConnectionId(userId)
                LogEvent("Successful login for connectionid: " & connectionId & ". Context. User: " & userId, _
                         EventLogEntryType.Information)
            Else
                Clients.Caller.isLoggedIn(False, results)
            End If
        Catch ex As Exception
            LogEvent("Login: " & ex.Message, EventLogEntryType.Error)
        End Try
End Sub

Если мы посмотрим на файл журнала клиента, каждые 30 минут мы получим следующие записи журнала:

  • Выполнение процедуры входа в систему с SiteCode = ABCD.
  • Сервер SignalR: аутентифицирован

Итак, мы знаем, что вызывается серверный метод входа в систему, а также вызывается клиентский метод isLoggedIn.

Однако в какой-то момент, когда вызывается серверный метод, клиентский метод isLoggedIn не вызывается. Итак, каждые 30 минут мы начинаем получать только одну запись:

  • Выполнение процедуры входа в систему с SiteCode = ABCD.

Кроме того, событие журнала:

LogEvent("Successful login for connectionid: " & connectionId & ". Context. User: " & userId, EventLogEntryType.Information)

в серверном методе входа в систему записывается в серверный журнал. Итак, Clients.Caller.isLoggedIn (True) вызывается должным образом, но мы не видим этого на стороне клиента.

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

Кроме того, это может быть чем-то специфическим для .NET-клиентов, поскольку я почти уверен, что мы не видели, чтобы это происходило с нашими клиентами HTML5 / javascript.


person smitra    schedule 20.03.2013    source источник
comment
При желании вы можете опробовать ночной пакет для клиента в этой ленте myget www.myget.org/F/aspnetwebstacknightly/. Теперь у нас есть ведение журнала на стороне клиента (у Connection есть свойство TextWriter connection.Trace). Вы можете использовать это, чтобы узнать, что происходит и почему что-то не работает в вашей сети.   -  person davidfowl    schedule 20.03.2013
comment
Спасибо. Мы зарегистрировали еще несколько событий и обновили исходный вопрос, добавив дополнительную информацию.   -  person smitra    schedule 21.03.2013
comment
Вам нужна регистрация на стороне клиента, а не на стороне сервера.   -  person davidfowl    schedule 21.03.2013
comment
Удалось ли вам это решить?   -  person zaitsman    schedule 05.05.2013
comment
Вы когда-нибудь это решали?   -  person Dave Alperovich    schedule 24.04.2014
comment
См. Недавно добавленный ответ.   -  person smitra    schedule 30.04.2014


Ответы (1)


В конце концов, мы просто создали простую функцию «PINGING». Он вызывается каждые 15 минут. Логика следующая:

  1. У клиента SignalR есть таймер, который вызывает метод PING сервера каждые 15 минут.
  2. В ответ сервер вызывает клиентский метод PINGCLIENT на клиенте.
  3. В следующем событии таймера PING на клиенте (через 15 минут) мы проверяем, получил ли ответ. Если мы этого не сделали, мы приостанавливаем все действия и повторно инициализируем соединение с концентратором. Затем перезапустите таймер PINGING.

Так что, хотя мы отказались от попыток выяснить, в чем была причина, у нас есть обходной путь для управления потерей соединения «сервер-клиент», когда это происходит. Обратите внимание, что это в дополнение к встроенной логике повторного подключения в signalR.

Мы также ведем журналы, и в среднем это происходит (клиент не получает ответный PING-запрос от сервера), может быть, один раз в день.

person smitra    schedule 29.04.2014