Руководство по устранению типичных неполадок для службы Azure SignalR

В этой статье приводятся рекомендации по устранению неполадок, связанных с некоторыми распространенными проблемами, с которыми могут столкнуться клиенты.

Слишком длинный маркер доступа

Возможные ошибки

  • ERR_CONNECTION_ на стороне клиента
  • 414 — слишком длинный универсальный код ресурса (URI)
  • 413 Полезные данные слишком велики
  • Длина маркера доступа не должна превышать 4 КБ. 413 — размер запрашиваемой сущности слишком большой

Основная причина

Для HTTP/2 максимальная длина одного заголовка составляет 4 K, поэтому при использовании браузера для доступа к службе Azure возникает ошибка ERR_CONNECTION_ для этого ограничения.

Для клиентов HTTP/1.1 или C# максимальная длина URI составляет 12 K , а максимальная длина заголовка составляет 16 K.

При использовании пакета SDK версии 1.0.6 или более поздней /negotiate возникает 413 Payload Too Large , когда созданный маркер доступа превышает 4 K.

Решение

По умолчанию утверждения из context.User.Claims включаются в состав маркера при создании маркера JWT доступа к ASRS(службе Azure SignalR Service), чтобы утверждения сохранялись и могли передаваться из ASRS в Hub при подключении клиента к Hub.

В некоторых случаях context.User.Claims используются для хранения большого количества сведений для сервера приложений, большинство из которых не используются Hubдругими компонентами.

Созданный маркер доступа передается по сети, и для подключений WebSocket/SSE маркеры доступа передаются через строки запросов. Поэтому рекомендуется передавать лишь необходимые утверждения от клиента через службу ASRS в сервер приложений, когда это необходимо для Центра.

Существует возможность ClaimsProvider настроить утверждения, которые передаются в ASRS внутри маркера доступа.

Для ASP.NET Core:

services.AddSignalR()
        .AddAzureSignalR(options =>
            {
                // pick up necessary claims
                options.ClaimsProvider = context => context.User.Claims.Where(...);
            });

Для ASP.NET:

services.MapAzureSignalR(GetType().FullName, options =>
            {
                // pick up necessary claims
                options.ClaimsProvider = context.Authentication?.User.Claims.Where(...);
            });

Наличие проблем или отзывов об устранении неполадок? Сообщите нам об этом.

Требуется TLS 1.2

Возможные ошибки

  • Ошибка ASP.NET "No server available" (Нет доступных серверов) #279
  • ASP.NET "Подключение не активно, данные не могут быть отправлены в службу". Ошибка #324
  • "An error occurred while making the HTTP request to https://<API endpoint> ("Произошла ошибка при выполнении HTTP-запроса к"). Эта ошибка может возникать, если сертификат сервера не настроен должным образом с HTTP.SYS в случае HTTPS. Возможная причина этой ошибки заключается в несоответствии привязки безопасности между клиентом и сервером".

Основная причина

Служба Azure из соображений безопасности поддерживает только TLS версии 1.2. В .NET Framework возможно, что TLS1.2 не является протоколом по умолчанию. В результате невозможно установить подключения сервера к ASRS.

Руководство по устранению неполадок

  1. Если эту ошибку можно воспроизвести локально, снимите флажок Только мой код, включите выдачу всех исключений CLR и отлаживайте сервер приложений локально, чтобы определить, какое исключение возникает.

    • Снимите флажок Только мой код

      Снимите флажок

    • Выдача исключений CLR

      Выдача исключений CLR

    • Просмотрите порождаемые исключения во время отладки кода серверной части приложения:

      Выдаваемые исключения

  2. Для приложений ASP.NET также можно добавить следующий код в Startup.cs, чтобы включить подробную трассировку и просмотреть ошибки в журнале.

    app.MapAzureSignalR(this.GetType().FullName);
    // Make sure this switch is called after MapAzureSignalR
    GlobalHost.TraceManager.Switch.Level = SourceLevels.Information;
    

Решение

