2014-05-18 1 views
1

Когда мое приложение сбрасывается, signalR отключается, но не восстанавливается.SignalR отключает и не подключается

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

// inside action executed on every completion of a task 
var h = new ForceHub(); 
h.MessageSent(email); 

выше коды прекращает отправку уведомлений, когда применение получает сброс (я могу эмулировать эту проблему путем прикосновения web.config).

Мне нужен способ подключения к клиенту. В настоящее время пользователь должен перезагрузить страницу для получения обновлений.

Вот мое определение ступица

public class ForceHub : Hub 
{ 
    public void MessageSent(string text) 
    { 
     GetContext().Clients.All.sent(text); 
    } 

    public void UpdateStatus(string msg) 
    { 
     GetContext().Clients.All.status(msg); 
    } 

    IHubContext GetContext() 
    { 
     return GlobalHost.ConnectionManager.GetHubContext<ForceHub>(); 
    } 
    public override Task OnConnected() 
    { 
     try { 
      IoC.Resolve<ILogger>().Info("SignalR Connected -----------"); 
     }catch (Exception){} 

     return base.OnConnected(); 
    } 

    public override Task OnDisconnected() 
    { 
     try { 
      IoC.Resolve<ILogger>().Info("SignalR Disconnected -----------"); 
     } 
     catch (Exception) { } 
     return base.OnDisconnected(); 
    } 

    public override Task OnReconnected() 
    { 
     try { 
      IoC.Resolve<ILogger>().Info("SignalR Re-Connected -----------"); 
     } 
     catch (Exception) { } 
     return base.OnReconnected(); 
    } 
} 

Я могу видеть Connected и Connected Re- событий запускается после запуска, однако после касания web.config, я не вижу какой-либо из этих событий, запускаемых ,

я пытался поймать это на клиенте, но это событие не tirggered:

$.connection.hub.disconnected(function() { 
    console.error('signalR disconnected, retrying connection'); 
    logError('Signal lost.'); 
    setTimeout(function() { connection.start(); }, 1000); 
}); 

обновление

я зацепил в Государственный Changed событие, которое действительно становится срабатывает, но в ПЕРЕУСТАНОВКИ попытка подключения ниже не работает.

 $.connection.hub.stateChanged(function (state) { 
      console.debug('signalR state changed', state); 
      if (state.newState == 1) { 
       console.debug('restarting'); 
       setTimeout(function() { $.connection.hub.start(); }, 1000); 
      } 
     }); 

это событие сработало дважды: NewState является 2, а затем 1.

+0

Это выглядело как интересный случай, и я попытался Репрографическим, но я был не в состоянии. Я не пытался выполнять длительные задачи, но с простой дополнительной страницей, чей код позади отправляет сообщение всем клиентам при попадании в GET. Это моделирует «внеполосное» задание, и оно нормально работает даже после сброса приложения, клиенты получают уведомление в обычном режиме. Я бы сказал, что SignalR не потеряет соединение (поэтому вы не видите события) ... Может быть, проблема в другом месте? – Wasp

+0

@Wasp Вы пытались изменить web.config? –

+0

Несомненно, я делал это между запросами на мою страницу «job» – Wasp

ответ

0

я мог бы иметь ключ ... Касание Web.config производит AppPool Перезапустить, а это означает, что новый рабочий процесс будет создаваться для новых запросов, в то время как существующий процесс будет продолжаться некоторое время, пока оставшиеся запросы не будут завершены или не будет достигнут тайм-аут. Запрос, который не заканчивается в период ожидания, прекращается.

Signalr клиент подключится к новому процессу в то время как долго работает задача выполняется в старом процессе, поэтому, когда на длинной выполняющейся задаче вы

GlobalHost.ConnectionManager.GetHubContext<ForceHub>(); 

вы на самом деле получить ссылку на «старый» хаб время клиент подключается к «новому» концентратору. Именно поэтому тест, подготовленный Wasp, работал: он делал новый запрос на публикацию в концентраторе signalr, который был обработан во вновь созданном рабочем процессе.

Вы можете попробовать настроить объединительную плату singalr (https://www.asp.net/signalr/overview/performance/scaleout-in-signalr), ее очень легко настроить с помощью Sql Server (https://www.asp.net/signalr/overview/performance/scaleout-with-sql-server). Объединительная плата должна быть способна подключать два рабочих процесса, и, надеюсь, вы получите уведомление на клиенте.

Если это проблема, уведомления, генерируемые новыми запросами, будут работать даже без объединительной платы. Обратите внимание, что реальная цель объединительной платы состоит в том, чтобы масштабировать signalr, то есть подключать ферму WebServers между ними.

Также имейте в виду, что выполнение многолетней задачи внутри IIS является задачей, которую трудно достичь, поскольку, помимо прочего, IIS регулярно перерабатывает утилиту appPool и имеет ограничения времени ожидания для выполнения запросов.Я рекомендую прочитать следующую запись: http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx «Если вы считаете, что можете просто написать фоновое задание самостоятельно, скорее всего, вы ошибетесь. Я не навязываю вам свои навыки, я просто говорю, что это тонко. Кроме того, почему вы должны были?»

Надеется, что это помогает

+0

, который звучит о правильном :) не коснулся этого кода годами. Я согласен с тем, что длительные задачи в IIS не идеальны. я смог довести диапазон выполнения до 1-30 минут, который все еще длинный, но был управляемым в течение последних нескольких лет. благодаря! –