【问题标题】:Azure APIM Policy to failover primary backend URL to secondary in case of a time outAzure APIM 策略在超时的情况下将主要后端 URL 故障转移到辅助
【发布时间】:2020-02-26 05:28:13
【问题描述】:

我的要求很简单。我有一个 APIM 端点,它调用具有预定义超时的后端 HTTP 服务。如果请求超时或返回“错误请求”以外的错误(Status Code > 400),则需要使用故障转移 HTTP 服务重试调用,直到成功或最大 5 次。我正在尝试使用 APIM 策略来完成此操作。虽然如果返回的状态代码高于 400,则重试和故障转移有效,但如果请求只是超时,则不会发生。如果请求只是超时,控件甚至不会进入 <retry>块。我相当确定我输入的重试条件无法捕获超时条件。有人可以帮我找出用于记录超时的 APIM 策略吗?

以下是 APIM 政策。

<policies>
    <inbound>
        <base />
        <set-variable name="isFlag" value="true" />
    </inbound>
    <backend>
        <choose>
            <when condition="@(context.Variables.GetValueOrDefault<string>("isFlag") == "true")">
                <set-backend-service base-url="<primary url>" />
                <forward-request timeout="5" />
                <retry condition="@(context.Response == null || context.Response.StatusCode > 400)" count="5" interval="1" first-fast-retry="true">
                    <set-backend-service base-url="<secondary url>" />                        
                </retry>
            </when>
        </choose>
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />        
    </on-error>
</policies>

以下是 APIM 跟踪的摘录

Inbound
(3.014 ms)
api-inspector (0.403 ms)
{
    "request": {
        "method": "GET",
        "url": "https://gpcshare-apim-gpc-dev-aes.azure-api.net/statcode/405?sleep=7000",
        "headers": [
            {
                "name": "Ocp-Apim-Subscription-Key",
                "value": "a02f7f4e18d54d84ba55d4f122548072"
            },
            {
                "name": "Sec-Fetch-Site",
                "value": "cross-site"
            },
            {
                "name": "Sec-Fetch-Mode",
                "value": "cors"
            },
            {
                "name": "X-Forwarded-For",
                "value": "103.111.183.78"
            },
            {
                "name": "Cache-Control",
                "value": "no-cache, no-store"
            },
            {
                "name": "Via",
                "value": "ICAP/1.0 bmg70302.ibosscloud.com (IBOSS/0.4.4 iboss ICAP service )"
            },
            {
                "name": "Content-Type",
                "value": "text/plain;charset=UTF-8"
            },
            {
                "name": "Accept",
                "value": "*/*"
            },
            {
                "name": "Accept-Encoding",
                "value": "gzip,deflate,br"
            },
            {
                "name": "Accept-Language",
                "value": "en-US,en;q=0.9"
            },
            {
                "name": "Host",
                "value": "gpcshare-apim-gpc-dev-aes.azure-api.net"
            },
            {
                "name": "Referer",
                "value": "https://apimanagement.hosting.portal.azure.net/apimanagement/Content/1.42.0.1/apimap//apimap-apis/index.html?clientOptimizations=undefined&l=en.en-us&trustedAuthority=https%3A%2F%2Fportal.azure.com&shellVersion=undefined"
            }
        ]
    }
}
api-inspector (0.004 ms)
{
    "configuration": {
        "api": {
            "from": "/statcode",
            "to": null,
            "version": null,
            "revision": "1"
        },
        "operation": {
            "method": "GET",
            "uriTemplate": "/{code}"
        },
        "user": "-",
        "product": "-"
    }
}
cors (2.601 ms)
"Origin header was missing or empty and the request was classified as not cross-domain. CORS policy was not applied."
cors (0.002 ms)
"Origin header was missing or empty and the request was classified as not cross-domain. CORS policy was not applied."
set-variable (0.003 ms)
{
    "message": "Context variable was successfully set.",
    "name": "isFlag",
    "value": "true"
}
Backend
(4,991.587 ms)↑ Back to top
choose (0.017 ms)
{
    "message": "Expression was successfully evaluated.",
    "expression": "context.Variables.GetValueOrDefault<string>(\"isFlag\") == \"true\"",
    "value": true
}
set-backend-service (0.007 ms)
{
    "message": "Backend service URL was changed.",
    "oldBackendServiceUrl": "",
    "newBackendServiceUrl": "https://httpstat.us/",
    "request": {
        "url": "https://httpstat.us/405?sleep=7000"
    }
}
forward-request (0.151 ms)
{
    "message": "Request is being forwarded to the backend service. Timeout set to 5 seconds",
    "request": {
        "method": "GET",
        "url": "https://httpstat.us/405?sleep=7000",
        "headers": [
            {
                "name": "Host",
                "value": "httpstat.us"
            },
            {
                "name": "Request-Id",
                "value": "|f595c50c66d7453c97a7dc14c9c1af9e.2b06f656cb6c4704_b907aebb."
            },
            {
                "name": "Ocp-Apim-Subscription-Key",
                "value": "a02f7f4e18d54d84ba55d4f122548072"
            },
            {
                "name": "Sec-Fetch-Site",
                "value": "cross-site"
            },
            {
                "name": "Sec-Fetch-Mode",
                "value": "cors"
            },
            {
                "name": "X-Forwarded-For",
                "value": "103.111.183.78,13.91.254.72"
            },
            {
                "name": "Cache-Control",
                "value": "no-cache, no-store"
            },
            {
                "name": "Via",
                "value": "ICAP/1.0 bmg70302.ibosscloud.com (IBOSS/0.4.4 iboss ICAP service )"
            },
            {
                "name": "Content-Type",
                "value": "text/plain;charset=UTF-8"
            },
            {
                "name": "Accept",
                "value": "*/*"
            },
            {
                "name": "Accept-Encoding",
                "value": "gzip,deflate,br"
            },
            {
                "name": "Accept-Language",
                "value": "en-US,en;q=0.9"
            },
            {
                "name": "Referer",
                "value": "https://apimanagement.hosting.portal.azure.net/apimanagement/Content/1.42.0.1/apimap//apimap-apis/index.html?clientOptimizations=undefined&l=en.en-us&trustedAuthority=https%3A%2F%2Fportal.azure.com&shellVersion=undefined"
            }
        ]
    }
}
forward-request (4,991.413 ms)
{
    "messages": [
        "Error occured while calling backend service.",
        "Request to the backend service timed out"
    ]
}
Outbound
(0.183 ms)↑ Back to top
transfer-response (0.067 ms)
{
    "message": "Response headers have been sent to the caller."
}
transfer-response (0.116 ms)
{
    "message": "Response body streaming to the caller is complete."
}