Добавьте в запуск следующий код:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Наличие проблем или отзывов об устранении неполадок? Сообщите нам об этом.

400 Bad Request returned for client requests (Возврат ошибки с кодом 400 (Недопустимый запрос) для клиентских запросов)

Основная причина

Проверьте, нет ли в запросе клиента нескольких строк hub. Параметр hub запроса сохраняется, и если служба обнаруживает несколько hub в запросе, она возвращает ошибку 400.

Наличие проблем или отзывов об устранении неполадок? Сообщите нам об этом.

401 Unauthorized returned for client requests (Возврат ошибки с кодом "401 — не санкционировано" для клиентских запросов)

Основная причина

В настоящее время значение по умолчанию времени существования токена JWT составляет один (1) час.

Для ASP.NET Core SignalR при использовании типа транспорта WebSocket это нормально.

Для ASP.NET другого типа транспорта Core SignalR, SSE и длинного опроса по умолчанию по умолчанию подключение может сохраняться в течение одного часа.

Для ASP.NET SignalR клиент отправляет в службу запрос "оставаться в живых", когда /ping происходит сбой, клиент прерывает /ping подключение и никогда не будет повторно подключаться. Для ASP.NET SignalR время существования маркера по умолчанию длится не более одного часа для всех типов транспорта.

Решение

Для проблем безопасности расширение срока жизни не рекомендуется. Мы рекомендуем добавить в клиент логику повторного подключения, чтобы при получении такой ошибки 401 он возобновлял подключение. Когда клиент перезагрузит подключение, он согласовывает работу с сервером приложений, чтобы снова получить маркер JWT и получить обновленный маркер.

Ознакомьтесь с этим разделом, чтобы узнать, как устанавливать заново клиентские подключения.

Наличие проблем или отзывов об устранении неполадок? Сообщите нам об этом.

404 returned for client requests (Возврат ошибки с кодом 404 для клиентских запросов)

При постоянных подключениях к SignalR сначала выполняется /negotiate для службы Azure SignalR, а затем устанавливается реальное подключение к службе Azure SignalR.

Руководство по устранению неполадок

  • Выполните указания из раздела Как просмотреть исходящие запросы, чтобы получить запрос, отправляемый клиентом в службу.
  • Проверьте URL-адрес запроса, при котором возникает ошибка 404. Если URL-адрес указывает на ваше веб-приложение и выглядит подобно {your_web_app}/hubs/{hubName}, проверьте, не установлен ли на клиенте параметр SkipNegotiation в значение true. Клиент получает URL-адрес перенаправления при первом согласовании с сервером приложений. Клиент не должен пропускать переговоры при использовании Azure SignalR.
  • Еще 404 может произойти, когда запрос подключения обрабатывается более пяти (5) секунд после /negotiate вызова. Проверьте метку времени в запросе клиента и, если служба реагирует слишком медленно, сообщите о проблеме в нашу службу поддержки.

Наличие проблем или отзывов об устранении неполадок? Сообщите нам об этом.

В ASP.NET при запросе повторного подключения к SignalR возвращается ошибка 404

В SignalR для ASP.NET при разрыве клиентского подключения оно трижды восстанавливается с использованием того же connectionId, прежде чем попытки восстановить подключение прекращаются. /reconnect может помочь, если подключение нарушается из-за временных проблем в сети, при которых /reconnect все же может повторно установить стабильно работающее подключение. В других случаях, например, подключение клиента удаляется из-за удаления перенаправленного подключения к серверу или Служба SignalR имеет некоторые внутренние ошибки, такие как перезапуск экземпляра, отработка отказа или развертывание. Подключение больше не существует, поэтому /reconnect возвращается 404. Это ожидаемое поведение для /reconnect и после трехкратного повтора остановки подключения. Рекомендуем реализовать логику перезапуска подключения для случаев прекращения подключений.

Наличие проблем или отзывов об устранении неполадок? Сообщите нам об этом.

Возврат ошибки с кодом 429 (Слишком много запросов) для клиентских запросов

