NGINX的HTTP负载均衡

1. 总览

    跨多个应用程序实例的负载均衡是一种用于优化资源利用率,最大化吞吐量,减少延迟和确保容错配置的常用技术。
    NGINX可以在不同的部署方案中用作非常有效的HTTP负载均衡器。

2. 将HTTP流量代理到一组服务器

    要开始使用NGINX对一组服务器的HTTP流量进行负载均衡,首先需要使用upstream指令定义该组。该指令放置在http上下文(context)中。
    使用server指令配置组中的服务器(不要与定义虚拟服务器的server块混淆)。例如,以下配置定义了一个名为backend的组,并且由三个服务器配置组成:

http {
    upstream backend {
        server backend1.example.com weight=5;
        server backend2.example.com;
        server 192.0.0.1 backup;
    }
}

    若要将请求传递到服务器组,请在proxy_pass指令(或对应相关协议的fastcgi_pass,memcached_pass,scgi_pass,uwsgi_pass指令)中指定该组的名称。在下面示例中,运行在NGINX上的虚拟服务器将所有请求传递到上一个示例中定义的backend upstream组:

server {
    location / {
        proxy_pass http://backend;
    }
}

    以下示例结合了以上两个代码片段,并显示了如何将HTTP请求代理到后端服务器组。该组由三台服务器组成,其中两台运行同一应用程序的实例,而第三台是备份服务器。因为没有在upstream块中指定负载均衡算法,所以NGINX使用默认算法Round Robin:

http {
    upstream backend {
        server backend1.example.com;
        server backend2.example.com;
        server 192.0.0.1 backup;
    }
    
    server {
        location / {
            proxy_pass http://backend;
        }
    }
}

3. 选择负载均衡方法

    NGINX开源支持五种负载均衡方法。

  • Round Robin 请求在服务器之间平均分配,同时考虑了服务器权重。默认情况下使用此方法(没有启用它的指令):
upstream backend {
   # no load balancing method is specified for Round Robin
   server backend1.example.com;
   server backend2.example.com;
}
  • Least Connections(最少的连接)将请求发送到活动连接数最少的服务器,同时考虑服务器权重:
upstream backend {
    least_conn;
    server backend1.example.com;
    server backend2.example.com;
}
  • IP哈希(ip_hash) 根据客户端IP地址在服务器之间分配请求。在这种情况下,可以使用IPv4地址的前三个八位位组或整个IPv6地址来计算哈希值。该方法保证了来自同一地址的请求将到达同一服务器,除非它不可用。
upstream backend {
    ip_hash;
    server backend1.example.com;
    server backend2.example.com;
}

    如果其中一台服务器需要暂时从负载均衡循环中删除,则可以使用down参数对其进行标记,以保留客户端IP地址的当前哈希值。该服务器要处理的请求将自动发送到组中的下一个服务器:

upstream backend {
    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com down;
}
  • 通用哈希(Generic Hash) 为服务器组指定负载均衡方法,在该服务器组中,客户端-服务器映射基于散列key值。该key可以包含文本,变量,以及它们的组合。例如,密钥可以是成对的源IP地址和端口,或者是本示例中的URI:
upstream backend {
    hash $request_uri consistent;
    server backend1.example.com;
    server backend2.example.com;
}

    请注意,从组中添加或删除服务器可能会导致将大多数密钥重新映射到其他服务器。
    如果指定了consistent参数,则将使用ketama 一致性哈希方法。根据用户定义的哈希键值,请求在所有upstream服务器上平均分配。该方法确保在将服务器添加到组中或从组中删除服务器时,只有很少的键将被重新映射到不同的服务器。这有助于为缓存服务器获得更高的缓存命中率。在负载均衡缓存服务器或其他累积状态的应用程序的情况下最大程度地减少了缓存丢失。

  • Random(随机) 每个请求将传递到随机选择的服务器。如果指定了two参数,首先,NGINX考虑服务器权重随机选择两个服务器,然后使用指定的方法选择这些服务器之一,默认方法是least_conn,将请求传递到活动连接数最少的服务器。least_time方法以最小的平均响应时间和最少的活动连接数将请求传递给服务器。如果指定least_time=header,则使用接收响应头的时间 。如果指定least_time=last_byte,则使用接收完整响应的时间。least_time方法是商业订阅的一部分,需要付费使用。
    句法:
random [two [method]];

    示例:

upstream backend {
    random two least_time=last_byte;
    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com;
    server backend4.example.com;
}

    个人感觉ip_hash和通用hash的侧重点是不同的,ip_hash保证session由同一台服务器处理,可能会出现某台服务器负载比其他服务器负载大的情况;通用hash保证服务器的负载相对均衡。

4. 服务器权重

    默认情况下,NGINX使用Round Robin方法根据请求的权重在组中的服务器之间分配请求。server指令的weight参数设置服务器的权重,默认值为1:

upstream backend {
    server backend1.example.com weight=5;
    server backend2.example.com;
    server 192.0.0.1 backup;
}

    在此示例中,backend1.example.com具有weight 5;其他两台服务器的默认权重为1。具有IP地址192.0.0.1的服务器被标记为backup服务器,除非其他两台服务器均不可用,否则不会接收请求。根据这种权重配置,每6次请求,5次发送到backend1.example.com,1次发送到backend2.example.com。

5. 服务器慢启动

    服务器慢速启动功能可防止最近恢复的服务器被连接压垮,因为连接可能会超时并导致服务器再次标记为故障。
    慢速启动允许upstream服务器在恢复或可用后逐渐将其权重从0恢复到正常值。这可以通过server指令的slow_start参数实现:

