尝试使用 API-M 部署 API 终结点,但在后端部分中覆盖了后端服务 URL



我已经针对当前的生产端点设置了我的API-M端点,这工作正常。我现在想将一小部分访问者指向一个新的(并希望得到改进的(端点,但如果它失败,我希望 API-M 针对当前端点重试请求。

我已经设置了一个这样的策略,配置了在我让它工作时 100% 击中金丝雀的机会。入库部分取自样品 https://github.com/Azure/api-management-samples/blob/914f1032583dd9e1a1ca8ba01eaba247290fa134/policies/Route%20percentage%20of%20traffic%20to%20canary.policy.xml:

<policies>
<inbound>
<base />
<set-variable name="canaryPercentage" value="@(100)" />
<set-variable name="canaryBackendServiceUrl" value="https://new-base-uri" />
<choose>
<when condition="@(new Random().Next(100) < context.Variables.GetValueOrDefault<int>("canaryPercentage"))">
<set-backend-service base-url="@(context.Variables.GetValueOrDefault<string>("canaryBackendServiceUrl"))" />
</when>
</choose>
</inbound>
<backend>
<retry condition="@(context.Response != null && context.Response.StatusCode >= 500)" count="10" interval="10" max-interval="100" delta="10" first-fast-retry="true">
<set-backend-service base-url="https://old-base-uri" />
<forward-request timeout="10" />
</retry>
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>

根据跟踪,入站部分工作。这是来自"入站"部分的最后一条日志消息:

set-backend-service (0.038 ms)
{
"message": "Backend service URL was changed.",
"oldBackendServiceUrl": "https://old-base-uri/",
"newBackendServiceUrl": "https://new-base-uri",
"request": {
"url": "https://new-base-uri/endpoint"
}
}

但是第二天,它把它扔掉了(很抱歉今天早上把它打乱了 - 这是"后端"部分中的第一条声明(:

set-backend-service (0.016 ms)
{
"message": "Backend service URL was changed.",
"oldBackendServiceUrl": "https://new-base-uri",
"newBackendServiceUrl": "https://old-base-uri/",
"request": {
"url": "https://old-base-uri/endpoint"
}
}

我很难理解为什么会发生这种情况,因为策略的后端元素中没有引用。

我希望发生的是,应首先将请求转发到 Canary(新(终结点,如果失败并出现服务器端错误 (>=500(,则针对生产终结点重试请求。

设法自己解决了这个问题。我必须承认 API-M 语法有点令人困惑,但诀窍是在重试元素和选择元素中仔细检查条件。另请注意 set-body 元素 - 它是必需的,以及将传入主体设置为变量。没有它,将不会发布任何带有重试请求的正文,并且您最终会遇到此错误:

forward-request (1.326 ms)
{
"messages": [
"Content length mismatch",
"Content length mismatch"
]
}

变量在入站元素中设置:

<set-variable name="body" value="@(context.Request.Body.As<string>(preserveContent: true))" />

使它工作的完整后端元素:

<backend>
<retry condition="@(context.Response.StatusCode >= 400)" count="1" interval="0" first-fast-retry="true">
<choose>
<when condition="@(context.Response.StatusCode >= 400)">
<set-backend-service base-url="https://production-uri" />
</when>
</choose>
<set-body>@((string)context.Variables["body"])</set-body>
<forward-request />
</retry>
</backend>

最新更新