【问题讨论】:

    标签: azure azure-api-management policies


    【解决方案1】:

    您可以将您的逻辑包含在 retry 策略中。有一个policy snippet sample 可以参考。特别是这个line

    这是相同的政策供参考

    <!--
        This policy routes calls to the closest of two backend services, and fails over to the secondary if an HTTP 404 is returned.
    
        It assumes that the API Manager is deployed in 'East US' and 'West Europe'. Similarly the policy (as is) assumes two backend services, in the same regions, vis:
            https://hello-eus.azurewebsites.net/  (for East US); and
            https://hello-weu.azurewebsites.net/  (for West Europe)
    
        If a failure (HTTP 404) is returned from the backend service, the policy will re-route the call to the fail-over region.
        The policy uses cached values to track which service has returned an error in the last 10 seconds, to avoid routing new requests to a backend which will likely fail.
    -->
    <policies>
        <inbound>
            <base />
            <set-backend-service base-url="https://hello-eus.azurewebsites.net/" />
            <choose>
                <when condition="@(context.Deployment.Region.Equals("east us", System.StringComparison.InvariantCultureIgnoreCase))">
                    <set-backend-service base-url="https://hello-eus.azurewebsites.net/" />
                    <cache-lookup-value key="@("eus-down")" variable-name="is-eus-down" />
                    <choose>
                        <when condition="@(context.Variables.GetValueOrDefault<bool>("is-eus-down"))">
                            <set-backend-service base-url="https://hello-weu.azurewebsites.net/" />
                        </when>
                    </choose>
                </when>
                <when condition="@(context.Deployment.Region.Equals("west europe", System.StringComparison.InvariantCultureIgnoreCase))">
                    <set-backend-service base-url="https://hello-weu.azurewebsites.net/" />
                    <cache-lookup-value key="@("weu-down")" variable-name="is-weu-down" />
                    <choose>
                        <when condition="@(context.Variables.GetValueOrDefault<bool>("is-weu-down"))">
                            <set-backend-service base-url="https://hello-eus.azurewebsites.net/" />
                        </when>
                    </choose>
                </when>
            </choose>
        </inbound>
        <backend>
            <retry condition="@(context.Response.StatusCode == 404)" count="2" interval="1" max-interval="10" delta="1" first-fast-retry="true">
                <choose>
                    <when condition="@(context.Response != null && (context.Response.StatusCode == 404))">
                        <choose>
                            <when condition="@(context.Request.Url.Host.Contains("hello-eus.azurewebsites.net"))">
                                <set-backend-service base-url="https://hello-weu.azurewebsites.net" />
                                <cache-store-value key="@("eus-down")" value="@(true)" duration="10" />
                            </when>
                            <otherwise>
                                <set-backend-service base-url="https://hello-eus.azurewebsites.net" />
                                <cache-store-value key="@("weu-down")" value="@(true)" duration="10" />
                            </otherwise>
                        </choose>
                    </when>
                </choose>
                <forward-request />
            </retry>
        </backend>
        <outbound>
            <base />
        </outbound>
        <on-error>
            <base />
        </on-error>
    </policies>
    

    【讨论】:

      猜你喜欢
      • 2016-12-17
      • 2014-11-01
      • 1970-01-01
      • 2018-12-28
      • 2014-08-28
      • 2018-02-02
      • 2020-03-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多