Есть два способа.

Количество одновременных подключений превысило максимальное

Для бесплатных экземпляров ограничение на количество одновременных подключений равно 20. Для стандартных экземпляров предел количества одновременных подключений составляет 1000 на единицу (unit), то есть Unit100 допускает 100 000 одновременных подключений.

В это количество подключений включаются как клиентские, так и серверные подключения. Ознакомьтесь со сведениями о том, как учитываются подключения.

СогласованиеThrottled

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

Наличие проблем или отзывов об устранении неполадок? Сообщите нам об этом.

Ошибка 500 при согласовании: служба Azure SignalR еще не подключена, повторите попытку позже

Основная причина

Эта ошибка сообщается, когда подключение к серверу не Служба Azure SignalR подключено.

Руководство по устранению неполадок

Включите трассировку на стороне сервера, чтобы получить подробные сведения об ошибке, возникающей при попытке сервера подключиться к службе Azure SignalR.

Включение ведения журналов на стороне сервера для ASP.NET Core SignalR

Ведение журналов на стороне сервера для ASP.NET Core SignalR интегрируется с ведением журналов на основе ILogger, реализованным в платформе ASP.NET Core. Включить ведение журналов на стороне сервера можно с помощью ConfigureLogging, как показано в примере ниже:

.ConfigureLogging((hostingContext, logging) =>
        {
            logging.AddConsole();
            logging.AddDebug();
        })

Категории средств ведения журнала для Azure SignalR всегда начинаются с Microsoft.Azure.SignalR. Чтобы включить подробные журналы из Azure SignalR, настройте предыдущие префиксы на Debug уровень в файле appsettings.json , см. в следующем примере:

{
    "Logging": {
        "LogLevel": {
            ...
            "Microsoft.Azure.SignalR": "Debug",
            ...
        }
    }
}

Включение трассировки на стороне сервера для ASP.NET SignalR

При использовании версии >ПАКЕТА SDK = 1.0.0можно включить трассировки, добавив в него следующие web.configзначения: (Сведения)

<system.diagnostics>
    <sources>
      <source name="Microsoft.Azure.SignalR" switchName="SignalRSwitch">
        <listeners>
          <add name="ASRS" />
        </listeners>
      </source>
    </sources>
    <!-- Sets the trace verbosity level -->
    <switches>
      <add name="SignalRSwitch" value="Information" />
    </switches>
    <!-- Specifies the trace writer for output -->
    <sharedListeners>
      <add name="ASRS" type="System.Diagnostics.TextWriterTraceListener" initializeData="asrs.log.txt" />
    </sharedListeners>
    <trace autoflush="true" />
  </system.diagnostics>

Наличие проблем или отзывов об устранении неполадок? Сообщите нам об этом.

Клиентское подключение прерывается

Когда клиент подключен к службе Azure SignalR, постоянное подключение между клиентом и службой Azure SignalR в некоторых случаях может разрываться по ряду причин. В этом разделе описывается несколько возможных ситуаций, ведущих к такому разрыву подключений, а также приводятся указания по выявлению их первопричины.

Возможные ошибки, отображаемые на стороне клиента

  • The remote party closed the WebSocket connection without completing the close handshake
  • Service timeout. 30000.00ms elapsed without receiving a message from service.
  • {"type":7,"error":"Connection closed with an error."}
  • {"type":7,"error":"Internal server error."}

Основная причина

Клиентские подключения могут разрываться в различных ситуациях:

  • При Hub возникновении исключений с входящим запросом
  • Когда подключение к серверу, к которому направляется клиент, удаляется, см. в следующем разделе, где подробно описано удаление подключения к серверу.
  • При возникновении проблемы с сетевым подключением между клиентом и Служба SignalR
  • Если Служба SignalR имеет некоторые внутренние ошибки, такие как перезапуск экземпляра, отработка отказа, развертывание и т. д.

Руководство по устранению неполадок

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

Наличие проблем или отзывов об устранении неполадок? Сообщите нам об этом.

