Производительность в узле MSAL

Необходимые условия

  • См. статью Производительность в MSAL Browser, в которой описаны методы, которые приложение может использовать для повышения производительности при получении токенов с помощью MSAL.
  • Node.js

Показатель производительности

Приложения, которые хотят измерять производительность потоков проверки подлинности в MSAL Node, могут сделать это вручную, используя API-интерфейсы измерения производительности узла или аналогичные. Ниже приведен список некоторых важных точек данных, которые можно собирать:

Данные Значение Suggestions
authType acquireToken* API, используемый для запроса токена Используется для идентификации использования.
correlationId Идентификатор корреляции, используемый для запроса токена. Это можно получить с помощью correlationId свойства в AuthenticationResult Используется для идентификации использования.
durationTotalInMs Общее время, затраченное на MSAL, включая сетевые вызовы и доступ к кэшу Предупреждение о высокой общей задержке (> 1 секунду). Значение зависит от источника маркера. Из кэша: одно обращение к кэшу. Из сети: два доступа к кэшу плюс два HTTP-вызова.
durationInCacheInMs Время, затраченное на загрузку или сохранение кэша токенов в постоянном хранилище (например, Redis). Сигнал тревоги при всплесках.
durationInHttpInMs Время, затраченное на выполнение HTTP-вызовов к idP (например, Microsoft Entra ID). Для более точного мониторинга можно использовать пользовательский сетевой клиент. Дополнительные сведения см. в разделе "Конфигурация " и "Пример пользовательской сети " Сигнал тревоги при всплесках.
tokenSource Источник маркера (т. е. кэш и сеть). Это можно получить с помощью fromCache свойства в AuthenticationResult Токены извлекаются из кэша значительно быстрее (например, ~100 мс по сравнению с ~700 мс). Можно использовать для мониторинга коэффициента попаданий в кэш и настройки оповещений. Используйте вместе с durationTotalInMs.

Рассмотрим пример.

    const { PerformanceObserver, performance } = require('node:perf_hooks');

    const perfObserver = new PerformanceObserver((items) => {
        items.getEntries().forEach((entry) => {
            console.log(entry);
        })
    });

    perfObserver.observe({ entryTypes: ["measure"], buffered: true });

    // ...

    performance.mark("acquireTokenByClientCredential-start");

    const tokenResponse = await msalInstance.acquireTokenByClientCredential({
        scopes: ["User.Read.All"],
    });

    performance.mark("acquireTokenByClientCredential-end");

    performance.measure("acquireTokenByClientCredential", {
        start: "acquireTokenByClientCredential-start"
        end: "acquireTokenByClientCredential-end"
        detail: {
            tokenSource: tokenResponse.fromCache
            correlationId: tokenResponse.correlationId
        }
    });

Рекомендации по производительности для конфиденциальных клиентских приложений

Так как конфиденциальные клиентские приложения в основном используются с сценариями на стороне сервера, связанными с параллельной обработкой запросов, рекомендуется ограничить экземпляры MSAL ConfidenticalClientApplication (CCA) для каждого пользователя, запроса или сеанса.

Новый экземпляр CCA для каждого запроса означает, что его кэш по умолчанию в памяти изначально не будет содержать никаких маркеров или метаданных о том, как получить маркеры. Таким образом, создаваемый экземпляр CCA необходимо подготовить перед запросом токена во избежание снижения производительности.

import {
    ConfidentialClientApplication,
    AuthenticationResult,
    CryptoProvider,
    OnBehalfOfRequest
} from "@azure/msal-node";

function getMsalInstance(partitionKey: string): ConfidentialClientApplication {
    return new ConfidentialClientApplication({
        auth: {
            clientId: "ENTER_CLIENT_ID",
            authority: "http://login.microsoftonline.com/ENTER_TENANT_ID"
            cloudDiscoveryMetadata: "PROVIDE_STRINGIFIED_DISCOVERY_METADATA"
            authorityMetadata: "PROVIDE_STRINGIFIED_AUTHORITY_METADATA"
        },
        cache: {
            cachePlugin: new CustomCachePlugin(
                this.cacheClientWrapper,
                partitionKey
            )
        }
    });
};

async function getToken(tokenRequest: OnBehalfOfRequest): Promise<AuthenticationResult | null> {
    const partitionKey = await this.cryptoProvider.hashString(tokenRequest.oboAssertion);

    const cca = getMsalInstance(partitionKey);

    let tokenResponse = null;

    try {
        await cca.getTokenCache().getAllAccounts(); // required for cache read
        tokenResponse = await cca.acquireTokenOnBehalfOf(tokenRequest);
    } catch (error) {
        throw error;
    }

    return tokenResponse;
};

Дополнительные сведения см. в статье Веб-API (CCA) с использованием настраиваемого подключаемого модуля распределенного кэша.

См. также