用tengine 2.3.0 ,安装了ngx_http_upstream_check_module 模块,希望用它来自动监控后台服务的健康。根据文档,在upstream 里添加 check interval=3000 rise=2 fall=5 timeout=1000 type=http; 重启nginx后,访问出现502错误。 把check指定注释后,再启动nginx又可以访问。
[alibaba/tengine]upstream 添加了check interval=3000 指令后; 访问不到后台的服务
回答
tengine 2.3.0 ,安装了ngx_http_upstream_check_module 模块。 配置文件中 upstream myserver { server 192.168.11.1:8080 weight=10; server 192.168.11.1:8081 weight=30; }这样工作正常。负载均衡正常工作。 但是,加了 check interval=3000 rise=2 fall=5 timeout=1000 type=http; upstream myserver { server 192.168.11.1:8080 weight=10; server 192.168.11.1:8081 weight=30;
check interval=3000 rise=2 fall=5 timeout=1000 type=http;
}
健康检查一直失败,导致不能访问服务。 实际上,后台服务一直正常运行。
@piraterocy 你要确认健康检查 的 响应是不是 200。你可以查看 后台服务 的 日志,或者tcpdump抓包查看健康检查请求和响应。
健康检查失败 Index | Upstream | Name | Status | Rise counts | Fall counts | Check type | Check port |
---|---|---|---|---|---|---|---|
0 | myserver | 192.168.11.1:8080 | down | 0 | 261 | http | 0 |
1 | myserver | 192.168.11.1:8081 | down | 0 | 249 | http | 0 |
难道要求我被检查的服务,还要添加一个特殊的心跳接口?
补充说明一下,后台的服务是spring boot的
@piraterocy
你可以 根据 链接 中配置 check_http_send
指令来模拟正确的http请求, 以及使用check_http_expect_alive
指令指定期望的响应状态码。
具体 该填什么,还需要根据你具体后台业务的逻辑来决定,这个你需要自己调试。
@mrpre upstream myserver { server 192.168.11.1:8080 weight=10; server 192.168.11.1:8081 weight=30;
check interval=3000 rise=2 fall=5 timeout=1000 type=http;
check_keepalive_requests 100;
check_http_send "HEAD / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
健康检查失败 Index Upstream Name Status Rise counts Fall counts Check type Check port 0 myserver 192.168.11.1:8080 down 0 261 http 0 1 myserver 192.168.11.1:8081 down 0 249 http 0 难道要求我被检查的服务,还要添加一个特殊的心跳接口?
补充说明一下,后台的服务是spring boot的
这里健康检查反馈检查都失败,所以关键问题是你要看下为啥检查请求你的源站无法返回200应答。
Fall counts: 261
Fall counts: 249
如何检查源站,方法很多,比如
- 抓包看健康检查的请求的应答结果
- 模拟健康检查请求自己请求一下:
check_http_send "HEAD / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n";
@chobits 请问如何模拟,不胜感激 模拟健康检查请求自己请求一下:check_http_send "HEAD / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n";
我在bash中直接输入 [root@k8s-node-2 ~]# check_http_send "HEAD / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n" -bash: check_http_send: command not found
================================= 我在nginx机器上,直接访问服务,返回正常的 [root@k8s-node-2 ~]# curl -X GET http://192.168.11.1:8081/rest/course/getAdminNums2 {"code":"0","isSuc":true,"resultType":null,"message":"ok","result":"实例 app01 端口 8081 打印出来的日志--20"}[root@k8s-node-2 ~]#
最后实在没有办法 check_http_expect_alive http_2xx http_3xx http_4xx; 最后加了 http_4xx, 才认为是健康。
但是这个不科学啊!!!!
check_http_send "HEAD / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n";
这里的意思是指nginx.conf里的配置,而不是命令行。请求的内容(如果不理解请学习下http protocol)就是 check_http_send的指令的参数。
如果 你期望 以下请求作为健康检查用
curl -X GET http://192.168.11.1:8081/rest/course/getAdminNums2
你应该这么配置
check_http_send "GET /rest/course/getAdminNums2 HTTP/1.1\r\nHost: <这里你要自己填写合适的host>\r\nConnection: keep-alive\r\n\r\n"
curl -v的参数可以展示出HTTP请求内容,你把此内容编辑到check_http_send的参数里即可。
@chobits 非常感谢你的悉心指点。
还有一个问题。check_http_send "GET /rest/course/getAdminNums2 HTTP/1.1\r\nHost: <这里你要自己填写合适的host>\r\nConnection: keep-alive\r\n\r\n"
我有二个相同的服务
http://192.168.11.1:8080
http://192.168.11.1:8081
这里难道要配置二条吗?
两个服务属于负载均衡的节点,理论上,tengine是会逐次请求每个节点的。因此,不存在配置两个情况。check_http_send 检查的url,只要支持能访问200就可,不一定非要用业务url
@bukebuhao 假设,有3个功能一样服务,做成集群。 分别部署在 192.168.1.11 , 192.168.1.12, 192.168.1.13. check_http_send 怎么配? 我试过不配Host, 但是不行。系统3个服务一个都找不到。
upstream myserver { server 192.168.1.11 weight=10; server 192.168.1.12 weight=30; server 192.168.1.13 weight=30;
check interval=3000 rise=2 fall=5 timeout=1000 type=http;
check_keepalive_requests 1;
check_http_send "HEAD / HTTP/1.1\r\nHost: <这里怎么配>\r\nConnection: keep-alive\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
@piraterocy 你还是没理解上面说的。
check_http_send
里面的值是需要你自己定义的,其结果必须是能让server返回 200,你不仅仅只是修改Host这么简单。
check_http_send
这个值填什么,并不是别人可以告诉你的,而是需要你自己不断调试,调试到server回复200为止,因为server是你自己的业务。
如果你说,这三个ip,需要不一样的check_http_send
检测,那就无解了,你三个一模一样的服务,理应能够处理一样的请求。你必须自己找到共性,然后觉得 check_http_send
的值。
@mrpre 我完全理解上面说的, 下面的是我的配置,如果把Host配进去,正常工作。 否则,二个服务一个都检测不到。 请问为什么? 再深入一步,如果二个server是不同的ip,又该怎么配? upstream myserver { server 192.168.11.1:8080 weight=10; server 192.168.11.1:8081 weight=30;
check interval=3000 rise=2 fall=5 timeout=1000 type=http;
check_keepalive_requests 1;
check_http_send "HEAD / HTTP/1.1\r\nHost: 192.168.11.1\r\nConnection: keep-alive\r\n\r\n"; #可以,正常工作
check_http_send "HEAD / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n"; #不行,检测不到
check_http_expect_alive http_2xx http_3xx ;
}
check_http_send "HEAD / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n";
这里的意思是指nginx.conf里的配置,而不是命令行。请求的内容(如果不理解请学习下http protocol)就是 check_http_send的指令的参数。如果 你期望 以下请求作为健康检查用
curl -X GET http://192.168.11.1:8081/rest/course/getAdminNums2
你应该这么配置
check_http_send "GET /rest/course/getAdminNums2 HTTP/1.1\r\nHost: <这里你要自己填写合适的host>\r\nConnection: keep-alive\r\n\r\n"
curl -v的参数可以展示出HTTP请求内容,你把此内容编辑到check_http_send的参数里即可。
@chobits 如果我有3个物理机器,部署了相同的服务做集群。 请问,你提到的Host要怎么配?
@piraterocy "如果把Host配进去,正常工作。 否则,二个服务一个都检测不到。 请问为什么?"
这个难道不是需要看看服务的逻辑吗?对于Tengine而言,这个支持字符串,没有任何意义,Tengine只需要将次字符串发送至你配置的服务,然后等到响应。
理论上Host是必须配置的,RFC规定。至于配置成什么Host,完全是服务的限制,这个应该在服务端去寻找答案。
”如果二个server是不同的ip,又该怎么配?“ check_http_send
和你配置的多个server是不是一样的ip没有关系,你只要提供一样的服务,那么个理应该就能使用相同的check_http_send
进行检测。
问题已经彻底搞明白了,特别感谢 @mrpre @chobits . 这里我总结一下,方便后来的码农。
问题出在对http 1.1 规范的理解上, 按照http1.1 请求头里必须包含Host属性,否则返回404. 所以,这里配置成 check_http_send "HEAD / HTTP/1.1\r\nHost: www.goushi.com\r\nConnection: keep-alive\r\n\r\n"; 就可以, 哪怕是【www.goushi.com】狗屎都可以。我这里没有虚拟主机,所以Host对我么有用。 顺便吐槽一下官方文档的例子,采用http1.1却不加Host属性,容易误导。
或者,check_http_send "HEAD / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n"; 也可以。 这里的【http 是1.0】
至于发送的目的ip, 就是 upstream 里指定的每个 server
希望对看到的朋友有帮助!
顺便吐槽一下官方文档的例子,采用http1.1却不加Host属性,容易误导。 或者,check_http_send "HEAD / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n"; 也可以。这里的【http 是1.0】
感谢建议,后面我们会加个pr来修复文档,这里确实描述不当容易误导。