[alibaba/tengine]upstream 添加了check interval=3000 指令后; 访问不到后台的服务

2024-07-12 843 views
3
Question

用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又可以访问。

回答

8

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;
    }

健康检查一直失败,导致不能访问服务。 实际上,后台服务一直正常运行。

3

@piraterocy 你要确认健康检查 的 响应是不是 200。你可以查看 后台服务 的 日志,或者tcpdump抓包查看健康检查请求和响应。

2
健康检查失败 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的

1

@piraterocy 你可以 根据 链接 中配置 check_http_send指令来模拟正确的http请求, 以及使用check_http_expect_alive指令指定期望的响应状态码。
具体 该填什么,还需要根据你具体后台业务的逻辑来决定,这个你需要自己调试。

3

@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;  
}
7
健康检查失败 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

如何检查源站,方法很多,比如

  1. 抓包看健康检查的请求的应答结果
  2. 模拟健康检查请求自己请求一下:check_http_send "HEAD / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n";
3

@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 ~]#

4

最后实在没有办法 check_http_expect_alive http_2xx http_3xx http_4xx; 最后加了 http_4xx, 才认为是健康。

但是这个不科学啊!!!!

1

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的参数里即可。

4

@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

这里难道要配置二条吗?

1

两个服务属于负载均衡的节点,理论上,tengine是会逐次请求每个节点的。因此,不存在配置两个情况。check_http_send 检查的url,只要支持能访问200就可,不一定非要用业务url

4

@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;  

}

4

@piraterocy 你还是没理解上面说的。

check_http_send 里面的值是需要你自己定义的,其结果必须是能让server返回 200,你不仅仅只是修改Host这么简单。

check_http_send这个值填什么,并不是别人可以告诉你的,而是需要你自己不断调试,调试到server回复200为止,因为server是你自己的业务。

如果你说,这三个ip,需要不一样的check_http_send检测,那就无解了,你三个一模一样的服务,理应能够处理一样的请求。你必须自己找到共性,然后觉得 check_http_send的值。

5

@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  ;  
}
6

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要怎么配?

2

@piraterocy "如果把Host配进去,正常工作。 否则,二个服务一个都检测不到。 请问为什么?"
这个难道不是需要看看服务的逻辑吗?对于Tengine而言,这个支持字符串,没有任何意义,Tengine只需要将次字符串发送至你配置的服务,然后等到响应。
理论上Host是必须配置的,RFC规定。至于配置成什么Host,完全是服务的限制,这个应该在服务端去寻找答案。

”如果二个server是不同的ip,又该怎么配?“ check_http_send和你配置的多个server是不是一样的ip没有关系,你只要提供一样的服务,那么个理应该就能使用相同的check_http_send进行检测。

1

问题已经彻底搞明白了,特别感谢 @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

希望对看到的朋友有帮助!

6

顺便吐槽一下官方文档的例子,采用http1.1却不加Host属性,容易误导。 或者,check_http_send "HEAD / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n"; 也可以。这里的【http 是1.0】

感谢建议,后面我们会加个pr来修复文档,这里确实描述不当容易误导。