Nginx 中 upstream 机制的负载均衡

开发者福利!热门AI工具限时免费用 购周边即赠Coding Plan Lite,Claude Code、Cursor等20+工具畅享,效率翻倍! 阅读详情

目录

负载均衡

upstream 机制使得 Nginx 以反向代理的形式运行,因此 Nginx 接收客户端的请求,并根据客户端的请求,Nginx 选择合适后端服务器来处理该请求。但是若存在多台后端服务器时,Nginx 是根据怎样的策略来决定哪个后端服务器负责处理请求?这就涉及到后端服务器的负载均衡问题。
Nginx 的负载均衡策略可以划分为两大类:内置策略 和 扩展策略。内置策略包含 加权轮询 和 IP hash,在默认情况下这两种策略会编译进 Nginx 内核,只需在 Nginx 配置中指明参数即可。扩展策略有第三方模块策略:fair、URL hash、consistent hash等,默认不编译进 Nginx 内核。本文只讲解 加权轮询 和 IP_hash 策略。

加权轮询

加权轮询策略是先计算每个后端服务器的权重,然后选择权重最高的后端服务器来处理请求。

相关结构体

ngx_http_upstream_peer_t 结构体

typedef struct {
    /* 负载均衡的类型 */
    ngx_http_upstream_init_pt        init_upstream;
    /* 负载均衡类型的初始化函数 */
    ngx_http_upstream_init_peer_pt   init;
    /* 指向 ngx_http_upstream_rr_peers_t 结构体 */
    void                            *data;
} ngx_http_upstream_peer_t;

ngx_http_upstream_server_t 结构体

/* 服务器结构体 */
typedef struct {
    /* 指向存储 IP 地址的数组,因为同一个域名可能会有多个 IP 地址 */
    ngx_addr_t                      *addrs;
    /* IP 地址数组中元素个数 */
    ngx_uint_t                       naddrs;
    /* 权重 */
    ngx_uint_t                       weight;
    /* 最大失败次数 */
    ngx_uint_t                       max_fails;
    /* 失败时间阈值 */
    time_t                           fail_timeout;

    /* 标志位,若为 1,表示不参与策略选择 */
    unsigned                         down:1;
    /* 标志位,若为 1,表示为备用服务器 */
    unsigned                         backup:1;
} ngx_http_upstream_server_t;

ngx_http_upstream_rr_peer_t 结构体

typedef struct {
    /* 后端服务器 IP 地址 */
    struct sockaddr                *sockaddr;
    /* 后端服务器 IP 地址的长度 */
    socklen_t                       socklen;
    /* 后端服务器的名称 */
    ngx_str_t                       name;

    /* 后端服务器当前的权重 */
    ngx_int_t                       current_weight;
    /* 后端服务器有效权重 */
    ngx_int_t                       effective_weight;
    /* 配置项所指定的权重 */
    ngx_int_t                       weight;

    /* 已经失败的次数 */
    ngx_uint_t                      fails;
    /* 访问时间 */
    time_t                          accessed;
    time_t                          checked;

    /* 最大失败次数 */
    ngx_uint_t                      max_fails;
    /* 失败时间阈值 */
    time_t                          fail_timeout;

    /* 后端服务器是否参与策略,若为1,表示不参与 */
    ngx_uint_t                      down;          /* unsigned  down:1; */

#if (NGX_HTTP_SSL)
    ngx_ssl_session_t              *ssl_session;   /* local to a process */
#endif
} ngx_http_upstream_rr_peer_t;

ngx_http_upstream_rr_peers_t 结构体

typedef struct ngx_http_upstream_rr_peers_s  ngx_http_upstream_rr_peers_t;

struct ngx_http_upstream_rr_peers_s {
    /* 竞选队列中后端服务器的数量 */
    ngx_uint_t                      number;

 /* ngx_mutex_t                    *mutex; */

    /* 所有后端服务器总的权重 */
    ngx_uint_t                      total_weight;

    /* 标志位,若为 1,表示后端服务器仅有一台,此时不需要选择策略 */
    unsigned                        single:1;
    /* 标志位,若为 1,表示所有后端服务器总的权重等于服务器的数量 */
    unsigned                        weighted:1;

    ngx_str_t                      *name;

    /* 后端服务器的链表 */
    ngx_http_upstream_rr_peers_t   *next;

    /* 特定的后端服务器 */
    ngx_http_upstream_rr_peer_t     peer[1];
};

ngx_http_upstream_rr_peer_data_t 结构体

typedef struct {
    ngx_http_upstream_rr_peers_t   *peers;
    ngx_uint_t                      current;
    uintptr_t                      *tried;
    uintptr_t                       data;
} ngx_http_upstream_rr_peer_data_t;

