Антипаттерн: многократный вызов правила MessageLogging в прокси API

Вы просматриваете документацию по Apigee Edge.
Перейдите к документации по Apigee X.
Информация

Правило MessageLogging в Apigee Edge позволяет разработчикам прокси API регистрировать пользовательские сообщения в syslog или на диске (только в Edge для частного облака). Любая важная информация, связанная с запросом к API, например входные параметры, полезная нагрузка запроса, код ответа, сообщения об ошибках (если есть) и т. д., может быть зарегистрирована для дальнейшего использования или отладки. Хотя для ведения журнала в правиле используется фоновый процесс, при его использовании следует учитывать некоторые нюансы.

Антипаттерн

Правила MessageLogging позволяют эффективно получать больше информации о запросе к API и устранять проблемы, связанные с ним. Однако если использовать одно и то же правило MessageLogging несколько раз или если несколько правил MessageLogging регистрируют данные фрагментами в одном и том же прокси-сервере API в потоках, отличных от PostClientFlow, это может привести к нежелательным последствиям. Это связано с тем, что Apigee Edge открывает подключение к внешнему серверу syslog для правила MessageLogging. Если в правиле используется TLS через TCP, то возникают дополнительные издержки на установление TLS-подключения.

Рассмотрим это на примере прокси API.

прокси-сервер API

В следующем примере правило MessageLogging с названием LogRequestInfo размещено в потоке запроса, а другое правило MessageLogging с названием LogResponseInfo добавлено в поток ответа. Оба они находятся в PreFlow ProxyEndpoint. Правило LogRequestInfo выполняется в фоновом режиме, как только прокси-сервер API получает запрос, а правило LogResponseInfo выполняется после того, как прокси-сервер получает ответ от целевого сервера, но до того, как прокси-сервер возвращает ответ API-клиенту. Это приведет к дополнительному расходу системных ресурсов, поскольку может быть установлено два TLS-подключения.

Кроме того, существует правило MessageLogging с названием LogErrorInfo, которое выполняется только в том случае, если во время выполнения прокси-сервера API возникает ошибка.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndpoint name="default">
  ...
<FaultRules>
    <FaultRule name="fault-logging">
        <Step>
            <Name>LogErrorInfo</Name>
        </Step>
    </FaultRule>
</FaultRules>
<PreFlow name="PreFlow">
    <Request>
      <Step>
        <Name>LogRequestInfo</Name>
      </Step>
    </Request>
  </PreFlow>
  <PreFlow name="PreFlow">
    <Response>
      <Step>
        <Name>LogResponseInfo</Name>
      </Step>
    </Response>
  </PreFlow>
  ...
</ProxyEndpoint>

Правила ведения журналов сообщений

В приведенных ниже примерах конфигураций правил данные регистрируются на сторонних серверах журналов с использованием TLS через TCP. Если в одном прокси-сервере API используется несколько таких правил, издержки на установление и управление TLS-подключениями будут занимать дополнительную системную память и циклы ЦП, что приведет к проблемам с производительностью при масштабировании.

Правило LogRequestInfo

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MessageLogging name="LogRequestInfo">
  <Syslog>
    <Message>[3f509b58 tag="{organization.name}.{apiproxy.name}.{environment.name}"] Weather request for WOEID {request.queryparam.w}.</Message>
    <Host>logs-01.loggly.com</Host>
    <Port>6514</Port>
    <Protocol>TCP</Protocol>
    <FormatMessage>true</FormatMessage>
    <SSLInfo>
        <Enabled>true</Enabled>
    </SSLInfo>
  </Syslog>
  <logLevel>INFO</logLevel>
</MessageLogging>

Правила LogResponseInfo

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MessageLogging name="LogResponseInfo">
  <Syslog>
    <Message>[3f509b58 tag="{organization.name}.{apiproxy.name}.{environment.name}"] Status: {response.status.code}, Response {response.content}.</Message>
    <Host>logs-01.loggly.com</Host>
    <Port>6514</Port>
    <Protocol>TCP</Protocol>
    <FormatMessage>true</FormatMessage>
    <SSLInfo>
        <Enabled>true</Enabled>
    </SSLInfo>
  </Syslog>
  <logLevel>INFO</logLevel>
