Мы создали инфраструктуру для наших фоновых демонов, чтобы помочь им вести себя согласованно, и поэтому нам не нужно постоянно переписывать один и тот же код.
И, конечно, десять лет спустя мы создали новое.
Одним из приложений в старой структуре является приложение сигнализации SignalR. Он размещает экземпляр SignalR в Microsoft Owin, а затем периодически проверяет базу данных на наличие всего необходимого для pu sh, затем обращается к веб-сайту SignalR, который затем использует настроенную объединительную панель для связи с другими запущенными веб-серверами, что затем отправим sh различным веб-клиентам.
Вроде запутанно, но это работает.
И теперь моя работа - переместить его в новую среду фонового приложения, и я ' я получаю ошибки HTTP 500 при попытке запустить веб-приложение.
Код в новом демоне почти такой же, как и в старом приложении, и я не могу понять, почему он работает в этом и не в другом.
Способ работы обеих сред состоит в том, что у каждого демона есть функция doWork (), которая вызывается неоднократно. В старом приложении была занята / wait l oop, которая вызывала бы doWork (). В новом приложении doWork () вызывается из System.Timers.Timer ElapsedEventHandler.
Мы определили класс для переноса экземпляра SignalR:
public class SignalRWebApp : IDisposable
{
public readonly string signalRUrl;
private IDisposable webApp;
public SignalRWebApp()
{
this.signalRUrl = String.Format("http://localhost:{0}", getFreePort());
this.webApp = null;
}
private static int getFreePort()
{
var listener = new TcpListener(IPAddress.Loopback, 0);
listener.Start();
var port = ((IPEndPoint) listener.LocalEndpoint).Port;
listener.Stop();
return port;
}
public bool started { get { return this.webApp != null; } }
public void start(string signalRBackplaneConnectionString)
{
if (this.webApp != null)
return;
Action<IAppBuilder> startAction = app =>
{
app.UseCors(CorsOptions.AllowAll);
GlobalHost.DependencyResolver.UseSqlServer(signalRBackplaneConnectionString);
app.MapSignalR();
};
this.webApp = WebApp.Start(this.signalRUrl, startAction);
}
#region IDisposable
[...]
#endregion
}
Мы храним экземпляр этого в элементе stati c, так что функция work () может получить к нему доступ:
public class Utils
{
public static SignalRWebApp signalRWebApp;
}
И затем мы заключаем наш код запуска в использование (), чтобы он существовал, пока приложение работает. Обратите внимание - если вы посмотрите на класс SignalRWebApp выше, вы заметите, что он на самом деле ничего не делает, пока не запустится.
using (Utils.signalRWebApp = new SignalRWebApp())
{
// initialize and run the background app
// (this will repeatedly call work() until shutdown is requested)
}
Затем наша рабочая функция запускается запуском SignalRWebApp, если она еще не запущен:
public class JobLockDaemon
{
private string signalRUrl;
private IHubProxy ticketLockSignalRHubProxy;
private HubConnection signalRConnection;
public JobLockDaemon()
{
this.checkedSnapshot = false;
this.signalRUrl = null;
this.ticketLockSignalRHubProxy = null;
this.signalRConnection = null;
}
public void doWork()
{
this.connectToSignalR();
// go ahead and do something
}
private void connectToSignalR()
{
if (this.signalRUrl == null)
{
if (!Utils.signalRWebApp.started)
{
Utils.signalRWebApp
.start(this.signalRBackplaneConnectionString());
}
this.signalRUrl = Utils.signalRWebApp.signalRUrl;
}
if (this.ticketLockSignalRHubProxy == null)
{
this.signalRConnection = new HubConnection(this.signalRUrl);
this.ticketLockSignalRHubProxy = this.signalRConnection.CreateHubProxy("TicketLockSignalRHub");
this.signalRConnection.Start().Wait();
}
}
}
И все работает, в старой платформе Daemon. Но в новом я получаю исключение this.signalRConnection.Start ():
System.AggregateException
Message "One or more errors occurred." string
InnerException {
"StatusCode: 500,
ReasonPhrase: 'Internal Server Error',
Version: 1.1,
Content: System.Net.Http.StreamContent,
Headers:
{
Date: Mon, 30 Mar 2020 16:29:27 GMT
Server: Microsoft-HTTPAPI/2.0
Content-Length: 0
}"
}
System.Exception {
Microsoft.AspNet.SignalR.Client.HttpClientException
}
Итак, вопрос в том, куда мне go посмотреть, чтобы выяснить, почему сервер SignalR выбрасывает 500 ?
И почему это работает в старой платформе, а не в новой?
Единственное структурное различие, которое я вижу, состоит в том, что в новой платформе вызывается метод Start () от таймера истекшего событияHandler. Может ли это иметь значение?
FWIW: Я попытался инициализировать трассировку сигнала в соответствии с инструкциями здесь:
https://docs.microsoft.com/en-us/aspnet/signalr/overview/testing-and-debugging/enabling-signalr-tracing
Используя старый работающий фреймворк, я вижу:
SignalR.SqlMessageBus Информация: 0: Установленные объекты SignalR SQL SignalR.SqlMessageBus Verbose: 0: Создано DbCommand: CommandType = Text, CommandText = SELECT [PayloadId] FROM [SignalR]. [Messages_0_Id], Parameters = SignalR.ScaleoutMessageBus Информация: 0: Stream (0) - измененное состояние с исходного на открытое SignalR.SqlMessageBus Verbose: 0: поток 0: SqlReceiver запущен, начальный идентификатор полезной нагрузки = 4188906 SignalR.SqlMessageBus Verbose: 0: Поток 0: выполнение считывателя получения, параметр начального идентификатора полезной нагрузки = 4188906
SignalR.SqlMessageBus Verbose: 0: Поток 0: запуск SQL приемник уведомлений SignalR.SqlMessageBus Verbose: 0: Поток 0: SQL прослушиватель уведомлений запущен
Использование новой инфраструктуры, которая не:
* 10 53 *
SignalR.SqlMessageBus Информация: 0: объекты SignalR SQL установлены SignalR.SqlMessageBus Подробно: 0: создано DbCommand: CommandType = Text, CommandText = SELECT [PayloadId] FROM [SignalR]. [Messages_0_Id], параметры .ScaleoutMessageBus Информация: 0: Stream (0) - измененное состояние с Начального на Открытое. SignalR.SqlMessageBus. Подробно: 0: Поток 0: SqlReceiver запущен, начальный идентификатор полезной нагрузки = 4188977 SignalR.SqlMessageBus. Подробный: 0: Поток 0: выполнение считывающего устройства, начальное. Параметр полезной нагрузки = 4188977
SignalR.SqlMessageBus Подробный: 0: Поток 0: Запуск SQL прослушивателя уведомлений
Другими словами, в новом фреймворке мы видим «Запуск SQL слушателя уведомлений», но мы никогда не видим «SQL слушатель уведомлений запущен».
Есть идеи, почему он не запускается?
Или где я могу посмотреть, почему он не запускается?