英文:
How to add listener rules in a loop; with priority derived from loop index?
问题
以下是您要求的代码的中文翻译部分:
// 为负载均衡器内的应用程序添加监听器
const myListener = alb.addListener("myListener", {});
// 在此添加优先级为1的规则。
for (let i = 0; i < clients.length; i++) {
const tenantId = clients[i].tenantId;
const domainName = clients[i].dnsName;
const taskDefinition = new ecs.FargateTaskDefinition(
this,
`serviceTask${tenantId}`,
{}
);
// 现在为clients[i]创建容器
// ...
// 现在为现有的LB添加监听器
const myTarget = new elbv2.ApplicationTargetGroup(
this,
`myService${tenantId}targetgroup`,
{}
);
const listenerRule = new elbv2.ApplicationListenerRule(
this,
"listenerRule" + tenantId,
{
listener: myListener,
/*priority: i + 2; */ /*优先级为2及以上的规则*/
priority: clients.length - i + 1,
action: ListenerAction.forward([myTarget]),
conditions: [elbv2.ListenerCondition.hostHeaders([domainName])],
}
);
}
请注意最后一个代码块中的 priority
字段。一行被注释掉,当前的方法没有被注释掉。这两种方法是相似的。所有这些都在一个for循环中。在被注释掉的部分中,我从2开始,一直到clients数组的长度。在另一种方法中,我从末尾开始。
假设数组中有4个元素。因此,监听器规则的优先级将为 - 5, 4, 3, 2。
容器 | 监听器规则优先级 |
---|---|
容器A | 5 |
容器B | 4 |
容器C | 3 |
容器D | 2 |
在新的部署中,假设删除了clients
数组的第一个元素。因此,更新后的优先级将为 - 4, 3, 2。
容器 | 监听器规则优先级 |
---|---|
容器B | 4 |
容器C | 3 |
容器D | 2 |
这不会带来太多麻烦。cdk deploy
运行得很完美。这是因为优先级为5的规则被简单地删除,不需要创建新的规则。其余的容器与之前相同的优先级映射。
现在假设删除clients
数组的最后一个元素。因此,更新的CloudFormation模板将容器映射到如下优先级:
容器 | 监听器规则优先级 |
---|---|
容器A | 4 |
容器B | 3 |
容器C | 2 |
请注意,容器A、B、C之前分别映射到5、4、3的优先级,但在删除最后一个元素后,它们分别映射到4、3、2的优先级。这在部署过程中会引发“ListenerRule已存在”的错误。因为当A被映射到优先级4时,它注意到优先级4已经映射到B。依此类推...
那么,我应该如何处理这样的部署更新,其中删除了高优先级规则(具有低优先级值的规则),而其他规则都向前移动了一个位置。
英文:
In continuation to my previous quest, now I am stuck at the following juncture. I read a file clients.json and then create stack resources based on the input from the file. This file contains an array. And for each item of an array I create similar resources. In the following code, I am adding listener rules in a loop for containers which are also created in the same loop.
//add listener for application inside load balancer
const myListener = alb.addListener("myListener", {});
// rule with priority 1 added here.
for (let i = 0; i < clients.length; i++) {
const tenantId = clients[i].tenantId;
const domainName = clients[i].dnsName;
const taskDefinition = new ecs.FargateTaskDefinition(
this,
`serviceTask${tenantId}`,
{}
);
// now create container for clients[i]
// ...
// now add listeners to existing LB
const myTarget = new elbv2.ApplicationTargetGroup(
this,
`myService${tenantId}targetgroup`,
{}
);
const listenerRule = new elbv2.ApplicationListenerRule(
this,
"listenerRule" + tenantId,
{
listener: myListener,
/*priority: i + 2; */ /*rules with priority 2 and above*/
priority: clients.length - i + 1,
action: ListenerAction.forward([myTarget]),
conditions: [elbv2.ListenerCondition.hostHeaders([domainName])],
}
);
}
Look at the priority
field in the last block. One line is commented and the current approach is uncommented. Both the approaches are similar. All of this is in a for-loop. In the commented part, I am starting from 2 and going till the length of clients array. In the other approach, I am starting from the end.
Suppose there are 4 elements in the array. So the listener rule priorities will be - 5, 4, 3, 2.
container | listener rule priority |
---|---|
containerA | 5 |
containerB | 4 |
containerC | 3 |
containerD | 2 |
In a new deployment, suppose the first element of the clients
array is removed. So the updated priorities will be - 4, 3, 2.
container | listener rule priority |
---|---|
containerB | 4 |
containerC | 3 |
containerD | 2 |
This is not much of a hassle. cdk deploy
runs perfectly. This is because rule with priority 5 is simply deleted and no new rule has to be created. The remaining containers map to the same priority as before.
Now suppose the last element if the clients
array is removed. So the updated cloudformation template will map the containers to the priorities like this,
container | listener rule priority |
---|---|
containerA | 4 |
containerB | 3 |
containerC | 2 |
Notice that containers A, B, C were earlier mapped to 5, 4, 3 respectively, but after removal of the last element, they are mapped to 4, 3, 2 respectively. This gives "ListenerRule already exist" error during deployment. Because when A is getting mapped to priority 4, it notices that 4 priority is already mapped to B. And so on...
So, how should I handle such a deployment update where a high priority rule (one with low priority value) is removed and other rules shift by one.
答案1
得分: 1
The CloudFormation AWS::ElasticLoadBalancingV2::ListenerRule
docs 解释了当重新分配规则优先级时出现错误的原因:
> 一个监听器不能有多个具有相同优先级的规则。如果尝试通过更新它们的优先级来重新排序规则,请不要指定一个已经存在的规则使用的新优先级,因为这可能会导致错误。如果需要在不同的规则中重用相同的优先级,必须首先将其删除作为优先级,然后在随后的更新中指定它。
换句话说,您想要设置唯一的、半永久的优先级值,同时适应后续的插入和删除。
一种方法是为clients.json
中的每个条目分配一个明确的优先级值。这些优先级将设置为间隔,例如,100,以适应后续的重新排序(规则显然接受最高为50000
的优先级值)。
- containerA:
100
- containerB:
200
- containerC:
300
如果有新的客户出现,您可以为她分配最高优先级,例如,containerD: 50
,而无需触碰现有的优先级。
英文:
The CloudFormation AWS::ElasticLoadBalancingV2::ListenerRule
docs explain why you're getting the error when re-assigning the rule priorities:
> A listener can't have multiple rules with the same priority. If you try to reorder rules by updating their priorities, do not specify a new priority if an existing rule already uses this priority, as this can cause an error. If you need to reuse a priority with a different rule, you must remove it as a priority first, and then specify it in a subsequent update.
In other words, you're looking to set unique, semi-permanent priority values, while accomodating subsequent insertions and deletions.
One approach would be to assign an explicit priority value to each entry in clients.json
. These priorities would be set with a gap of, say, 100 to accomodate later reordering (rules apparently accept priority values up to 50000
).
- containerA:
100
- containerB:
200
- containerC:
300
If a new customer comes along, you can give her top priority with containerD: 50
, for instance, without touching the existing priorities.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论