4

我正在研究基于 Docker、registrator、consul 和 HAProxy 的微服务架构。

我也在使用 Consul-template 来动态生成 HAProxy 配置文件。一切正常:当我添加同一个微服务的多个实例时,HAProxy 配置会立即更新,并使用循环策略正确分派请求。

当我删除一些实例(按比例缩小)时,会出现我的问题。如果在请求运行时关闭容器,则会出现错误。

我是 HAProxy 的新手,所以有没有办法配置 HAProxy 来告诉它在容器消失时重试对另一个端点的失败请求?

精度:我正在为我的前端和后端使用 layer7 路由模式(模式 http)。这是我的领事模板文件的一个小样本:

backend hello-backend
    balance roundrobin
    mode http
    {{range service "HelloWorld" }}server {{.Node}} {{.Address}}:{{.Port}} check
    {{end}}

    # Path stripping
    reqrep ^([^\ ]*)\ /hello/(.*) \1\ /\2

frontend http
    bind *:8080
    mode http

    acl url_hello path_beg /hello
    use_backend hello-backend if url_hello

谢谢您的帮助。

4

1 回答 1

4

HAProxy 无法重新发送已经发送到后端的请求。

这是创建者威利的论坛帖子。

仅当请求仍处于 haproxy 中时才会发生重新调度。一旦发送,就无法执行。对于非幂等请求也不能执行它,因为在服务器死亡并返回 RST 之前,无法知道服务器上是否已经开始了某些处理。

http://haproxy.formilux.narkive.com/nGKXq6WU/problems-with-haproxy-down-servers-and-503-errors

这篇文章已经很老了,但根据最近的讨论,它仍然适用。如果请求大于tune.bufsize (默认为 16KB iirc 左右),则 HAProxy 甚至没有在发生错误时将整个请求保留在内存中。

幸运的是(为了工艺)和不幸的是(为了现实世界的效用),Willy 一直坚持 HAProxy 的正确行为,他确实是正确的,一旦非幂等请求被发送到就重试是不合适的。后端服务器,因为在某些情况下这肯定会导致重复处理。

对于GET根据定义应该是幂等的请求(GET请求必须是可重复的,没有后果,否则它不应该被设计为使用GET- 它应该是POST或另一个动词)有一个可行的论点,即重新发送到不同的后端将是一个合法的行动方案,但目前也不支持。

相比之下,Varnish确实支持重做,我已经使用(在 HAProxy 之后)成功地处理GET了我对同一对象命名空间有在线和近线存储的请求。旧的,“不受欢迎”的文件被迁移到近线(更慢,更便宜)存储,但所有请求都被发送到在线存储,如果在线返回 404,则重试目的地为近线。但是,我'除了GET.

理想情况下,您的解决方案是让您的后端被宣布为不健康,可能是在关闭之前故意使他们的 HTTP 健康检查失败并耗费大量时间。一种相当简单的方法是运行状况检查要求存在一个静态文件,该文件会在关闭前从后端删除。或者,您可以通过 stats/admin UI 或套接字请求 HAProxy 将后端视为处于维护模式,从而防止启动更多请求,同时允许正在运行的请求耗尽。

于 2016-08-26T12:19:31.730 回答