我有一个具有 96 个 vCPU 的 AWS EC2 主机
我执行以下脚本,该脚本将异步子进程扩展到一定限制(作为脚本参数传递)。每个异步子进程都会调用 AWS CLI 并退出
#!/bin/bash
function f() {
p=$1
echo "$(date) entering f($p)"
aws sts get-caller-identity
echo "$(date) leaving f($p)"
}
a=""
for i in {1..400}; do
a="$a
$i"
done
jobs_limit=$1
while read line; do
jobs=$(jobs -r | wc -l)
while [ $jobs -ge $jobs_limit ]; do
sleep 0.1
jobs=$(jobs -r | wc -l)
done
echo "$(f $line)" &
done < <(echo "$a")
wait
问题:当子进程超过40个时,某些进程随机出现
Unable to locate credentials. You can configure credentials by running "aws configure".
错误。
这是使用不同限制执行脚本时的输出
sh-4.2$ /tmp/b.sh 40 2>&1 | egrep 'Unable to locate credentials' | wc -l
0
sh-4.2$ /tmp/b.sh 40 2>&1 | egrep 'Unable to locate credentials' | wc -l
0
sh-4.2$ /tmp/b.sh 44 2>&1 | egrep 'Unable to locate credentials' | wc -l
22
sh-4.2$ /tmp/b.sh 44 2>&1 | egrep 'Unable to locate credentials' | wc -l
7
sh-4.2$ /tmp/b.sh 48 2>&1 | egrep 'Unable to locate credentials' | wc -l
18
sh-4.2$ /tmp/b.sh 48 2>&1 | egrep 'Unable to locate credentials' | wc -l
14
如上所示,40 个时错误为零,超过 40 个时错误数随机。
有人可以解释一下发生了什么事吗?
有一个想法,它可能会调用
/metadata
端点来获取信用,并且它以某种方式限制了请求率,所以我更改为在父进程中获取信用并将其传递给子进程,但没有运气
function f() {
p=$1
cc=$2
echo "$(date) entering f($p)"
k=$(echo $cc | jq .AccessKeyId -r)
s=$(echo $cc | jq .SecretAccessKey -r)
t=$(echo $cc | jq .Token -r)
AWS_ACCESS_KEY_ID=$k AWS_SECRET_ACCESS_KEY=$s AWS_SESSION_TOKEN=$t aws sts get-caller-identity
echo "$(date) leaving f($p)"
}
...
creds=$(curl http://169.254.169.254/latest/meta-data/iam/security-credentials/EMRJobFlowRole)
...
echo "$(f $line $creds)" &
...
@jarmod 为我指明了正确的方向。如果我减少生育孩子的频率,那么问题就会消失。
请参阅循环末尾的额外
sleep 0.050
。
#!/bin/bash
function f() {
p=$1
echo "$(date) entering f($p)"
aws sts get-caller-identity
echo "$(date) leaving f($p)"
}
a=""
for i in {1..400}; do
a="$a
$i"
done
jobs_limit=$1
while read line; do
jobs=$(jobs -r | wc -l)
while [ $jobs -ge $jobs_limit ]; do
sleep 0.050
jobs=$(jobs -r | wc -l)
done
echo "$(f $line)" &
# Otherwise IMDS throttles us
sleep 0.05
done < <(echo "$a")
wait
仍有待解决的问题:如果这是 IMDS 相关问题,那么为什么当我将凭据传递给每个子进程时它不起作用?为什么在这种情况下会调用 IMDS?