upstream backend {
    server backend1.example.com slow_start=30s;
    server backend2.example.com;
    server 192.0.0.1 backup;
}

    slow_start参数默认值为0,即禁用慢速启动。该参数不能与hash、ip_hash和random负载均衡方法一起使用。
    示例的时间值为30 秒,表示如果backend1恢复正常,需要花费30秒将backend1服务器的连接数增加到最大值。
    请注意,如果一个组中只有一台服务器,则忽略server指令的max_fails、fail_timeout和slow_start参数,并且默认该服务器永远可用。

6. 配置健康检查

    NGINX可以持续测试您的HTTP upstream服务器,避开出现故障的服务器,并可以将恢复正常的服务器添加到负载均衡组中。

6.1先决条件
  • 对于被动健康检查,可以使用NGINX 开源版本或NGINX Plus(商业版);
  • 对于主动健康检查和实时活动监控仪表板,需要使用NGINX Plus;
  • 一个HTTP upstream服务器的负载均衡组。
6.2 被动健康检查

    对于被动运行状况检查,NGINX会监视事务的发生,并尝试恢复失败的连接。如果仍然无法恢复交易,则NGINX将服务器标记为不可用,并暂时停止向其发送请求,直到再次将其标记为活动。
    对于每个upstream服务器,使用upstream块中server指令的参数定义了服务器不可用的条件:

  • fail_timeout 设置必须多次尝试失败才能将服务器标记为不可用的时间,以及将服务器标记为不可用的时间(默认为10秒)。
  • max_fails 设置在fail_timeout服务器标记为不可用的时间内必须发生的失败尝试次数(默认为1次尝试)。

    在下面的示例中,如果NGINX无法在30秒内向服务器发送请求或没有收到3次响应,则将服务器标记为30秒钟不可用:

upstream backend {
    server backend1.example.com;
    server backend2.example.com max_fails=3 fail_timeout=30s;
}

    上面介绍的是被动健康检查,与之相对的是主动健康检查,需要付费,不介绍。

7. 与多个工作进程共享数据

    如果upstream块不包含zone指令,则每个工作进程(worker process)将保留其自己的服务器组配置副本,并维护一组自己的相关计数器。计数器包括当前到组中每个服务器的连接数以及将请求传递到服务器的失败尝试数。因此,无法动态修改服务器组配置。
    当zone指令包含在upstream块中时,upstream组的配置将保留在所有工作进程之间共享的存储区中。此方案是可动态配置的,因为所有工作进程访问组配置的同一副本并使用相同的相关计数器。
    zone指令对于upstream组的主动健康检查和动态重置是必需的。但是,upstream组的其他特性也可以从该指令的使用中受益。
    例如,如果组的配置不是共享的,每个工作进程都会维护自己的计数器,用于记录将请求传递给服务器时失败的次数。在这种情况下,每个请求只能到达一个工作进程。当选择处理请求的工作进程无法将请求传输到服务器时,其他工作进程对此一无所知。虽然某些工作进程可能认为服务器不可用,但其他进程可能仍会向此服务器发送请求。要明确服务器不可用,fail_timeout参数设置的时间范围内失败的尝试次数必须等于max_fails乘以工作进程数。另一方面,zone指令保证了预期的行为。
    同样,如果没有zone指令,至少在低负载下,最小连接负载均衡方法可能无法按预期工作。此方法将请求传递给活动连接数最少的服务器。如果组的配置不是共享的,则每个工作进程使用其自己的计数器来计算连接数,并可能将请求发送到同一服务器刚刚发送请求的另一个工作进程。但是,您可以增加请求数以减少这种影响。在高负载情况下,请求均匀地分布在工作进程之间,最小连接方法按预期工作。

7.1 设定zone大小

    由于使用模式差异很大,因此无法给出理想的存储区大小。所需的内存量取决于启用了哪些功能(例如会话持久性,健康检查或DNS重新解析)以及如何标识upstream服务器。
    例如,在sticky_route启用会话持久性方法和单个健康检查的情况下,一个256 KB的区域可以容纳upstream服务器的指示数量如下:

  • 128个服务器(每个服务器定义为IP地址:端口对)
  • 88个服务器(每个服务器定义为主机名:端口对,其中主机名解析为单个IP地址)
  • 12个服务器(每个服务器定义为主机名:端口对,其中主机名解析为多个IP地址)

8. 使用DNS配置HTTP负载均衡

    可以在运行时使用DNS修改服务器组的配置。
    对于在server指令中用域名标识的upstream组中的服务器,NGINX可以监视对相应DNS记录中IP地址列表的更改,并自动将更改应用于upstream组的负载均衡,无需重启。这可以通过在http块中包含的resolver指令以及server指令的resolve参数来完成:

http {
    resolver 10.0.0.1 valid=300s ipv6=off;
    resolver_timeout 10s;
    server {
        location / {
            proxy_pass http://backend;
        }
    }
    upstream backend {
        zone backend 32k;
        least_conn;
        # ...
        server backend1.example.com resolve;
        server backend2.example.com resolve;
    }
}

    在该示例中,server指令的resolve参数告诉NGINX定期将backend1.example.com和backend2.example.com域名重新解析为IP地址。
    resolver指令定义NGINX向其发送请求的DNS服务器的IP地址(这里是10.0.0.1)。默认情况下,NGINX会以记录中的TTL值指定的频率重新解析DNS记录,但你可以使用valid参数覆盖TTL值。在示例中,该值为300秒。
    可选的参数ipv6=off,表示只有IPv4地址用于负载均衡。默认情况下支持解析IPv4和ipv6地址。
    如果域名解析为多个IP地址,则这些地址将保存到upstream配置并进行负载均衡。在我们的示例中,服务器使用最小连接的方法进行负载均衡。如果服务器的IP地址列表已更改,NGINX将立即开始通过新地址集进行负载均衡。
    注:各个命令的使用,以官方文档为准。

参考文档

https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值