Apache mod_proxy_ajp模块过早地将流量发送到备用后端服务器

Apache mod_proxy_ajp模块过早地将流量发送到备用后端服务器,apache,tomcat,mod-proxy,ajp,mod-proxy-ajp,Apache,Tomcat,Mod Proxy,Ajp,Mod Proxy Ajp,我们有一对Apache2.4Web服务器web02,web03运行mod_proxy_ajp,与一对Tomcat 7.0.59服务器app02,app03对话 app03上的Tomcat服务器是一个备用服务器,除非app02完全脱机,否则不应获取流量 web02和web03上的Apache配置: 在我们的Apache日志中有数百条这样的消息 关于让Apache坚持使用app02(除非它完全脱机)的设置有什么建议吗?您在Tomcat连接器中遇到线程耗尽问题,导致httpd认为app02处于错误状态

我们有一对Apache2.4Web服务器web02,web03运行mod_proxy_ajp,与一对Tomcat 7.0.59服务器app02,app03对话

app03上的Tomcat服务器是一个备用服务器,除非app02完全脱机,否则不应获取流量

web02和web03上的Apache配置:

在我们的Apache日志中有数百条这样的消息


关于让Apache坚持使用app02(除非它完全脱机)的设置有什么建议吗?

您在Tomcat连接器中遇到线程耗尽问题,导致httpd认为app02处于错误状态,从某种意义上说,它是

简单的回答是将Tomcat AJP连接器切换为使用protocol=org.apache.coyote.AJP.AjpNioProtocol

答案很长,嗯,相当长

mod_jk在httpd和Tomcat之间使用持久连接。这方面的历史论据是绩效。它节省了为每个请求建立新TCP连接的时间。通常,测试表明此参数不成立,并且建立新TCP连接或执行CPING/CPONG以确认连接有效所需的时间(如果使用持久连接,则需要执行此操作)与此时间几乎相同。mod_jk的默认设置是无Regaredless、持久连接

当使用持久连接时,mod_jk为每个httpd工作线程创建一个连接,并将该连接缓存在工作线程中

Tomcat 7.x中默认的AJP连接是BIO连接器。此连接器使用阻塞I/O,每个连接需要一个线程

当httpd配置的工作线程数超过Tomcat的线程数时,就会出现问题。起初一切都很好。当一个httpd工作进程遇到需要传递给Tomcat的第一个请求时,mod_jk为该httpd工作进程创建持久连接,并为该请求提供服务。该httpd工作程序处理的需要传递给Tomcat的后续请求将使用该缓存连接。请求被有效地随机分配给httpd工作人员。随着越来越多的httpd工作人员看到他们需要传递给Tomcat的第一个请求,mod_jk为每个工作人员创建必要的持久连接。与Tomcat的许多连接可能大部分处于空闲状态。空闲的程度取决于httpd上的负载以及传递给Tomcat的请求的比例

一切都很好,直到更多的httpd工作人员需要创建到Tomcat的连接,使Tomcat具有线程。请记住,Tomcat AJP BIO连接器要求每个连接有一个线程,因此maxThreads本质上是Tomcat允许的最大AJP连接数。此时mod_jk无法创建请求,因此故障转移过程启动

有两种解决办法。第一个——我上面描述的那个——是删除每个连接一个线程的限制。通过切换到NIO AJP连接器,Tomcat使用轮询器线程来维持1000个连接,只将要处理的数据传递给线程进行处理。Tomcat处理的限制是maxThreads是Tomcat可以在该连接器上处理的最大并发请求数

第二种解决方案是禁用持久连接。mod_jk创建一个连接,将其用于单个请求,然后关闭它。这减少了mod_jk在httpd和Tomcat之间任何一点所需的连接数量


对不起,上面的文字太多了。我也在各种演示中介绍了这一点,包括。

您在Tomcat连接器中遇到线程耗尽问题,导致httpd认为app02处于不良状态,从某种程度上说,是这样的

简单的回答是将Tomcat AJP连接器切换为使用protocol=org.apache.coyote.AJP.AjpNioProtocol

答案很长,嗯,相当长

mod_jk在httpd和Tomcat之间使用持久连接。这方面的历史论据是绩效。它节省了为每个请求建立新TCP连接的时间。通常,测试表明此参数不成立,并且建立新TCP连接或执行CPING/CPONG以确认连接有效所需的时间(如果使用持久连接,则需要执行此操作)与此时间几乎相同。mod_jk的默认设置是无Regaredless、持久连接

