Nginx健康检查nginx_upstream_check_module
nginx健康检查介绍:
主动健康检查,nignx定时主动地去ping后端的服务列表,当发现某服务出现异常时,把该服务从健康列表中移除,当发现某服务恢复时,又能够将该服务加回健康列表中。nginx自带的upstream轮询可以实现业务接口切换, nginx有一个开源的实现nginx_upstream_check_module模块能更加平滑的进行业务切换
nginx自带健康检查的缺陷:
- Nginx只有当有访问时后,才发起对后端节点探测。
- 如果本次请求中,节点正好出现故障,Nginx依然将请求转交给故障的节点,然后再转交给健康的节点处理。所以不会影响到这次请求的正常进行。但是会影响效率,因为多了一次转发
- 自带模块无法做到预警
- 被动健康检查, 应用服务器没挂,但是数据库连接池不够导致应用假死, Nginx任然认为它是一个正常节点, 继续把请求打在这台服务器上
使用第三访模块nginx_upstream_check_module:
- 区别于nginx自带的非主动式的心跳检测,淘宝开发的tengine自带了一个提供主动式后端服务器心跳检测模块
- 若健康检查包类型为http,在开启健康检查功能后,nginx会根据设置的间隔向指定的后端服务器端口发送健康检查包,并根据期望的HTTP回复状态码来判断服务是否健康。
- 后端真实节点不可用,则请求不会转发到故障节点
- 故障节点恢复后,请求正常转发
介绍nginx_upstream_check_module模块针对nginx1.20+
一、模块下载解压
nginx下载地址:https://nginx.org/en/download.html
nginx_upstream_check_module模块下载:
github地址: https://github.com/yaoweibin/nginx_upstream_check_module
taobao官网:http://tengine.taobao.org/document_cn/http_upstream_check_cn.html
下载
https://codeload.github.com/yaoweibin/nginx_upstream_check_module/zip/master
上传到服务器并解压
bash
tar -zxvf nginx-1.22.1.tar.gz
unzip nginx_upstream_check_module-master.zip
二、官方步骤
安装
配置
三、自己安装步骤跟着官网来
安装patch
nginx
yum install -y patch
#(重点: 已安装nginx一定是停止运行状态的)
# 注意check_1.20.1+.patch 版本要跟你的nginx版本对应上
#(一定要执行这行命令, 要不然健康检查会报错: http upstream check module can not find any check server, make sure you've added the check servers, client: xxx.xxx.xxx.xxx, server: localhost, request: "GET /status HTTP/1.1", host: "xxx.xxx.xxx.xxx:8087")
# 执行patch命令一定要在(nginx源码目录)
patch -p1 < /home/app/nginx_upstream_check_module-master/check_1.20.1+.patch
安装nginx和模块nginx_upstream_check_module-master
nginx
# 进入nginx安装包目录, 执行下面命令, 根据自己的实际情况安装对应参数值改成自己的 (重点: nginx一定是停止运行状态的)
./configure --user=app --group=app --with-http_ssl_module --with-threads --with-file-aio --with-http_stub_status_module --add-module=/opt/app/nginx_upstream_check_module-master/ --prefix=/opt/app/nginx
make && make install
--prefix: nginx主目录
--user: nginx启动用户
--group: nginx启动组
--add-module: 添加模块
--with-http_ssl_model: 启动ssl模块
配置nginx
Nginx会每隔3000毫秒(3秒)向每个服务器发送一个GET请求/dist-app-ytgz-approve/health_check接口ip是对应的server后面的ip端口。如果服务器连续两次(rise=2)返回2xx或3xx状态码,那么Nginx就认为这个服务器是健康的。如果服务器连续五次(fall=5)没有响应或者返回非2xx或3xx的状态码,那么Nginx就认为这个服务器是不健康的,会自动将其剔除。
为什么请求接口带/dist-app-ytgz-approve那是因为我后台application.yaml里面配置的server.servlet.context-path: /dist-app-ytgz-approve
nginx
http {
upstream approve {
server xxx.xxx.xxx.xxx:9010;
server xxx.xxx.xxx.xxx:9090;
ip_hash;
check interval=3000 rise=2 fall=5 timeout=5000 type=http;
check_http_send "GET /dist-app-ytgz-approve/health_check HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
# Nginx会每隔3000毫秒(3秒)向每个服务器发送一个GET请求/dist-app-ytgz-approve/health_check接口ip是对应的server后面的ip端口。如果服务器连续两次(rise=2)返回2xx或3xx状态码,那么Nginx就认为这个服务器是健康的。如果服务器连续五次(fall=5)没有响应或者返回非2xx或3xx的状态码,那么Nginx就认为这个服务器是不健康的,会自动将其剔除。
}
server {
listen 8087;
server_name localhost;
location /dist-app-ytgz-approve {
proxy_pass http://approve;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;
add_header X-Route-Ip $upstream_addr;
add_header X-Route-Status $upstream_status;
}
location /status {
check_status;
access_log off;
}
}
}
后台健康检查接口
java
package com.dist.ytgz.approve.controller;
import com.dist.common.util.LogUtil;
import com.dist.ytgz.approve.service.HealthCheckService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* TODO
*
* @author <a href="mailto:zhangxiao@dist.com.cn">Zhang Xiao</a>
* @since
*/
@RequestMapping
@RestController
public class HealthCheckController {
@Autowired
private HealthCheckService healthCheckService;
@GetMapping("/health_check")
public ResponseEntity<String> healthCheck() {
// 这里可以添加检查数据库连接数的逻辑
// 如果数据库连接数正常,返回200状态码
// 如果数据库连接数耗尽,返回503状态码
Long startTime = System.currentTimeMillis();
boolean isDatabaseHealthy = healthCheckService.checkDatabaseHealth();
if (isDatabaseHealthy) {
Long endTime = System.currentTimeMillis();
LogUtil.error("健康检查总共耗时: " + (endTime-startTime) / 1000.0);
return ResponseEntity.ok("Healthy");
} else {
Long endTime = System.currentTimeMillis();
LogUtil.error("不健康检查总共耗时: " + (endTime-startTime) / 1000.0);
return ResponseEntity.status(503).body("Unhealthy");
}
}
}
package com.dist.ytgz.approve.service.impl;
import com.dist.ytgz.approve.service.HealthCheckService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.persistence.EntityManager;
import javax.persistence.Query;
/**
* TODO
*
* @author <a href="mailto:zhangxiao@dist.com.cn">Zhang Xiao</a>
* @since
*/
@Service
public class HealthCheckServiceImpl implements HealthCheckService {
@Autowired
private EntityManager em;
@Override
public boolean checkDatabaseHealth() {
try {
// 这里的SQL语句应该替换为适合您的数据库的语句
Query query = em.createNativeQuery("SELECT count(1) from dual");
query.getSingleResult();
return true;
} catch (Exception e) {
// 如果查询失败,那么可能是数据库连接数耗尽,或者数据库服务器出现了其他问题
return false;
}
}
}
四、启动nginx
nginx健康检查的日志信息
nginx服务器状态
server number: 是后端服务器的数量
generation: 是Nginx reload的次数
Index: 是服务器的索引
Upstream: 是在配置中upstream的名称
Name: 是服务器IP:PORT
Status: 是服务器的状态
Rise counts: 是服务器连续检查成功的次数
Fall counts: 是连续检查失败的次数
Check type: 是检查的方式
Check port: 是后端专门为健康检查设置的端口