Nginx负载均衡之动态更新upstream

2024-06-17 11:20

本文主要是介绍Nginx负载均衡之动态更新upstream,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        Nginx 的配置是启动时一次性加载到内存中的,在实际的使用中,对 Nginx 服务器上游服务器组中节点的添加或移除仍需要重启或热加载 Nginx 进程。在 Nginx 的商业版本中,提供了 ngx_http_api_module 模块,可以通过 API 动态添加或移除上游服务器组中的节点。
        对于 Nginx 开源版本,通过 Nginx 的扩展版 OpenResty 及 Lua 脚本也可以实现上游服务器组中节点的动态操作,这里只使用 OpenResty 的 lua-upstream-nginx-module 模块简单演示节点的上下线状态动态修改的操作。该模块提供了 set_peer_down 指令,该指令可以对 upstream 的节点实现上下线的控制。
        由于该指令只支持 worker 级别的操作,为使得 Nginx 的所有 worker 都生效,此处通过编写 Lua 脚本与 lua-resty-upstream-healthcheck 模块做了简单的集成,利用 lua-resty-upstream-healthcheck 模块的共享内存机制将节点状态同步给其他工作进程,实现对 upstream 的节点状态的控制。
        首先在 OpenResty 的 lualib 目录下创建公用函数文件 api_func.lua,lualib/api_func.lua 内容如下:

local _M = { _VERSION = '1.0' }
local cjson = require "cjson"
local upstream = require "ngx.upstream"
local get_servers = upstream.get_servers
local get_primary_peers = upstream.get_primary_peers
local set_peer_down = upstream.set_peer_down# 分割字符串为table
local function split( str,reps )local resultStrList = {}string.gsub(str,"[^"..reps.."]+",function ( w )table.insert(resultStrList,w)end)return resultStrList
end# 获取server列表
local function get_args_srv( args )if not args["server"] thenngx.say("failed to get post args: ", err)return nilelseif type(args["server"]) ~= "table" thenserver_list=split(args["server"],",")elseserver_list=args["server"]endendreturn server_list
end# 获取节点在upstream中的顺序
local function get_peer_id(ups,server_name)local srvs = get_servers(ups)for i, srv in ipairs(srvs) do-- ngx.print(srv["name"])if srv["name"] == server_name thentarget_srv = srvtarget_srv["id"] = i-1breakendendreturn target_srv["id"]
end# 获取节点共享内存key
local function gen_peer_key(prefix, u, is_backup, id)if is_backup thenreturn prefix .. u .. ":b" .. idendreturn prefix .. u .. ":p" .. id
end# 设置节点状态
local function set_peer_down_globally(ups, is_backup, id, value,zone_define)local u = upslocal dict = zone_definelocal ok, err = set_peer_down(u, is_backup, id, value)if not ok thenngx.say(cjson.encode({code = "E002", msg = "failed to set peer down", data = err}))endlocal key = gen_peer_key("d:", u, is_backup, id)local ok, err = dict:set(key, value)if not ok thenngx.say(cjson.encode({code = "E003", msg = "failed to set peer down state", data = err}))end
end# 获取指定upstream的节点列表
function  _M.list_server(ups)local srvs, err = get_servers(ups)ngx.say(cjson.encode(srvs))
end# 设置节点状态
function  _M.set_server(ups,args,status,backup,zone_define)local server_list = get_args_srv(args)if server_list == nil thenngx.say(cjson.encode({code = "E001", msg = "no args",data = server_list}))return nilendfor _, s in pairs(server_list) dolocal peer_id = get_peer_id(ups,s)if status thenlocal key = gen_peer_key("nok:", ups, backup, peer_id)local ok, err = zone_define:set(key, 1)set_peer_down_globally(ups, backup, peer_id, true,zone_define)elselocal key = gen_peer_key("ok:", ups, backup, peer_id)local ok, err = zone_define:set(key, 0)set_peer_down_globally(ups, backup, peer_id, nil,zone_define)endendngx.say(cjson.encode({code = "D002", msg = "set peer is success",data = server_list}))
endreturn _M

        Nginx 配置文件 status.conf 的内容如下:

# 关闭socket错误日志
lua_socket_log_errors off;# 设置共享内存名称及大小
lua_shared_dict _healthcheck_zone 10m;init_worker_by_lua_block {local hc = require "resty.upstream.healthcheck"# 设置需要健康监测的upstreamlocal ups = {"foo.com","sslback"}# 遍历ups,绑定健康监测策略for k, v in pairs(ups) dolocal ok, err = hc.spawn_checker{shm = "_healthcheck_zone",      # 绑定lua_shared_dict定义的共享内存upstream = v,                   # 绑定upstream指令域type = "http",http_req = "GET / HTTP/1.0\r\nHost: foo.com\r\n\r\n",# 用以检测的raw格式http请求interval = 2000,                # 每2s检测一次timeout = 1000,                 # 检测请求超时时间为1sfall = 3,                       # 连续失败3次,被检测节点被置为DOWN状态rise = 2,                       # 连续成功2次,被检测节点被置为UP状态# 当健康检测请求返回的响应码为200或302时,被认# 为检测通过valid_statuses = {200, 302},concurrency = 10,               # 健康检测请求的并发数为10}if not ok thenngx.log(ngx.ERR, "failed to spawn health checker: ", err)returnendend
}upstream foo.com {server 192.168.2.145:8080;server 192.168.2.109:8080;server 127.0.0.1:12356 backup;
}upstream sslback {server 192.168.2.145:443;server 192.168.2.159:443;
}server {listen 18080;access_log  off;error_log off;# 健康检测状态页location = /healthcheck {access_log off;allow 127.0.0.1;allow 192.168.2.0/24;allow 192.168.101.0/24;deny all;default_type text/plain;content_by_lua_block {local hc = require "resty.upstream.healthcheck"ngx.say("Nginx Worker PID: ", ngx.worker.pid())ngx.print(hc.status_page())}}location = /ups_api {default_type  application/json;content_by_lua '# 获取URL参数local ups = ngx.req.get_uri_args()["ups"]local act = ngx.req.get_uri_args()["act"]if act == nil or ups == nil thenngx.say("usage: /ups_api?ups={name}&act=[down,up,list]")returnend# 引用api_func.lua脚本local api_fun = require "api_func"# 绑定共享内存_healthcheck_zonelocal zone_define=ngx.shared["_healthcheck_zone"]if act == "list" then# 获取指定upstream的节点列表api_fun.list_server(ups)elsengx.req.read_body()local args, err = ngx.req.get_post_args()if act == "up" then# 节点状态将设置为UPapi_fun.set_server(ups,args,false,false,zone_define)endif act == "down" then# 节点状态将设置为DOWNapi_fun.set_server(ups,args,true,false,zone_define)endend';}
}

        操作命令如下:

