Antipattern:在 API Proxy 中多次叫用 MessageLogging 政策

您正在查看 ApigeeApigee Hybrid 說明文件。
查看 Apigee Edge 說明文件。

Apigee 的MessageLogging 政策可讓 API Proxy 開發人員將自訂訊息記錄到 Cloud Logging 或 syslog 端點。您可以記錄任何與 API 要求相關的重要資訊,例如輸入參數、要求酬載、回應碼、錯誤訊息 (如有) 等等,以供日後參考或偵錯。雖然這項政策會使用背景程序執行記錄功能,但使用這項政策時仍有注意事項。

反模式

MessageLogging 政策可讓您有效率地取得 API 要求的更多資訊,並對 API 要求遇到的任何問題進行偵錯。不過,如果在 PostClientFlow 以外的流程中使用相同的 MessageLogging 政策超過一次,或是有多個 MessageLogging 政策在同一個 API 代理程式中以區塊記錄資料,可能會產生不良影響。這是因為 Apigee 會為 MessageLogging 政策開啟至外部端點的連線。如果政策使用 TCP 上的 TLS,就像 syslog 端點一樣,就會產生額外的建立 TLS 連線的額外負擔。

讓我們透過範例 API Proxy 加以說明。

API Proxy

在以下範例中,名為「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>

訊息記錄政策

在下列政策設定範例中,系統會透過 TCP 和 TLS 將資料記錄到第三方記錄伺服器。如果在同一個 API 代理程式中使用多項這類政策,建立及管理 TLS 連線的額外負擔會佔用更多系統記憶體和 CPU 週期,導致大規模的效能問題。如果使用 MessageLogging 將記錄記錄至 Cloud Logging 端點,也會發生類似的負面影響。

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 Proxy 流程中多次建立記錄端點連線,導致網路作業負擔增加。
  • 如果 syslog 伺服器速度緩慢,或無法處理多個 syslog 呼叫所造成的大量資料,就會對訊息處理器造成回壓,導致處理要求速度緩慢,並可能導致延遲時間過長或發生 504 閘道逾時錯誤。
  • 如果 MessageLogging 政策放在 PostClient 流程以外的流程中,可能就不會記錄資訊,因為如果在執行這項政策前發生任何錯誤,系統就不會執行 MessageLogging 政策。

    在先前的 ProxyEndpoint 範例中,在下列情況下系統不會記錄資訊:

    • 如果在要求流程中,LogRequestInfo 政策前方的任何政策都失敗。
    • 如果目標伺服器發生任何錯誤 (HTTP 4XX、5XX),在這種情況下,如果未傳回成功的回應,LogResponseInfo 政策就不會執行。

    無論是哪種情況,系統都會執行 LogErrorInfo 政策,並只記錄與錯誤相關的資訊。

最佳做法

  • 在 Proxy 流程中,使用一或多個 ExtractVariables 政策JavaScript 政策,設定要記錄至內容變數的所有流程變數,以便供稍後執行的 MessageLogging 政策使用。
  • 使用單一 MessageLogging 政策,在 PostClientFlow 中記錄所有必要資料,而 PostClientFlow 會無條件執行。
  • 如果您使用 syslog,請在不需要保證將訊息傳送至 syslog 伺服器,且不強制使用 TLS/SSL 時,使用 UDP 通訊協定。

MessageLogging 政策的設計目的是與實際的 API 功能 (包括錯誤處理) 脫鉤。因此,在 PostClientFlow 中叫用此函式 (位於要求/回應處理之外) 表示無論 API 是否成功,都會一律記錄資料。

以下是 PostClientFlow 中叫用 MessageLogging Policy 的範例:

<?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* 變數。

延伸閱讀