Haproxy 多个实例 - 服务后端不稳定 5 分钟
Haproxy multiple instances - service backends don't stabilize for 5 min
问题:
在 Haproxy 中使用 SRV 记录,后端会向下和向上几次,但在大约 5 分钟内不稳定
架构:
云提供商:AWS
运行 ECS 上的多个 (3) Haproxy 容器,带有 ELB 以在它们之间分配流量。
我将 Haproxy 后端设置为使用 SRV 记录进行服务发现
我动态地想向 Haparoxy 添加服务(后端),所以我使用配置模板和套接字重新加载。
每个服务有 2 个后端
重新加载脚本如下所示,它生成模板并在模板更改时重新加载:#没有添加新服务所以我认为重新加载脚本与问题无关
#!/bin/bash
mkdir -p /var/PROJECT/services/
aws s3 cp s3://$BUCKET/services/services.json /var/PROJECT/services/
python3 /var/PROJECT/docker/generateHaproxyConfig.py >> /var/log/haproxy-gen.log
if ! diff -q /etc/haproxy/haproxy.cfg.new /etc/haproxy/haproxy.cfg &>/dev/null; then
mv /etc/haproxy/haproxy.cfg.new /etc/haproxy/haproxy.cfg
mkdir -p /etc/haproxy/states
for b in $(socat /var/run/haproxy/socket - <<< "show backend" | fgrep -v '#')
do
socat /var/run/haproxy/socket - <<< "show servers state $b" > /etc/haproxy/states/$b
done
/etc/init.d/haproxy reload
fi
在我的测试中,我有服务 运行 (06:49:14) 然后停止它 (~06:50:00) 然后在几秒钟后启动它。
在日志 HA1 中,我们看到它执行了以下操作:
1) 在 06:49:14
UP
2) 在 06:50:16
下跌
3) 后端 1 在 06:51:17 #它应该有两个后端都在这里 UP 而没有更多的 DOWNs
4) 后端 1 在 06:51:58 发生故障 #这是意外的!
5) 后端 1 在 06:52:09
恢复正常
6) backend2 在 06:56:10 启动 #为什么这需要这么长时间?
其他容器也有类似的行为
SRV DNS 记录如下所示:
_test-git._tcp.staging.qa。
SRV
1 1 32773 6c733da247894543afe5d11828751a05._test-git._tcp.staging.qa.
_test-git._tcp.staging.qa。
SRV
1 1 32773 ec40447095d345069daf9ff7c0b6bd8c._test-git._tcp.staging.qa.
6c733da247894543afe5d11828751a05._test-git._tcp.staging.qa。
一种
172.18.2.194
ec40447095d345069daf9ff7c0b6bd8c._test-git._tcp.staging.qa。
一种
172.18.1.171
Haproxy 配置模板:
global
log /dev/log local0 info
#log /dev/log local1 info
#log /dev/log local2 info
chroot /var/lib/haproxy
user haproxy
group haproxy
pidfile /run/haproxy.pid
stats socket /var/run/haproxy/socket
server-state-base /etc/haproxy/states
# stats socket /var/run/hapee-lb.sock mode 666 level admin
# stats socket ipv4@127.0.0.1:9999 level admin
stats timeout 30s
daemon
spread-checks 4
tune.maxrewrite 1024
# tune.ssl.default-dh-param 2048
resolvers awsdns
nameserver default {{settings.NAMESERVER}}
resolve_retries 3
timeout resolve 3s
timeout retry 3s
hold other 30s
hold refused 30s
hold nx 1s
hold timeout 30s
hold valid 10s
hold obsolete 30s
defaults
log global
mode http
balance roundrobin
load-server-state-from-file local
option httplog
option dontlognull
# option forwardfor except 127.0.0.0/8
option dontlog-normal
option socket-stats
# option forceclose
option forwardfor if-none
# option httpclose
# option forceclose
# option http-server-close
option redispatch
retries 3
maxconn 500000
timeout connect 5s
timeout client 300s
timeout server 1h
timeout queue 30s
# timeout http-request 5s
# timeout http-keep-alive 15s
frontend www-http
bind 0.0.0.0:80
# reqadd X-Forwarded-Proto:\ http
acl is_valid_base_domain hdr_end(host) -i PROJECT.io
# acl servers_alive nbsrv(www-backend-%[req.hdr(host),lower,field(1,'.')]) ge 1
# use_backend www-backend-%[req.hdr(host),lower,field(1,'.')]-redirect if is_valid_base_domain !servers_alive
use_backend www-backend-%[req.hdr(host),lower,field(1,'.')] if is_valid_base_domain
use_backend www-health if !is_valid_base_domain
default_backend www-backend
frontend stats
bind *:1936
mode http
option httpclose
stats enable
stats uri /
stats show-legends
#stats show-desc
stats show-node
stats refresh 2
{% for service in services %}
backend www-backend-{{service.name}}
option httpchk GET /health.php
http-check expect string 1
acl servers_alive nbsrv(www-backend-{{service.name}}) ge 1
http-request redirect code 302 location https://{{settings.REDIRECT_HOST}}/site/{{service.id}}/launch?s_r_path=%[path]&s_r=1&%[query] if ! servers_alive
server-template {{service.name}} 2 _{{service.name}}._tcp.{{settings.SERVICE_DISCOVERY_DOMAIN_NAME}} resolvers awsdns resolve-prefer ipv4 resolve-opts allow-dup-ip check
{% endfor %}
backend www-backend
# errorfile 502 /var/PROJECT/lb/statuses/200.http
# errorfile 503 /var/PROJECT/lb/statuses/200.http
backend www-health
acl is_valid_base_domain hdr_end(host) -i PROJECT.io
errorfile 502 /var/PROJECT/lb/statuses/200.http
errorfile 503 /var/PROJECT/lb/statuses/200.http
Haproxy 容器日志:https://gist.github.com/amitaymolko/5865e9fdef6bf47ffc2323c813edd40d
编辑:更新了 haproxy 配置
我最初的猜测是 DNS 问题,也许您缓存了一个 "NXDOMAIN"?尝试减少 staging.qa
的 TTL
问题:
在 Haproxy 中使用 SRV 记录,后端会向下和向上几次,但在大约 5 分钟内不稳定
架构:
云提供商:AWS
运行 ECS 上的多个 (3) Haproxy 容器,带有 ELB 以在它们之间分配流量。
我将 Haproxy 后端设置为使用 SRV 记录进行服务发现
我动态地想向 Haparoxy 添加服务(后端),所以我使用配置模板和套接字重新加载。
每个服务有 2 个后端
重新加载脚本如下所示,它生成模板并在模板更改时重新加载:#没有添加新服务所以我认为重新加载脚本与问题无关
#!/bin/bash
mkdir -p /var/PROJECT/services/
aws s3 cp s3://$BUCKET/services/services.json /var/PROJECT/services/
python3 /var/PROJECT/docker/generateHaproxyConfig.py >> /var/log/haproxy-gen.log
if ! diff -q /etc/haproxy/haproxy.cfg.new /etc/haproxy/haproxy.cfg &>/dev/null; then
mv /etc/haproxy/haproxy.cfg.new /etc/haproxy/haproxy.cfg
mkdir -p /etc/haproxy/states
for b in $(socat /var/run/haproxy/socket - <<< "show backend" | fgrep -v '#')
do
socat /var/run/haproxy/socket - <<< "show servers state $b" > /etc/haproxy/states/$b
done
/etc/init.d/haproxy reload
fi
在我的测试中,我有服务 运行 (06:49:14) 然后停止它 (~06:50:00) 然后在几秒钟后启动它。
在日志 HA1 中,我们看到它执行了以下操作:
1) 在 06:49:14
UP
2) 在 06:50:16
下跌
3) 后端 1 在 06:51:17 #它应该有两个后端都在这里 UP 而没有更多的 DOWNs
4) 后端 1 在 06:51:58 发生故障 #这是意外的!
5) 后端 1 在 06:52:09
恢复正常
6) backend2 在 06:56:10 启动 #为什么这需要这么长时间?
其他容器也有类似的行为
SRV DNS 记录如下所示:
_test-git._tcp.staging.qa。
SRV
1 1 32773 6c733da247894543afe5d11828751a05._test-git._tcp.staging.qa.
_test-git._tcp.staging.qa。
SRV
1 1 32773 ec40447095d345069daf9ff7c0b6bd8c._test-git._tcp.staging.qa.
6c733da247894543afe5d11828751a05._test-git._tcp.staging.qa。
一种
172.18.2.194
ec40447095d345069daf9ff7c0b6bd8c._test-git._tcp.staging.qa。
一种
172.18.1.171
Haproxy 配置模板:
global
log /dev/log local0 info
#log /dev/log local1 info
#log /dev/log local2 info
chroot /var/lib/haproxy
user haproxy
group haproxy
pidfile /run/haproxy.pid
stats socket /var/run/haproxy/socket
server-state-base /etc/haproxy/states
# stats socket /var/run/hapee-lb.sock mode 666 level admin
# stats socket ipv4@127.0.0.1:9999 level admin
stats timeout 30s
daemon
spread-checks 4
tune.maxrewrite 1024
# tune.ssl.default-dh-param 2048
resolvers awsdns
nameserver default {{settings.NAMESERVER}}
resolve_retries 3
timeout resolve 3s
timeout retry 3s
hold other 30s
hold refused 30s
hold nx 1s
hold timeout 30s
hold valid 10s
hold obsolete 30s
defaults
log global
mode http
balance roundrobin
load-server-state-from-file local
option httplog
option dontlognull
# option forwardfor except 127.0.0.0/8
option dontlog-normal
option socket-stats
# option forceclose
option forwardfor if-none
# option httpclose
# option forceclose
# option http-server-close
option redispatch
retries 3
maxconn 500000
timeout connect 5s
timeout client 300s
timeout server 1h
timeout queue 30s
# timeout http-request 5s
# timeout http-keep-alive 15s
frontend www-http
bind 0.0.0.0:80
# reqadd X-Forwarded-Proto:\ http
acl is_valid_base_domain hdr_end(host) -i PROJECT.io
# acl servers_alive nbsrv(www-backend-%[req.hdr(host),lower,field(1,'.')]) ge 1
# use_backend www-backend-%[req.hdr(host),lower,field(1,'.')]-redirect if is_valid_base_domain !servers_alive
use_backend www-backend-%[req.hdr(host),lower,field(1,'.')] if is_valid_base_domain
use_backend www-health if !is_valid_base_domain
default_backend www-backend
frontend stats
bind *:1936
mode http
option httpclose
stats enable
stats uri /
stats show-legends
#stats show-desc
stats show-node
stats refresh 2
{% for service in services %}
backend www-backend-{{service.name}}
option httpchk GET /health.php
http-check expect string 1
acl servers_alive nbsrv(www-backend-{{service.name}}) ge 1
http-request redirect code 302 location https://{{settings.REDIRECT_HOST}}/site/{{service.id}}/launch?s_r_path=%[path]&s_r=1&%[query] if ! servers_alive
server-template {{service.name}} 2 _{{service.name}}._tcp.{{settings.SERVICE_DISCOVERY_DOMAIN_NAME}} resolvers awsdns resolve-prefer ipv4 resolve-opts allow-dup-ip check
{% endfor %}
backend www-backend
# errorfile 502 /var/PROJECT/lb/statuses/200.http
# errorfile 503 /var/PROJECT/lb/statuses/200.http
backend www-health
acl is_valid_base_domain hdr_end(host) -i PROJECT.io
errorfile 502 /var/PROJECT/lb/statuses/200.http
errorfile 503 /var/PROJECT/lb/statuses/200.http
Haproxy 容器日志:https://gist.github.com/amitaymolko/5865e9fdef6bf47ffc2323c813edd40d
编辑:更新了 haproxy 配置
我最初的猜测是 DNS 问题,也许您缓存了一个 "NXDOMAIN"?尝试减少 staging.qa
的 TTL