加权轮询策略的启动

在 Nginx 启动过程中,在解析完 http 配置块之后,会调用各个 http 模块对应的初始函数。对于 upstream 机制的 ngx_http_upstream_module 模块来说,对应的 main 配置初始函数是ngx_http_upstream_init_main_conf()如下所示:

for (i = 0; i < umcf->upstreams.nelts; i++) {  

    init = uscfp[i]->peer.init_upstream ? 
        uscfp[i]->peer.init_upstream:                                  ngx_http_upstream_init_round_robin;  

    if (init(cf, uscfp[i]) != NGX_OK) {  
            return NGX_CONF_ERROR;  
    }  
}  

ngx_http_upstream_module 模块中,如果用户没有做任何策略选择,那么执行默认采用加权轮询策略初始函数为ngx_http_upstream_init_round_robin。否则的话执行的是uscfp[i]->peer.init_upstream指针函数。

当接收到来自客户端的请求时,Nginx 会调用 ngx_http_upstream_init_request 初始化请求的过程中,调用 uscf->peer.init(r, uscf),对于 upstream 机制的加权轮询策略来说该方法就是 ngx_http_upstream_init_round_robin_peer,该方法完成请求初始化工作。

static void  
ngx_http_upstream_init_request(ngx_http_request_t *r)  
{  
...  
if (uscf->peer.init(r, uscf) != NGX_OK) {  
        ngx_http_upstream_finalize_request(r, u,  
                                           NGX_HTTP_INTERNAL_SERVER_ERROR);  
        return;  
    }  

    ngx_http_upstream_connect(r, u);  
}  

完成客户端请求的初始化工作之后,会选择一个后端服务器来处理该请求,选择后端服务器由函数 ngx_http_upstream_get_round_robin_peer 实现。该函数在 ngx_event_connect_peer中被调用。

ngx_int_t  
ngx_event_connect_peer(ngx_peer_connection_t *pc)  
{  
...  
/* 调用 ngx_http_upstream_get_round_robin_peer  */
   rc = pc->get(pc, pc->data);  
   if (rc != NGX_OK) {  
       return rc;  
   }  

  s = ngx_socket(pc->sockaddr->sa_family, SOCK_STREAM, 0);  
...  
}  

当已经选择一台后端服务器来处理请求时,接下来就会测试该后端服务器的连接情况,测试连接由函数 ngx_http_upstream_test_connect 实现,在函数 ngx_http_upstream_send_request 中被调用。

static void  
ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u)  
{  
...  
    if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK) {  
        /* 测试连接失败 */ 
        ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);  
        return;  
    }  
...  
}  

若连接测试失败,会由函数 ngx_http_upstream_next 发起再次测试,若测试成功,则处理完请求之后,会调用 ngx_http_upstream_free_round_robin_peer 释放后端服务器。

加权轮询工作流程

加权轮询策略的基本工作过程是:初始化负载均衡服务器列表,初始化后端服务器,选择合适后端服务器处理请求,释放后端服务器。

初始化服务器列表

初始化服务器列表由函数 ngx_http_upstream_init_round_robin 实现,该函数的执行流程如下所示:

  • 第一种情况:若 upstream 机制配置项中配置了服务器:
    • 初始化非备用服务器列表,并将其挂载到 us->peer.data 中;
    • 初始化备用服务器列表,并将其挂载到 peers->next 中;
  • 第二种情况:采用默认的方式 proxy_pass 配置后端服务器地址;
    • 初始化非备用服务器列表,并将其挂载到 us->peer.data 中;

该方法执行完成之后得到的结构如下图所示:

后端服务器列表初始化

