在持续高负荷下服务的常见背压策略

我想知道什么是人们使用他们的networking服务常见的背压战略?

想象一下,你的服务在重负载下运行,并且在某个时候负载达到你容量的120%。 你怎么处理这个?

我能想到的最好的策略是开始拒绝连接。 所以,如果一个主机达到了最高容量(例如,所有Apache员工都很忙),我会开始拒绝TCP连接,直到其中一个工作人员释放。 通过这种方式,所有被接受的连接都将被立即处理而不需要排队(所以延迟很小),过多的20%被拒绝,允许负载均衡器重新分配给其他主机或执行任何其他的负载减less策略(例如,redirect到静态/caching内容)。

我认为这种快速的方法比任何排队方式都要优越得多。 小的队列可以吸收短暂的stream量爆炸,但是由于过多的排队,您的系统在重负载下可能会失败。 例如,在没有任何AQM的FIFO队列处理的情况下,当所有处理的请求在客户端已经超时时,它可以进入状态,因此系统不进行前进。

我感到惊讶的是,这个策略听起来并不容易实现。 我的方法是在Web服务器上设置一个小的收听积压,期待所有不适合的连接被拒绝。 但是由于Linux内核2.2的变化,这种策略分崩离析(参见http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html )。

较新的Linux内核无条件地接受你的连接。 SYN-ACK响应被发送到客户端,根本不考虑监听积压大小。 启用tcp_abort_on_overflow选项也没有多大帮助。 这个选项使内核在连接不适合接受队列时发送RST,但此时客户端已经考虑了连接ESTABLISHED并可能已经开始发送数据。

这对HAProxy尤其有问题。 如果连接成功build立,它不会将请求重新发送到其他服务器,因为这个请求可能在服务器上有一些副作用。

所以我想我的问题是:

  • 我试图执行这样的事情是我奇怪的吗?
  • 有什么其他的策略来处理持续高负荷,你可以推荐?
  • 是Linux内核的tcp_abort_on_overflow中断,应该应用于半开放队列吗?

提前致谢!

回答你的第一个问题:是的。 那么,无论如何,我个人认为,不要个人认为。 问题是,你正试图设置你的TCP栈的限制,而你有自己的负载均衡器前面有很多计数器和选项。 如果将自己限制在TCP堆栈中,那么当遇到这些限制时,会遇到更多的问题。 我会检查并保持loadbalancer本身的限制。 设置会话计数器,或者创build一些健康脚本来validation服务器的健康状况。 在达到限制时,您可以拒绝新的传入请求,或者在将后端设置为已满时将其redirect到另一个服务器。 你被Apache的限制所束缚,而不是你的操作系统或haproxy,所以要尽量远离系统限制,通过控制你的Apache到达它的负载。

我想这也是你的第二个问题。

第三个问题的答案比较复杂,我不认为你想深入这个问题的深处。 在我看来,达到TCP溢出状态在调整服务器以维持高负载和stream量方面已经太过分了。

这是我的两分钱,希望它有帮助。