Мы столкнулись с интересной проблемой. Вот как выглядит наша установка:
- 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.