azure-api-management - 尝试使用 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"
}
}
我很难理解为什么会发生这种情况,因为政策的后端元素中没有提及。
我想要发生的是,请求应该首先被转发到金丝雀(新)端点,如果由于服务器端错误(> = 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>
推荐阅读
- mysql - 有没有办法确保对表架构的任何更改也适用于另一个表?
- python - 用于支持 Python Pandas 日期的凌乱 Excel 日期
- visual-studio - ScreenCaptureJob 未在 DEVOPS 中设置
- php - 我的视频没有显示说明请帮助我不是专家
- javascript - 从另一个组件调用函数
- angular - 使用 Angular-CLI 运行时设置节点选项
- powershell - [tag]已解决[/tag] 无法在 Powershell 命令中使用我的变量作为 Powershell Studio 中的 GUI
- python - 在条形堆栈图中标记和操作每个堆栈
- android - 如何从项目的strings.xml 列表中读取ViewModel 数据
- javascript - 如何在 html 日历中导入谷歌日历事件?