测试场景1:已经进入应用的请求,请求尚未响应完毕。将haproxy此应用的状态改成下线。请求是否能够正常响应到客户端。
测试场景2:已经进入应用的请求,将应用Kill -9 关闭掉,haproxy是否能够自动重试,将请求分发到其他应用。
1.在controller加入代码:
@RequestMapping("/testSlowResponse.do")
@ResponseBody
public String testSlowReponse() throws Exception{
for(int i=0;i<=30;i++){
Thread.currentThread().sleep(1000l);
System.out.println("res:" + i+" wait");
}
return "OK";
}
2.haproxy配置:
listen admin_status
mode http
bind 0.0.0.0:48800
stats enable
stats uri /xxh_status
stats auth xxh:xxh666
option httplog
listen web_haproxy_test
mode tcp
bind 0.0.0.0:8003
option tcplog
option httpchk /xxh/guest-access/check.jsp (重命名此JSP来使应用下线)
balance roundrobin
server web_77_1 192.16.50.77:8001 check port 8001 inter 3s rise 2 fall 3
server web_77_2 192.16.50.77:8002 check port 8002 inter 3s rise 2 fall 3
server web_77_3 192.16.50.77:8003 check port 8003 inter 3s rise 2 fall 3
场景1:
1.1.用浏览器访问/testSlowResponse.do
1.2.看三台服务器的日志,正在打印的就是收到请求的应用
1.3.重命名次应用的check.jsp为check.jsp.bak。观察到haproxy的监控页面此应用变成红色(即下线)
1.4.30S之后,浏览器能够正常收到请求。
测试结果:已经进入应用的请求,即使在haproxy上将其改成下线,请求依然能够的到正常响应。IE,CHROME都可以
场景2:
1.1.用浏览器访问/testSlowResponse.do
1.2.看三台服务器的日志,正在打印的就是收到请求的应用
1.3.直接将该应用Kill -9 掉。
1.4.浏览器观察到收到EMPTY_RESPONSE_BODY错误
1.5.但是浏览器会自动再次发起请求。
测试结果:已经进入应用的请求,即使kill -9 掉应用。haproxy不会向客户端发送重定向请求,也不会将改请求分发到其他正常的应用。但是chrome浏览器根据EMPTY_RESPONSE_BODY错误自动发起了请求。但是IE浏览器不会。
总结:如果要优雅停机,正确的步骤应该是先将haproxy的应用逐个下线,避免此应用再收到新的请求,等待已经进入应用的请求都响应完毕。在部署,再将haproxy的应用逐个上线。虽然chrome内核会自动再次请求,但是我们并不能保证所有的客户端的浏览器都用chrome.
如何知道所有请求都响应完毕:拦截所有的controller,添加atomicLong成员变量,每次请求进入加+1,结束减1(正常结束和异常都需要减)