反模式:在一个 API 代理中多次调用 MessageLogging 政策

您正在查看的是 Apigee Edge 文档。
转到 Apigee X 文档
信息

Apigee Edge 的 MessageLogging 政策允许 API 代理开发者将自定义消息记录到 syslog 或磁盘(仅限 Edge for Private Cloud)。与 API 请求相关的所有重要信息(例如输入参数、请求载荷、响应代码、错误消息(如有)等)均可记录以供日后参考或用于调试。虽然此政策使用后台进程执行日志记录,但请务必注意使用政策。

反模式

MessageLogging 政策提供了一种高效的方式来获取有关 API 请求的详细信息和调试 API 请求遇到的任何问题。但是,如果使用同一个 MessageLogging 政策多次,或者在非 PostClientFlow 的流中的同一 API 代理中具有多个 MessageLogging 政策日志数据区块,则可能会产生不利影响。这是因为 Apigee Edge 会打开与外部 syslog 服务器的连接,以执行 MessageLogging 政策。如果此政策通过 TCP 使用 TLS,则建立 TLS 连接会产生额外的开销。

我们借助一个 API 代理示例来说明这一点。

API 代理

在以下示例中,名为“LogRequestInfo”的 MessageLogging 政策放在请求流,并将另一个名为“LogResponseInfo”的 MessageLogging 政策添加到响应流。两者均位于 ProxyEndpoint PreFlow 中。一旦 API 代理收到请求,LogRequestInfo 政策就会在后台执行,而 LogResponseInfo 政策会在代理收到目标服务器的响应之后代理将响应返回给 API 客户端之前执行。这会使用额外的系统资源,因为可能建立了两个 TLS 连接。

此外,还有一个名为“LogErrorInfo”的 MessageLogging 政策,仅当 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 连接的开销将占用额外的系统内存和 CPU 周期,从而导致大规模出现性能问题。

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 网关超时错误。
  • 在使用文件日志记录的 Private Cloud 设置中,增加了消息处理器打开的并发文件描述符数量。
  • 如果将 MessageLogging 政策放在 PostClient 流之外的流中,则可能不会记录信息,因为在执行此政策之前发生任何故障时都将不会执行 MessageLogging 政策。

    在之前的 ProxyEndpoint 示例中,在以下情况下系统不会记录信息:

    • 如果放在请求流中 LogRequestInfo 政策前面的任何政策都失败。
    • 如果目标服务器失败并显示任何错误(HTTP 4XX、5XX)。在这种情况下,未返回成功响应时,系统将不会执行 LogResponseInfo 政策。

    在这两种情况下,都会执行 LogErrorInfo 政策,并仅记录错误相关信息。

最佳做法

  • 使用 ExtractVariables 政策JavaScript 政策来设置要记录的所有流变量,以便使其可供 MessageLogging 政策使用。
  • 使用一个 MessageLogging 政策来记录 PostClientFlow 中的所有必需数据,该操作将无条件执行。
  • 使用 UDP 协议(此协议不要求保证将消息传递到 Syslog 服务器,并且不需要 TLS/SSL)。

MessageLogging 政策旨在与实际 API 功能(包括错误处理)分离。因此,在 PostClientFlow 中进行调用(在请求/响应处理之外)意味着,无论 API 失败与否,它始终都会记录数据。

以下是在 PostClientFlow 中调用 MessageLogging 政策的示例:

<?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 中不提供响应变量,因此请务必使用 ExtractVariables 或 JavaScript 政策显式设置 woeidweather.response* 变量。

更多详情