当使用持久连接时,mod_jk为每个httpd工作线程创建一个连接,并将该连接缓存在工作线程中

Tomcat 7.x中默认的AJP连接是BIO连接器。此连接器使用阻塞I/O,每个连接需要一个线程

当httpd配置的工作线程数超过Tomcat的线程数时,就会出现问题。起初一切都很好。当httpd工作者遇到需要传递给Tomcat的第一个请求时,mod_jk创建peri 为该httpd工作者提供支架连接,并提供请求。该httpd工作程序处理的需要传递给Tomcat的后续请求将使用该缓存连接。请求被有效地随机分配给httpd工作人员。随着越来越多的httpd工作人员看到他们需要传递给Tomcat的第一个请求,mod_jk为每个工作人员创建必要的持久连接。与Tomcat的许多连接可能大部分处于空闲状态。空闲的程度取决于httpd上的负载以及传递给Tomcat的请求的比例

一切都很好,直到更多的httpd工作人员需要创建到Tomcat的连接,使Tomcat具有线程。请记住,Tomcat AJP BIO连接器要求每个连接有一个线程,因此maxThreads本质上是Tomcat允许的最大AJP连接数。此时mod_jk无法创建请求,因此故障转移过程启动

有两种解决办法。第一个——我上面描述的那个——是删除每个连接一个线程的限制。通过切换到NIO AJP连接器,Tomcat使用轮询器线程来维持1000个连接,只将要处理的数据传递给线程进行处理。Tomcat处理的限制是maxThreads是Tomcat可以在该连接器上处理的最大并发请求数

第二种解决方案是禁用持久连接。mod_jk创建一个连接,将其用于单个请求,然后关闭它。这减少了mod_jk在httpd和Tomcat之间任何一点所需的连接数量


对不起,上面的文字太多了。我在各种演示中也谈到了这一点,包括。

完全脱机的标准是什么?@DusanBajic我们只想在app02 Tomcat处于不良状态并停止服务页面或出现故障时将流量切换到app03,但这不是您现在的情况:无法连接到后端:app02,所以app02 Tomcat处于坏状态并停止了页面服务,所以流量转向app03我认为这不是期望的行为,但是您必须更准确地了解坏状态和停止页面服务的含义。更一般地说,在apache中微调负载平衡是可行的,也许您可能想考虑切换到更现代的反向代理,像haproxy或nginx?完全离线的标准是什么?@DusanBajic我们只想在app02 Tomcat处于不良状态并停止服务页面或出现故障时将流量切换到app03,但这不是您现在的情况:无法连接到后端:app02,因此app02 Tomcat处于不良状态并停止服务页面,所以流量翻转到APP03,我假设这不是期望的行为,但是你必须更精确地知道坏状态和停止服务页面意味着什么,更一般地说,在Apache中微调负载平衡可能是可行的,也许你可能想考虑切换到更现代的反向代理,比如HAXPROX或NGIXX?
<Proxy balancer://ajp_cluster>
  BalancerMember ajp://app02:8009 route=worker1 ping=3 retry=60
  BalancerMember ajp://app03:8009 status=+R route=worker2 ping=3 retry=60
  ProxySet stickysession=JSESSIONID|jsessionid lbmethod=byrequests
</Proxy>
<Connector protocol="AJP/1.3" URIEncoding="UTF-8" port="8009" />
[Thu Sep 12 14:23:28.028162 2019] [proxy_ajp:error] [pid 24234:tid 140543375898368] (70007)The timeout specified has expired: [client 207.xx.xxx.7:1077] AH00897: cping/cpong failed to 10.160.160.47:8009 (app02)
[Thu Sep 12 14:23:28.028196 2019] [proxy_ajp:error] [pid 24234:tid 140543375898368] [client 207.xx.xxx.7:1077] AH00896: failed to make connection to backend: app02
[Thu Sep 12 14:23:28.098869 2019] [proxy_ajp:error] [pid 24135:tid 140543501776640] [client 207.xx.xxx.7:57809] AH01012: ajp_handle_cping_cpong: ajp_ilink_receive failed, referer: https://site.example.com/cart
[Thu Sep 12 14:23:28.098885 2019] [proxy_ajp:error] [pid 24135:tid 140543501776640] (70007)The timeout specified has expired: [client 207.xx.xxx.7:57809] AH00897: cping/cpong failed to 10.160.160.47:8009 (app02), referer: https://site.example.com/cart