</MessageLogging>

Правило LogErrorInfo

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MessageLogging name="LogErrorInfo">
  <Syslog>
    <Message>[3f509b58 tag="{organization.name}.{apiproxy.name}.{environment.name}"] Fault name: {fault.name}.</Message>
    <Host>logs-01.loggly.com</Host>
    <Port>6514</Port>
    <Protocol>TCP</Protocol>
    <FormatMessage>true</FormatMessage>
    <SSLInfo>
        <Enabled>true</Enabled>
    </SSLInfo>
  </Syslog>
  <logLevel>ERROR</logLevel>
</MessageLogging>

Результат

  • Увеличение сетевых издержек из-за установления подключений к серверам журналов несколько раз во время работы прокси API.
  • Если сервер syslog работает медленно или не может справиться с большим объемом данных, вызванным многочисленными вызовами syslog, это приведет к обратному давлению на процессор сообщений, в результате чего обработка запросов будет выполняться медленно и может возникнуть высокая задержка или ошибка 504 Gateway Timeout.
  • Увеличенное количество дескрипторов файлов, одновременно открытых процессором сообщений в частном облаке, где используется ведение журнала файлов.
  • Если правило MessageLogging размещено в потоках, отличных от PostClient, существует вероятность того, что информация не будет зарегистрирована, поскольку правило MessageLogging не будет выполнено, если до его выполнения произойдет сбой.

    В примере ProxyEndpoint выше информация не будет регистрироваться в следующих случаях:

    • Если какое-либо из правил, расположенных в потоке запросов перед правилом LogRequestInfo, не выполняется.
      или
    • Если целевой сервер выдает ошибку (HTTP 4XX, 5XX). В этом случае, если успешный ответ не возвращается, правило LogResponseInfo не выполняется.

    В обоих случаях будет выполнено правило LogErrorInfo, и в журнал будет записана только информация, связанная с ошибкой.

Совет

  • Используйте правило ExtractVariables или правило JavaScript, чтобы задать все переменные потока, которые нужно регистрировать, и сделать их доступными для правила MessageLogging.
  • Используйте одно правило MessageLogging, чтобы регистрировать все необходимые данные в PostClientFlow, который выполняется безусловно.
  • Используйте протокол UDP, если гарантированная доставка сообщений на сервер syslog не требуется и TLS/SSL не обязательны.

Правило MessageLogging было разработано так, чтобы не зависеть от фактической функциональности API, в том числе от обработки ошибок. Поэтому при вызове в PostClientFlow, который находится вне обработки запроса/ответа, данные будут регистрироваться всегда, независимо от того, произошла ли ошибка в API.

Ниже приведен пример использования правила MessageLogging в PostClientFlow:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 ...
<PostClientFlow>
        <Request/>
        <Response>
            <Step>
                <Name>LogInfo</Name>
            </Step>
        </Response>
</PostClientFlow>
 ...

Ниже приведен пример правила MessageLogging, LogInfo, которое регистрирует все данные:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MessageLogging name="LogInfo">
  <Syslog>
    <Message>[3f509b58 tag="{organization.name}.{apiproxy.name}.{environment.name}"] Weather request for WOEID {woeid} Status: {weather.response.code}, Response {weather.response}, Fault: {fault.name:None}.</Message>
    <Host>logs-01.loggly.com</Host>
    <Port>6514</Port>
    <Protocol>TCP</Protocol>
    <FormatMessage>true</FormatMessage>
    <SSLInfo>
        <Enabled>true</Enabled>
    </SSLInfo>
  </Syslog>
  <logLevel>INFO</logLevel>
</MessageLogging>

Поскольку переменные ответа недоступны в PostClientFlow после Error Flow, важно явно задать переменные woeid и weather.response* с помощью правил ExtractVariables или JavaScript.

Дополнительные материалы