/* 初始化服务器负载均衡列表 */
ngx_int_t
ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
    ngx_http_upstream_srv_conf_t *us)
{
    ngx_url_t                      u;
    ngx_uint_t                     i, j, n, w;
    ngx_http_upstream_server_t    *server;
    ngx_http_upstream_rr_peers_t  *peers, *backup;

    /* 设置 ngx_http_upstream_peer_t 结构体中 init 的回调方法 */
    us->peer.init = ngx_http_upstream_init_round_robin_peer;

    /* 第一种情况:若 upstream 机制中有配置后端服务器 */
    if (us->servers) {
        /* ngx_http_upstream_srv_conf_t us 结构体成员 servers 是一个指向服务器数组 ngx_array_t 的指针,*/
        server = us->servers->elts;

        n = 0;
        w = 0;
        /* 在这里说明下:一个域名可能会对应多个 IP 地址,upstream 机制中把一个 IP 地址看作一个后端服务器 */

        /* 遍历服务器数组中所有后端服务器,统计非备用后端服务器的 IP 地址总个数(即非备用后端服务器总的个数) 和 总权重 */
        for (i = 0; i < us->servers->nelts; i++) {
            /* 若当前服务器是备用服务器,则 continue 跳过以下检查,继续检查下一个服务器 */
            if (server[i].backup) {ngx_http_upstream_peer_t
                continue;
            }

            /* 统计所有非备用后端服务器 IP 地址总的个数(即非备用后端服务器总的个数) */
            n += server[i].naddrs;
            /* 统计所有非备用后端服务器总的权重 */
            w += server[i].naddrs * server[i].weight;
        }

        /* 若 upstream 机制中配置项指令没有设置后端服务器,则出错返回 */
        if (n == 0) {
            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
                          
「云原生 | Nginxupstream 模块负载均衡算法详解 Nginx负载均衡 ngx_http_upsteam_module 模块,默认编译安装。upstream 模块只能定义在 http 模块下。本文将介绍轮询、权重轮询、IP_HASH、动态参数HASH,最小连接数、随机算法 6 种负载均衡算法。本文使用的 Nginx 版本为 nginx/1.22.0 ,所有负载均衡算法默认情况下均可使用,不需要单独引入依赖包,其他版本有有引入依赖的情况,请根据提示自行引入。 轮询算法为 Nginx 默认的负载均衡算法。其按照客............... 阅读详情

相关推荐

nginx 启动错误 nginx: [emerg] host not found in upstream

简述 利用nginx进行反向代理的时候,我们会配置proxy_pass。在启动nginx的时候,会报错。nginx 启动错误 nginx: [emerg] xxoo.pusdn.com host not found in upstream 前情提示 系统:centOS 一说 同步更新最新版、完整版请移步PUSDN Powered By PUSDN - 平行宇宙软件开发者网www.pusdn.com ,转载请标明出处! 部分截图、链接等因过期、更换域名、MD语法等可能不显示,可联系反馈(备注好博文地

JaneYork的博客 5887

2021-07-04 .NET高级班 92-Nginx

Nginx篇 1 基本操作命令 先CD到nginx.exe目录 启动nginx服务 nginx start nginx 优雅停止nginx,有连接时会等连接请求完成再杀死worker进程 nginx -s quit 优雅重启,并重新载入配置文件nginx.conf nginx -s reload 查看nginx配置是否正确,测试配置是否有语法错误 nginx -t 查看帮助信息 nginx -h 指定配置文件 nginx -c filename 停止服务 nginx -s stop nginx 2 负载

愚公智库 5万+

Nginx负载均衡upstream容错机制详解

模块 lua-resty-upstream-healthcheck 的原理是每到(interval)设定的时间,就会对被代理服务器的 HTTP 端口主动发起 GET 请求(http_req),当请求的响应状态码在确定为合法的列表(valid_status)中出现时,则认为被代理服务器是健康的,如果请求的连续(fall)设定次数返回响应状态码都未在列表(valid_status)中出现,则认为是故障状态。Nginx 被动检测机制的优点是不需要增加额外进程进行健康检测,但用该方法检测是不准确的。

wyx的博客 1648

Nginx 负载均衡upstream

严格的说,Nginx仅仅是作为Nginx Proxy反向代理使用的。普通的负载均衡软件,例如LVS,其实现的功能只是对请求数据包的转发(也可能会改写数据包)、传递,其中DR模式明显的特征是从负载均衡下面的节点服务器来看,接收到的请求还是来自访问负载均衡的客户端的真实用户。而反向代理不一样,反向代理接收访问用户的请求后,会代理用户重新发起请求代理下的节点服务器,最后把数据返回给客户端用,在节点服务器看来,访问的节点服务器的客户端就是反向代理服务器了,而非真是的网络用户。

老猫喜欢今日爬山的博客 6882

nginx 使用upstream 模块实现负载均衡

最近在项目开发的时候遇到需要使用集群的配置,需要使用nginx负载均衡,于是就研究了下如何使用nginx做这块的东西。 1、首先准备三台linux服务器做练习

CodingNoob 1602

使用Nginx-upstream机制实现服务器负载均衡

本内容的背景:现如今,一个网站或者系统面临着庞大群体的访问,服务器负载过高的情况时,一些公司的运维人员或者服务器的管理者,会考虑增加服务器的数量,使用服务器级群和负载均衡提高系统的处理能力,已解决服务器压力过大等问题。 服务器负载均衡可以使用很多种方式进行实现,例如:DNS、IP报文、反向代理等。本文主要使用nginxupstream机制来实现负载均衡。 ...

葬花吟 466

nginxupstream机制)的几种负载均衡策略

nginxupstream机制)的几种负载均衡策略 upstream机制使得Nginx以反向代理的方式运行,因此Nginx接受客户端的请求,并根据客户端的请求,Nginx选择合适的后端服务器来处理改请求。 Nginx负载均衡策略: (参考:http://openskill.cn/article/586) 1、轮询(默认) 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,会自动剔除; upstream test { server 10.0.0.7:80;

ajiu_9999的博客 1547

Nginx upstream反向代理-负载均衡及健康检查探活机制

(1824条消息) Nginx 通过upstream反向代理报 400 Bad Request_nginx proxy 400_赶路人儿的博客-CSDN博客。Nginx负载均衡(upstream)-yellowcong_51CTO博客_负载均衡 nginxNginx--upstream健康检查 - 心恩惠动 - 博客园 (cnblogs.com)

z69183787的专栏 891

nginx重试机制proxy_next_upstream

nginx作为反向代理服务器,后端RS有多台服务器,上层通过一定机制保证容错和负载均衡nginx的重试机制就是容错的一种 官方链接:http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 | http_403

流浪猫之家 2302

Nginx学习】3步轻松启动Nginx Upstream机制:访问第三方服务的终极指南

upstreamNginx中的一个模块,用于定义一组服务器,这些服务器可以是后端应用服务器、数据库服务器或其他任何服务。通过upstreamNginx可以将请求分发到这些服务器,实现负载均衡和高可用性。首先,我们需要在Nginx配置文件中定义一个upstream块。这个块中列出了所有的后端服务器。代码注释:定义一个名为的upstream。:定义一个后端服务器。首先,定义一个upstream块,包含多个后端服务。# 设置超时时间# 设置重试次数# 使用最少连接策略

java专栏 1157

Nginx学习】5大步骤揭秘Nginx Upstream机制:ngx_http_upstream_t数据结构的意义与实现

首先,我们来回顾一下Upstream机制的基本概念。Upstream机制允许Nginx将请求转发到多个后端服务器,从而实现负载均衡和高可用性。这就像是一支乐队,Nginx作为指挥,根据不同的需求将任务分配给不同的乐手(后端服务器),确保演奏的和谐与高效。让我们先来看看// 当前的HTTP请求// 上游配置// 上游服务器配置// 主配置// 后端服务器的连接信息// 当前连接// 请求状态// 请求体缓冲区// 响应缓冲区// 输出链表// 处理函数指针// 初始化上游函数指针。

java专栏 1259

NginxUpstream使用详解

Nginx 的 `upstream` 模块是实现负载均衡和故障转移的关键组件。通过合理配置,可以有效地提高应用的可用性和扩展性。

zhangxueyi的专栏 7069

Nginx学习】8大步骤揭秘Nginx Upstream机制:ngx_http_upstream_conf_t配置结构体详解

首先,我们来回顾一下Upstream机制的基本概念。Upstream机制允许Nginx将请求转发到多个后端服务器,从而实现负载均衡和高可用性。这就像是一支乐队,Nginx作为指挥,根据不同的需求将任务分配给不同的乐手(后端服务器),确保演奏的和谐与高效。让我们先来看看// 初始化上游函数指针// 初始化对等体函数指针// 连接超时时间// 发送超时时间// 读取超时时间// 缓冲区大小// 缓冲区数量// 忙碌缓冲区大小// 最大临时文件大小// 临时文件写入大小// 忽略客户端中断。

java专栏 1429

Nginx学习】5步揭秘Nginx Upstream机制:如何优雅地结束Upstream请求

首先,我们来回顾一下Upstream机制的基本概念。Upstream机制允许Nginx将请求转发到多个后端服务器,从而实现负载均衡和高可用性。这就像是一支乐队,Nginx作为指挥,根据不同的需求将任务分配给不同的乐手(后端服务器),确保演奏的和谐与高效。通过上述的解析,我们可以看到Nginx在结束Upstream请求时的设计和实现。从检查响应是否完整、清理缓存,到关闭连接、释放资源,每一步都至关重要。Nginx通过优雅地结束请求,确保了系统的稳定性和高效运行。

java专栏 724

Nginxupstream被动式重试机制

异常状态码部分(就是 4xx、5xx 错误)。上游服务器返回空响应或者非法响应头。

weixin_62845931的博客 1787

Nginx学习】5大步骤揭秘Nginx Upstream机制:如何发送请求到上游服务器?

首先,我们来回顾一下Upstream机制的基本概念。Upstream机制允许Nginx将请求转发到多个后端服务器,从而实现负载均衡和高可用性。这就像是一支乐队,Nginx作为指挥,根据不同的需求将任务分配给不同的乐手(后端服务器),确保演奏的和谐与高效。

java专栏 736
上一篇: Nginx 中 upstream 机制的实现
下一篇: C ++ 对象模型
逆风微积分
博客等级 码龄16年 468粉丝 214原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值