Количество клиентских подключений постоянно растет

Неправильное использование клиентского подключения может вызвать его. Если их инициатор забывает останавливать клиент SignalR или освобождать его, то соединение будет оставаться открытым.

Возможные ошибки, видимые из метрик SignalR, которые находятся в разделе "Мониторинг" в меню ресурсов портал Azure

Число клиентских подключений в метриках службы Azure SignalR постоянно возрастает в течение длительного времени.

Количество клиентских подключений постоянно растет

Основная причина

Подключение DisposeAsync клиента SignalR никогда не вызывается, и подключение остается открытым.

Руководство по устранению неполадок

Проверьте, возможно, клиент SignalR никогда не закрывается.

Решение

Проверьте, производится ли закрытие подключений. Вызывайте HubConnection.DisposeAsync() вручную после использования подключения, чтобы прекратить его.

Например:

var connection = new HubConnectionBuilder()
	.WithUrl(...)
	.Build();
try
{
	await connection.StartAsync();
	// Do your stuff
	await connection.StopAsync();
}
finally
{
	await connection.DisposeAsync();
}

Распространенное неправильное использование клиентских подключений

Пример функции Azure

Эта проблема часто возникает, когда кто-то устанавливает клиентское подключение SignalR в методе функции Azure, а не делает его статическим членом в классе функций. Возможно, вы ожидаете, что будет установлено только одно клиентское подключение, но вместо этого количество подключений клиента постоянно увеличивается в метриках. Все эти подключения будут удаляться только после перезапуска службы Azure SignalR или функции Azure SignalR. Это происходит из-за того, что функция Azure устанавливает одно клиентское подключение для каждого запроса и если вы не останавливаете подключение клиента в методе функции, клиент сохраняет подключения к службе Azure SignalR.

Решение

Наличие проблем или отзывов об устранении неполадок? Сообщите нам об этом.

Подключение к серверу разрывается

Когда запускается сервер приложений, пакет SDK Azure начинает в фоновом режиме инициировать серверные подключения к удаленной службе Azure SignalR. Как описано в статье Internals of Azure SignalR Service (Внутренние компоненты службы Azure SignalR), служба Azure SignalR направляет входящий клиентский трафик в эти серверные подключения. При удалении подключения к серверу он закрывает все клиентские подключения, которые он обслуживал.

Так как подключения между сервером приложений и Служба SignalR являются постоянными подключениями, они могут столкнуться с проблемами с сетевым подключением. В пакете SDK сервера у нас есть стратегия Always Reconnect с подключениями к серверу. Рекомендуется также поощрять пользователей добавлять логику непрерывного повторного подключения к клиентам со случайным временем задержки, чтобы избежать массовых одновременных запросов к серверу.

Регулярно существуют новые выпуски версий для Служба Azure SignalR, а иногда и исправления на уровне Azure или обновления или иногда прерывания работы с зависимыми службами. Эти события могут привести к короткому периоду сбоя службы, но если на стороне клиента есть механизм отключения или повторного подключения, эффект минимальный, как и любой клиент, вызванный отключением повторного подключения.

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

Возможные ошибки, отображаемые на стороне сервера

  • [Error]Connection "..." to the service was dropped
  • The remote party closed the WebSocket connection without completing the close handshake
  • Service timeout. 30000.00ms elapsed without receiving a message from service.

Основная причина

Подключение на стороне сервера закрыто службой ASRS(Azure SignalR Service).

Высокая загрузка ЦП или нехватка пула потоков на стороне сервера может привести к истечении времени ожидания пинга.

В ASP.NET SignalR существовала известная проблема, которая была исправлена в версии 1.6.0 пакета SDK. Обновите используемый пакет SDK до новейшей доступной версии.

Исчерпание пула потоков

Если на сервере возникла нехватка потоков, то потоки не смогут производить обработку сообщений. Все потоки не отвечают в определенном методе.

Как правило, в асинхронных методах асинхронная синхронизация или в Task.Result/Task.Wait() результате этого сценария.