# 查看upstream foo.com的服务器列表
curl "http://127.0.0.1:18080/ups_api?act=list&ups=foo.com"# 将192.168.2.145:8080这个节点设置为DOWN状态
curl -X POST -d "server=192.168.2.145:8080" "http://127.0.0.1:18080/ups_api?act= down&ups=foo.com"# 将192.168.2.145:8080这个节点设置为UP状态
curl -X POST -d "server=192.168.2.145:8080" "http://127.0.0.1:18080/ups_api?act= up&ups=foo.com"

 

 

这篇关于Nginx负载均衡之动态更新upstream的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1069301

相关文章

Windows的CMD窗口如何查看并杀死nginx进程

《Windows的CMD窗口如何查看并杀死nginx进程》:本文主要介绍Windows的CMD窗口如何查看并杀死nginx进程问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录Windows的CMD窗口查看并杀死nginx进程开启nginx查看nginx进程停止nginx服务

Java调用C#动态库的三种方法详解

《Java调用C#动态库的三种方法详解》在这个多语言编程的时代,Java和C#就像两位才华横溢的舞者,各自在不同的舞台上展现着独特的魅力,然而,当它们携手合作时,又会碰撞出怎样绚丽的火花呢?今天,我们... 目录方法1:C++/CLI搭建桥梁——Java ↔ C# 的“翻译官”步骤1:创建C#类库(.NET

Nginx Location映射规则总结归纳与最佳实践

《NginxLocation映射规则总结归纳与最佳实践》Nginx的location指令是配置请求路由的核心机制,其匹配规则直接影响请求的处理流程,下面给大家介绍NginxLocation映射规则... 目录一、Location匹配规则与优先级1. 匹配模式2. 优先级顺序3. 匹配示例二、Proxy_pa

MyBatis编写嵌套子查询的动态SQL实践详解

《MyBatis编写嵌套子查询的动态SQL实践详解》在Java生态中,MyBatis作为一款优秀的ORM框架,广泛应用于数据库操作,本文将深入探讨如何在MyBatis中编写嵌套子查询的动态SQL,并结... 目录一、Myhttp://www.chinasem.cnBATis动态SQL的核心优势1. 灵活性与可

Windows 系统下 Nginx 的配置步骤详解

《Windows系统下Nginx的配置步骤详解》Nginx是一款功能强大的软件,在互联网领域有广泛应用,简单来说,它就像一个聪明的交通指挥员,能让网站运行得更高效、更稳定,:本文主要介绍W... 目录一、为什么要用 Nginx二、Windows 系统下 Nginx 的配置步骤1. 下载 Nginx2. 解压

Mybatis嵌套子查询动态SQL编写实践

《Mybatis嵌套子查询动态SQL编写实践》:本文主要介绍Mybatis嵌套子查询动态SQL编写方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、实体类1、主类2、子类二、Mapper三、XML四、详解总结前言MyBATis的xml文件编写动态SQL

SpringBoot实现Kafka动态反序列化的完整代码

《SpringBoot实现Kafka动态反序列化的完整代码》在分布式系统中,Kafka作为高吞吐量的消息队列,常常需要处理来自不同主题(Topic)的异构数据,不同的业务场景可能要求对同一消费者组内的... 目录引言一、问题背景1.1 动态反序列化的需求1.2 常见问题二、动态反序列化的核心方案2.1 ht

golang实现动态路由的项目实践

《golang实现动态路由的项目实践》本文主要介绍了golang实现动态路由项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习... 目录一、动态路由1.结构体(数据库的定义)2.预加载preload3.添加关联的方法一、动态路由1

Nginx 413修改上传文件大小限制的方法详解

《Nginx413修改上传文件大小限制的方法详解》在使用Nginx作为Web服务器时,有时会遇到客户端尝试上传大文件时返回​​413RequestEntityTooLarge​​... 目录1. 理解 ​​413 Request Entity Too Large​​ 错误2. 修改 Nginx 配置2.1

Web技术与Nginx网站环境部署教程

《Web技术与Nginx网站环境部署教程》:本文主要介绍Web技术与Nginx网站环境部署教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、Web基础1.域名系统DNS2.Hosts文件3.DNS4.域名注册二.网页与html1.网页概述2.HTML概述3.