Nginx 负载均衡实现上游服务健康检查
Nginx 负载均衡实现上游服务健康检查
Author:Arsen
Date:2024/06/20
前言
如果你使用云负载均衡(如阿里云 CLB),我们可以通过配置健康检查来实现后端服务故障转移(通过 4/7 层实现)。而如果你使用 Nginx 作为负载均衡器时,又如何实现后端(上游)服务器的健康检查呢?要解决这个问题,就需要使用到 Nginx 的 nginx_upstream_check_module
模块,因为在不使用 nginx_upstream_check_module
模块的情况下,Nginx 的常规负载均衡机制并不具备自动移除不健康服务器的功能。默认情况下,Nginx 不会主动检查上游服务器的健康状态,因此无法在服务器出现故障时自动将其从负载均衡池中移除。
接下来将演示如何通过 nginx_upstream_check_module
实现负载均衡上游服务器的故障转移。
注意:nginx_upstream_check_module
是一个第三方模块,不属于官方 NGINX 发行版的一部分,因此需要我们手动将其集成到 NGINX 中,而不是通过官方预编译的 NGINX 包来使用它。
一、Nginx 部署并新增模块
1、下载 nginx、nginx_upstream_check_module 源码包
nginx_upstream_check_module 模块地址:https://github.com/yaoweibin/nginx_upstream_check_module
wget http://nginx.org/download/nginx-1.18.0.tar.gz
wget https://github.com/yaoweibin/nginx_upstream_check_module/archive/refs/tags/v0.4.0.tar.gz
2、解压安装包
tar xzf v0.4.0.tar.gz
tar xzf nginx-1.18.0.tar.gz
3、为 NGINX 源码打补丁
# 安装补丁工具
yum install -y patch
补丁列表(在我们上面下载的第三方模块中):
在补丁文件列表中,没有直接与 nginx-1.18.4
对应的补丁文件。通常情况下,选择一个版本号最接近但不高于你的 NGINX 版本的补丁文件会是最佳选择。如上图,使用 check_1.16.1+.patch
,因为它是最接近 1.18.0
的可用补丁且不高于1.18.0
。
# 开始打补丁
cd nginx-1.18.0/
patch -p1 < ../nginx_upstream_check_module-0.4.0/check_1.16.1+.patch
4、开始编译安装
关于模块安装注意事项,可以查看有道云笔记 nginx 编译安装部分。
# 安装nginx编译安装的依赖环境yum -y install make gcc gcc-c++ pcre pcre-devel gd-devel openssl openssl-devel zlib zlib-devel
./configure \
--with-http_gzip_static_module \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-pcre \
--with-file-aio \
--with-http_realip_module \
--without-http_scgi_module \
--without-http_uwsgi_module \
--without-http_fastcgi_module \
--with-compat --add-module=../nginx_upstream_check_module-0.4.0# --with-compat 是一个用于构建兼容模块的选项,它允许你编译 NGINX 时,使其模块在不同版本的 NGINX 上保持兼容。
# 这里仅仅是测试使用,我就不具体规划路径了(如安装路径、日志路径等),使用默认即可
如上图,Nginx 编译完成,默认输出了相关的工作路径,接下来就根据上图路径开始安装了:
make && make install
此时我们需要验证新增的第三方模块是否被成功集成:
二、健康检查配置
2.1 准备 nodeJS 应用程序
1、node 安装
过程略.
2、安装 pm2 守护进程管理器
npm install -g pm2
3、创建测试项目并启动项目
vim /data/nginx-test-projects/node-js-demo/app-1.js
const http = require('http');const server = http.createServer((req, res) => {res.setHeader("Content-Type", "application/json");res.writeHead(200);res.end(`{ "status": "success", "message": "app-1 请求成功!\n" }`);
});server.listen(3001, 'localhost', () => {console.log('running on http://localhost:3001/');
});
vim /data/nginx-test-projects/node-js-demo/app-2.js
const http = require('http');const server = http.createServer((req, res) => {res.setHeader("Content-Type", "application/json");res.writeHead(200);res.end(`{ "status": "success", "message": "app-2 请求成功!\n" }`);
});server.listen(3002, 'localhost', () => {console.log('running on http://localhost:3002/');
});
vim /data/nginx-test-projects/node-js-demo/app-3.js
const http = require('http');const server = http.createServer((req, res) => {res.setHeader("Content-Type", "application/json");res.writeHead(200);res.end(`{ "status": "success", "message": "app-3 请求成功!\n" }`);
});server.listen(3003, 'localhost', () => {console.log('running on http://localhost:3003/');
});
启动应用:
pm2 start /data/nginx-test-projects/node-js-demo/app-1.js
pm2 start /data/nginx-test-projects/node-js-demo/app-2.js
pm2 start /data/nginx-test-projects/node-js-demo/app-3.js
2.2 Nginx 配置负载均衡健康检查
1、nginx 配置
vim /usr/local/nginx/conf/nginx.conf
http {upstream backend {server 127.0.0.1:8080;server 127.0.0.1:8081;check interval=3000 rise=2 fall=5 timeout=1000 type=http;check_http_send "HEAD / HTTP/1.0\r\n\r\n";check_http_expect_alive http_2xx http_3xx;}server {listen 80;location / {proxy_pass http://backend;}}
}
配置说明:
-
upstream backend { ... }
: 定义名为backend
的上游服务器组。 -
server 127.0.0.1:8080;
: 定义一个地址为127.0.0.1:8080
的上游服务器。 -
- 配置健康检查参数:
check interval=3000 rise=2 fall=5 timeout=1000 type=http;
interval=3000
: 每隔 3000 毫秒(3 秒)进行一次健康检查。rise=2
: 如果服务器连续通过 2 次健康检查,则认为它是健康的。fall=5
: 如果服务器连续 5 次健康检查失败,则认为它是故障的。timeout=1000
: 每次健康检查必须在 1000 毫秒(1 秒)内完成。type=http
: 指定进行 HTTP 健康检查。
-
check_http_send "HEAD / HTTP/1.0\r\n\r\n";
: 向服务器发送 HTTP HEAD 请求。 -
check_http_expect_alive http_2xx http_3xx;
: 如果服务器返回的状态码在 2xx 或 3xx 范围内,则认为服务器是健康的。
2、健康检查验证
while sleep 0.5; do curl http://192.168.56.120; done
后端服务健康情况时,是正常的负载均衡的:
这里我分两种情况来验证:
1)未配置 nginx_upstream_check_module 的情况
此时,我停掉 app-1
pm2 stop app-1
看看 nginx 的错误日志是否持续输出,如果持续输出,说明 nginx 一直在轮询请求后端上游服务,且请求不到,这就证明默认的 nginx 负载均衡模式下,并不能实现后端上游服务的健康检查,客户的请求依然会打到坏掉的 app-1 服务上。如下图,正符合我们的假设。
2)配置了 nginx_upstream_check_module 的情况
这里,我们先恢复后端服务,使 3 台都正常工作。然后我们保持请求不要断,继续将 app-1 stop 掉,看会不会故障转移到其他节点:判断是否转移其实就是你看 nginx 是否有如上图相同的错误日志持续输出,如果有,那证明这个检测模块我们就没配置正确,否则证明我们的检测模块生效,且将坏掉的 app-1 从负载均衡中摘掉,恢复时自动加入负载均衡。
停掉 app-1
pm2 stop app-1
再看看 Nginx 的错误日志:
这里你会注意到,此时的错误日志与上一张图的错误日志不同了,那他们的区别是什么呢?
1)未配置 nginx_upstream_check_module 的错误日志分析:
由于我们没有配置了 Nginx 健康检查,在连接已建立后,NGINX 尝试连接到上游服务器时,连接被拒绝而抛出如下错误日志:
2024/06/20 13:19:55 [error] 14553#0: *510 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.56.120, server: localhost, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:3001/", host: "192.168.56.120"
这通常是由于上游服务器未能正常启动或者未响应
客户端请求处理:
- 如果 NGINX 配置中没有健康检查,或者健康检查无法检测到上游服务器的问题,客户端的请求可能会继续被发送到无法处理请求的上游服务器。
- 这种情况下,客户端请求可能会因为上游服务器的问题而遭遇连接失败或者长时间的等待响应。
2)配置了 nginx_upstream_check_module 的错误日志分析:
由于我们配置了 Nginx 健康检查,在连接已建立后,NGINX 尝试发送数据到上游服务器时,连接被拒绝而抛出如下错误日志:
2024/06/20 13:35:06 [error] 15030#0: send() failed (111: Connection refused)
2024/06/20 13:35:09 [error] 15030#0: send() failed (111: Connection refused)
2024/06/20 13:35:12 [error] 15030#0: send() failed (111: Connection refused)
2024/06/20 13:35:15 [error] 15030#0: send() failed (111: Connection refused)
在连接建立后,即使上游服务器通过了健康检查确认为健康状态,但在实际发送数据时,服务器可能由于负载过高、连接限制或其他原因拒绝处理请求。
客户端请求处理:
- 配置了健康检查后,NGINX 会在发送实际请求之前先检查上游服务器的健康状态。
- 如果上游服务器在健康检查时被标记为不可用,NGINX 将不会将客户端的请求发送到该上游服务器。
- 这种情况下,客户端的请求不会被打到处于故障状态的上游服务器,因为 NGINX 在发送请求之前会先确认上游服务器的可用性。
小结
1、nginx 未设置健康检查报错
这类报错是在连接建立阶段出现连接被拒绝的错误,通常因为上游服务器未能正常启动或者未响应。
2、nginx 设置了健康检查报错
康状态,但在实际发送数据时,服务器可能由于负载过高、连接限制或其他原因拒绝处理请求。
3、健康检查的目的
实现高可用。
—END
相关文章:
Nginx 负载均衡实现上游服务健康检查
Nginx 负载均衡实现上游服务健康检查 Author:Arsen Date:2024/06/20 目录 Nginx 负载均衡实现上游服务健康检查 前言一、Nginx 部署并新增模块二、健康检查配置2.1 准备 nodeJS 应用程序2.2 Nginx 配置负载均衡健康检查 小结 前言 如果你使用云负载均衡…...
小程序使用接口wx.getLocation配置
开通时需详细描述业务,否则可能审核不通过 可能需要绑定腾讯位置服务,新建应该,绑定到小程序 配置 权限声明:在使用wx.getLocation前,需要在app.json的permission字段中声明对用户位置信息的使用权限,并提…...
Protobuf安装配置--附带每一步截图
Protobuf Protobuf(Protocol Buffers)协议是一种由 Google 开发的二进制序列化格式和相关的技术,它用于高效地序列化和反序列化结构化数据,通常用于网络通信、数据存储等场景。 为什么要使用Protobuf Protobuf 在许多领域都得到…...
力扣1019.链表中的下一个更大节点
力扣1019.链表中的下一个更大节点 从左到右 每个数确定下一个更大节点后 弹出栈中存下标 即res.size() class Solution {public:vector<int> nextLargerNodes(ListNode* head) {vector<int> res;stack<int> st;for(auto ihead;i;ii->next){while(!st.e…...
查询mysql库表的几个语句
1、查询某个数据库的所有表 SELECTtable_name FROMinformation_schema.TABLES WHEREtable_schema database_namedatabase_name替换成你需要查询的数据库名称 2、查询某张表的所有字段名称 SELECTCOLUMN_NAME,column_comment FROMinformation_schema.COLUMNS WHEREtable…...
【CT】LeetCode手撕—103. 二叉树的锯齿形层序遍历
目录 题目1- 思路2- 实现⭐103. 二叉树的锯齿形层序遍历——题解思路 2- ACM实现 题目 原题连接:103. 二叉树的锯齿形层序遍历 1- 思路 二叉树的层序遍历,遇到奇数时,利用 Collections.reverse() 翻转即可 2- 实现 ⭐103. 二叉树的锯齿形层…...
1958springboot VUE宿舍管理系统开发mysql数据库web结构java编程计算机网页源码maven项目
一、源码特点 springboot VUE宿舍管理系统是一套完善的完整信息管理类型系统,结合springboot框架和VUE完成本系统,对理解JSP java编程开发语言有帮助系统采用springboot框架(MVC模式开发) ,系统具有完整的源代码和数…...
LVS DR模式
Linux Virtual Server(LVS)是一个由Linux内核支持的负载均衡解决方案,旨在通过集群技术来提高服务器的可扩展性、可靠性和高可用性。LVS通过将客户端的请求分发到多个服务器上,从而实现负载均衡和容错。 目录 LVS的工作模式 DR模…...
myslql事务示例
在 MySQL 中,事务(Transaction)是一组要么全部执行,要么全部不执行的SQL语句。这可以确保数据的一致性和完整性。事务管理的核心包括四个属性,即原子性(Atomicity)、一致性(Consiste…...
解决Flutter应用程序的兼容性问题
哈喽呀,大家好呀,淼淼又来和大家见面啦,Flutter作为一个跨平台的移动应用开发框架,极大地简化了开发者同时在Android和iOS平台上构建应用的难度。然而,由于不同设备、操作系统版本以及Flutter框架本身的变化࿰…...
整合微信支付一篇就够了
需要的工具 微信开发小程序工具 需要的材料 关键步骤 postman获取微信access_token https://api.weixin.qq.com/cgi-bin/token?appid=wxfssafa629021&grant_type=client_credential&secret=701d213dsfsdfsfdss4fb274生成h5跳转小程序的链接 https://api.weixin.…...
视创云展为企业虚拟展厅搭建,提供哪些功能?
在当下数字化浪潮中,如何为用户创造更富生动性和真实感的展示体验,已成为企业营销策略的核心。借助视创云展的线上虚拟3D企业展厅搭建服务,利用3D空间漫游和VR技术的融合,可以为用户呈现出一个既真实又充满想象力的全景图或三维模…...
c++ 常用的锁及用法介绍和示例
2024/6/21 14:20:10 在 C++ 中,常用的锁主要包括以下几种:std::mutex、std::recursive_mutex、std::timed_mutex 和 std::shared_mutex。这些锁可以帮助我们在多线程编程中保护共享数据,避免竞争条件。以下是每种锁的介绍及其用法示例: std::mutex std::mutex 是最基本的互…...
PostgreSQL源码分析——口令认证
认证机制 对于数据库系统来说,其作为服务端,接受来自客户端的请求。对此,必须有对客户端的认证机制,只有通过身份认证的客户端才可以访问数据库资源,防止非法用户连接数据库。PostgreSQL支持认证方法有很多࿱…...
Stability-AI(图片生成视频)
1.项目地址 GitHub - Stability-AI/generative-models: Generative Models by Stability AI 2.模型地址 魔搭社区 3.克隆项目后,按照教程安装 conda create --name Stability python3.10 conda activate Stability pip3 install -r requirements/pt2.txt py…...
Linux机器通过Docker-Compose安装Jenkins发送Allure报告
目录 一、安装Docker 二、安装Docker Compose 三、准备测试用例 四、配置docker-compose.yml 五、启动Jenkins 六、配置Jenkins和Allure插件 七、创建含pytest的Jenkins任务 八、项目结果通知 1.通过企业微信通知 2.通过邮件通知 九、配置域名DNS解析 最近小编接到一…...
基于Gunicorn+Flask+Docker模型高并发部署
关于猫头虎 大家好,我是猫头虎,别名猫头虎博主,擅长的技术领域包括云原生、前端、后端、运维和AI。我的博客主要分享技术教程、bug解决思路、开发工具教程、前沿科技资讯、产品评测图文、产品使用体验图文、产品优点推广文稿、产品横测对比文…...
java:类型变量(TypeVariable)解析--基于TypeResolver实现将类型变量替换为实际类型
上一篇博客《java:类型变量(TypeVariable)解析–获取泛型类(Generic Class)所有的类型变量(TypeVariable)的实际映射类型》中介绍如何如何正确解析泛型类的类型变量(TypeVariable),获取对应的实际类型。 有了类型变量(TypeVariable)–实际类型的映射,我们…...
ru俄罗斯域名如何申请SSL证书?
我们日常看到的都是com这种国际域名比较普遍,尤其是主流网站,主要原因考虑的其通用性,那么对于地方性的域名大家很少看到,比如俄罗斯国家域名.ru大家还是有些陌生的,但要说中国.CN域名那你就很熟悉了。 有用户在申请过…...
python实现购物车的功能
模拟购物车,准备一个列表 goodList [{name:笔记本电脑,price:8000}, {name:鼠标, price:100}] 5个函数 1.加入购物车 2.收藏商品 3.去结算 4.删除购物车商品 5.清空购物车 购物车 cartList [] 收藏列表 collectSet {笔记本电脑,鼠标} 数据示例 去结算计算出总价…...
日元预计明年开始上涨
被称为“日元先生”的前大藏省(现财务省)财务官榊原英资预测,美元兑日元汇率将在今年底或2025年初逐步升至130。他认为,通缩时代已经过去,通货膨胀即将来临。 《日本经济新闻》6月5日报道,日本财务省于5月3…...
8、PHP 实现二进制中1的个数、数值的整数次方
题目: 二进制中1的个数 描述: 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。 <?phpfunction NumberOf1($n) {$count 0;if($n < 0){$n $n & 0x7FFFFFFF;$count;}while($n ! 0){$count;$n $n & ($n - 1…...
linux git凭证管理
linux git 凭证管理 解决命令行git登录github的问题,支持两步验证 同样适用于Azure Devops, Bitbucket 官网: https://github.com/git-ecosystem/git-credential-manager https://github.com/git-ecosystem/git-credential-manager/blob/release/docs/…...
WIC 图像处理初体验——读取像素的值
先放上运行结果: 可以发现红绿蓝是从后往前的。 必须以C方式编译代码! #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <wincodec.h>int main(void) {CoInitialize(nullptr);IWICImagingFactory* fac;CoCreateInstance(CLS…...
使用Server-Sent Events (SSE),并获取message里面的内容
什么是Server-Sent Events (SSE)? Server-Sent Events (SSE)是一种服务器推送技术,允许服务器向客户端(浏览器)发送实时消息。与WebSocket不同,SSE是单向通信,只能从服务器到客户端。SSE在HTML5中作为标准实现&#…...
LabVIEW项目管理中如何平衡成本、时间和质量
在LabVIEW项目管理中,平衡成本、时间和质量是实现项目成功的关键。通过制定详细的项目计划、合理分配资源、严格控制进度、进行质量保证和灵活应对变化,项目管理者可以有效地协调这三者的关系,确保项目按时、按质、按预算完成。 1. 制定详细…...
如何检查 Kubernetes 网络配置
简介 Kubernetes 是一个容器编排系统,可以管理集群中的容器化应用程序。在集群中保持所有容器之间的网络连接需要一些高级网络技术。在本文中,我们将简要介绍一些工具和技术,用于检查这种网络设置。 如果您正在调试连接问题,调查…...
如何将网站封装成App:小猪APP分发助你实现
你有没有想过,将你的网站变成一个App会是什么样子?想象一下,用户只需点击一下图标,就能立刻访问你的内容,而不是在浏览器中输入网址。这不仅提升了用户体验,还能增加用户粘性。这一切都可以通过将网站封装成…...
探索C嘎嘎的奇妙世界:第十六关---STL(vector的练习)
1.只出现一次的数字 我们可以使用异或运算来解决这个问题: 异或运算有一个重要的性质:两个相同的数进行异或运算结果为 0,任何数与 0 异或结果为其本身。对于数组中的元素,依次进行异或运算,出现两次的元素异…...
最新扣子(Coze)实战案例:扣子卡片的制作及使用,完全免费教程
🧙♂️ 大家好,我是斜杠君,手把手教你搭建扣子AI应用。 📜 本教程是《AI应用开发系列教程之扣子(Coze)实战教程》,完全免费学习。 👀 关注斜杠君,可获取完整版教程。👍Ἷ…...
tiktok跨境电商运营/福建seo优化
int atoi(const char *_Str) double atof(const char *_String) 将字符串_Str转换成整型/浮点型数并返回。 int isdigit(int _C) 如果_C是数字,则为true。 getline 这个函数接受两个参数:一个输入流对象和一个string对象。 函数从输入流的下一行读…...
经营性网站备案 上海/seo推广优化平台
使用Spreadsheet_Excel_Reader类,同时中文方面的问题是方法如下(Spreadsheet_Excel_Reader自带的例子,稍作修改): <?php require_once Excel/reader.php; $data new Spreadsheet_Excel_Reader(); $data->setOu…...
怎么做网站流量统计分析/镇江百度推广公司
以上内容发布于中国国际人才交流基金会/PMI(项目管理协会) 个人总结的中文报名7个重点注意点: 1.PMI账号编号账号密码(PMI英文官网账号一定要学员自己测试是否能登录,因为中文审核机构是一定会登录检查的)&…...
web服务器做网站/咨询公司
方法介绍 MapReduce是一种计算模型,简单的说就是将大批量的工作(数据)分解(MAP)执行,然后再将结果合并成最终结果(REDUCE)。这样做的好处是可以在任务被分解后,可以通过大…...
server2012 wordpress/百度公司电话是多少
客户现场反馈,top的检查结果中,一个CPU的占用一直是100%。实际上现场有4个CPU,而且这个服务器是mysql专属服务器。 我的第一反应是io_thread一类的参数设置有问题,检查以后发现read和write的thread设置都是4,这和CPU数…...
ubuntu做网站服务器/网站推广优化外链
前言这几天拿到macbook就迫不及待的尝试了一下,刚开始前几天着实非常的不习惯。但是经过这几天的学习,感觉基本上掌握了其用法,马上就感觉这是一个生产代码、制作视频的利器。问过很多macbook的使用者都觉得用了很久不好用,安装的…...