SignalR в ASP.NET Core 3.0 MVC соединение не работает? - PullRequest
2 голосов
/ 08 ноября 2019

Вопрос в предложении: остаются ли соединения SignalR открытыми через keep-alive, если да, то почему они не работают в .NET Core 3, и если нет, то для чего нужны настройки keep-alive?

У меня есть веб-приложение ASP.NET Core 3.0 MVC, и я просто добавил в него SignalR, следуя инструкции по началу работы, расположенной здесь: https://docs.microsoft.com/en-us/aspnet/core/tutorials/signalr?view=aspnetcore-3.0&tabs=visual-studio (за исключением создания нового веб-приложения, мы просто добавили его в нашевместо приложения)

У меня есть простой концентратор, и клиент успешно подключается, и если я проверяю метод SignalR сразу после установления соединения, он работает. Тем не менее, соединение закрывается, если я не использую его в течение 30 секунд. Если я понимаю документацию, значение keepalive по умолчанию составляет 15 секунд, но я не вижу сообщений keepalive. Я пробовал различные настройки для KeepAliveInterval и ClientTimeoutInterval, но ничего не решило это.

Я добавил .withAutomaticReconnect () к вызову HubConnectionBuilder в нашем javascript, и это работает для восстановления соединения после отключения каждый раз30 секунд. Это то, как это должно работать, или соединение должно поддерживаться эхо-запросами и должно быть переподключено только из-за пропадания сети и т. Д.? Я чувствую, что упускаю что-то простое или неправильно понимаю, как это должно работать.

Вот различные части нашего кода:

Startup.cs Метод ConfigureServices:

        services.AddSignalR(hubOptions =>
        {
            hubOptions.EnableDetailedErrors = true;
            //hubOptions.KeepAliveInterval = TimeSpan.FromSeconds(10);
            //hubOptions.ClientTimeoutInterval = TimeSpan.FromMinutes(1);
        });

Startup.cs Настроить метод:

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
            endpoints.MapRazorPages();
            endpoints.MapHub<QuoteHub>("/quoteHub");
        });

Наш QuoteHub:

public class QuoteHub : Hub
{
    public QuoteHub()
    {

    }

    public override Task OnConnectedAsync()
    {
        var quoteId = Context.GetHttpContext().Request.Query["quoteId"];

        return Groups.AddToGroupAsync(Context.ConnectionId, quoteId);
    }
}

и настройка соединения javascript:

const setupQuoteConnection = (quoteId) => {
    let connection = new signalR.HubConnectionBuilder()
    .withUrl("/quoteHub?quoteId=" + quoteId)
    .configureLogging(signalR.LogLevel.Debug)
    .withAutomaticReconnect()
    .build();

    connection.on("ReceiveUpdate", (update) => {
    alert(update);
    }
    );

    connection.start()
    .catch(err => console.error(err.toString()));
};

и, если быть точным, вызов концентратору для отправки обновления клиентам:

_quoteHub.Clients.Group(domainEvent.QuoteId.ToString()).SendAsync("ReceiveUpdate", domainEvent.TotalPrice);

Обновление

Я нашел образец чата, расположенный по адресу https://github.com/aspnet/SignalR-samples. Я скачал и запустил этот образец, и он отлично работает, соединение остается открытым, но на всю жизньЯ не могу понять, что заставляет его работать иначе, чем мое приложение.

Я заметил некоторые проблемы в моем концентраторе и исправил их, хотя это не имело никакого значения:

public class QuoteHub : Hub
{
    public override async Task OnConnectedAsync()
    {
        var quoteId = Context.GetHttpContext().Request.Query["quoteId"];

        await Groups.AddToGroupAsync(Context.ConnectionId, quoteId);

        await base.OnConnectedAsync();
    }
}

ТогдаЯ обновил свой код JavaScript, чтобы настроить соединение и увеличить время ожидания сервера. Это действительно работает , но зачем мне это нужно, если в приведенном выше примере связанного чата его нет и прекрасно работает без него?

    let connection = new signalR.HubConnectionBuilder()
    .withUrl("/quoteHub?quoteId=" + quoteId)
    .configureLogging(signalR.LogLevel.Debug)
    .withAutomaticReconnect()
    .build();

    connection.serverTimeoutInMilliseconds = 3600000; //1 hour

Ответы [ 2 ]

0 голосов
/ 12 ноября 2019

Похоже, мы определили виновника наших постоянных 30-секундных отключений.

Когда мы обновили наше приложение с ASP.NET Core 2.2 MVC до 3.0, мы тоже пошли олл-ин с перемещением System.Text.Json (от Newtonsoft.Json). Что ж, у этого был побочный эффект - сломался наш компонент Telerik Reporting, который все еще требует Newtonsoft.Json. Итак, мы вернулись к использованию Newtonsoft.Json в нашем приложении, но часть, которую мы пропустили, была найдена в https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.0&tabs=visual-studio#switch-to-newtonsoftjson

Ключевым битом было «связать вызов метода AddNewtonsoftJsonProtocol с вызовом метода AddSignalR в Startup.ConfigureServices. ":

services.AddSignalR()
.AddNewtonsoftJsonProtocol

Больше ничего не нужно было, чтобы все это" просто работало ". Если вы читаете это, пожалуйста, обратитесь к образцу чата, который я упомянул в обновлении в вопросе (https://github.com/aspnet/SignalR-samples). Простота в этом коде и то, как он работает, был знаком для меня, что что-то не так с тем, как мывидели постоянные отключения - красная сельдь, которая застала меня врасплох, заключалась в том, что наши сообщения SignalR все еще работали.

0 голосов
/ 10 ноября 2019

Я думаю, вам также может понадобиться добавить опции. Транспорт вроде этого

public void ConfigureServices(IServiceCollection services)
{
    services.AddSignalR(hubOptions =>
    {
        hubOptions.EnableDetailedErrors = true;
        hubOptions.KeepAliveInterval = TimeSpan.FromMinutes(1);
    });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHub<MyHub>("/myhub", options =>
        {
            options.Transports = HttpTransportType.LongPolling; // you may also need this
        });
    });
}
...