См. Рекомендации по повышению производительности ASP.NET Core.

См. дополнительные сведения об исчерпании пула потоков.

Как определить исчерпание пула потоков

Проверьте количество потоков. Если пиковых количеств в текущее время не наблюдается, выполните следующие действия:

  • Если используется Служба приложений Azure, проверьте счетчик потоков в метриках. Проверьте агрегат Max:

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

  • Если используется платформа .NET framework, метрики можно найти в системном мониторе для виртуальной машины сервера.

  • Если применяется .NET Core в контейнере, см. статью Сбор диагностических сведений в контейнерах.

Также можно обнаруживать исчерпание пула потоков с помощью кода:

public class ThreadPoolStarvationDetector : EventListener
{
    private const int EventIdForThreadPoolWorkerThreadAdjustmentAdjustment = 55;
    private const uint ReasonForStarvation = 6;

    private readonly ILogger<ThreadPoolStarvationDetector> _logger;

    public ThreadPoolStarvationDetector(ILogger<ThreadPoolStarvationDetector> logger)
    {
        _logger = logger;
    }

    protected override void OnEventSourceCreated(EventSource eventSource)
    {
        if (eventSource.Name == "Microsoft-Windows-DotNETRuntime")
        {
            EnableEvents(eventSource, EventLevel.Informational, EventKeywords.All);
        }
    }

    protected override void OnEventWritten(EventWrittenEventArgs eventData)
    {
        // See: https://video2.skills-academy.com/dotnet/framework/performance/thread-pool-etw-events#threadpoolworkerthreadadjustmentadjustment
        if (eventData.EventId == EventIdForThreadPoolWorkerThreadAdjustmentAdjustment &&
            eventData.Payload[2] as uint? == ReasonForStarvation)
        {
            _logger.LogWarning("Thread pool starvation detected!");
        }
    }
}

Добавьте этот код в вашу службу:

service.AddSingleton<ThreadPoolStarvationDetector>();

Затем проверьте журнал при отключении сервера из-за времени ожидания связи.

Как определить первопричину исчерпания пула потоков

Чтобы определить первопричину исчерпания пула потоков, выполните следующие действия.

  • Создайте дамп памяти, затем проанализируйте стек вызовов. Дополнительные сведения см. в разделе Сбор и анализ дампов памяти.
  • Используйте библиотеку clrmd для создания дампа памяти при обнаружении исчерпания пула потоков. Затем выведите стек вызовов в журнал.

Руководство по устранению неполадок

  1. Откройте журнал на стороне сервера приложений, чтобы проверить, не происходит ли что-то непредвиденное.
  2. Просмотрите журнал событий на стороне сервера приложений и проверьте, не перезапускался ли сервер приложений.
  3. Создайте проблему. Укажите в обращении время появления неполадки и имя ресурса, и отправьте его нам по электронной почте.

Наличие проблем или отзывов об устранении неполадок? Сообщите нам об этом.

Советы

Как просмотреть исходящий запрос от клиента?

Например, при использовании ASP.NET Core (для ASP.NET это делается сходным образом):

  • Из браузера. При использовании, например, браузера Chrome можно с помощью клавиши F12 открыть окно консоли и перейти на вкладку Network (Сеть). Возможно, потребуется обновить страницу, нажав клавишу F5, чтобы зафиксировать обмен данными с самого начала.

    Представление Network (

  • Из клиента C#:

    Локальный веб-трафик можно просматривать с помощью Fiddler. Fiddler поддерживает трафик WebSocket, начиная с версии 4.5.

    Представление обмена по сети в Fiddler

Как перезапустить клиентское подключение?

Ниже приведены примеры кода, которые содержат логику перезапуска подключений со стратегией ALWAYS RETRY (всегда повторять):

Наличие проблем или отзывов об устранении неполадок? Сообщите нам об этом.

Следующие шаги

Из этого руководства вы узнали, как справляться с распространенными проблемами. Вы также можете ознакомиться с общими методиками устранения неполадок.