QCon 全球软件开发大会(北京站)门票 9 折倒计时 4 天,点击立减 ¥880 了解详情
写点什么

Nginx 专题(2):Nginx 的负载均衡策略及其配置

2020 年 2 月 06 日

Nginx专题(2):Nginx的负载均衡策略及其配置

前篇Nginx专题(1):Nginx之反向代理及配置详细介绍了 Nginx 功能之一——反向代理。本篇文章将重点介绍 Nginx 功能之二——负载均衡。


为了增加对负载均衡的好感,我们先了解负载均衡能实现什么。


  • 将多个服务器节点绑定在一起提供统一的服务入口。

  • 故障转移,在意外发生的时候,可以增加一层保险,减少损失。

  • 降低上线运维复杂度,实现平滑上线。运维和开发同学都喜欢。


下面正式进入主题。


一、Nginx 的负载均衡策略

负载均衡就是将请求“均衡”地分配到多台业务节点服务器上。这里的“均衡”是依据实际场景和业务需要而定的。


对于 Nginx 来说,请求到达 Nginx,Nginx 作为反向代理服务器,有绝对的决策权,可以按照规则将请求分配给它知道的节点中的一个,通过这种分配,使得所有节点需要处理的请求量处于相对平均的状态,从而实现负载均衡。


Nginx 支持的负载均衡策略很多,比较重点的如下:


  • round robin(轮询)

  • random(随机)

  • weight(权重)

  • fair(按响应时长,三方插件)

  • url_hash(url 的 hash 值)

  • ip_hash(ip 的 hash 值)

  • least_conn(最少连接数)


这么多的策略,非常不利于记忆和选择,我们不妨将这些常见的策略归类,分而化之,方便挑选。


第一类 最佳实现

  • weight(权重)

  • random(随机)


最佳实践,其实就是最常见、最普通的默认配置,当然也是在一定程度上最好用的配置。不知道用什么方式的时候,就可以选择用这一类型。


轮询不用多说。这里的随机,其实在大量请求的情况下,按照概率的理论等同于轮询的方式。


轮询配置参考:


#默认配置就是轮询策略upstream server_group {   server backend1.example.com;   server backend2.example.com;}
复制代码


随机配置参考:


upstream server_group {    random;    server backend1.example.com;    server backend2.example.com;    server backend3.example.com;    server backend4.example.com;}
复制代码


第二类 性能优先

  • weight(权重)

  • fair(按响应时长,三方插件)

  • least_conn(最少连接数)


让业务节点中性能更强的机器得到更多请求,这也是一个比较好的分配策略。


什么是性能更好的机器?这个问题也有很多的维度去考量。


  • 从经验或硬件上分为高权重、低权重的机器。

  • 按照节点请求的响应时长来决定是多分配请求,还是少分配请求。

  • 按照保持的连接数。一般来说保持的连接数越多说明处理的任务越多,也是最繁忙的,可以将请求分配给其他机器处理。


权重的配置参考:


upstream server_group {    server backend1.example.com weight=5;    #默认为不配置权重为1    server backend2.example.com;}
复制代码


响应的时长(fair)配置参考:需要在 Nginx 编译时加入 nginx-upstream-fair 模块。


upstream server_group{   fair;   server backend1.example.com;    server backend2.example.com;    server backend3.example.com;    server backend4.example.com;}
复制代码


最少连接数(least_conn)配置参考:


upstream server_group {    least_conn;    server backend1.example.com;    server backend2.example.com;}
复制代码


第三类 保持稳定

  • ip_hash

  • url_hash


很多请求都是有状态的,上一次请求到哪个业务节点,这次还要请求到哪台机器。比如常见的 session 就是这样一种有状态的业务。


这里 Nginx 提供了按照客户端 ip 的 hash 来作为用户的标示分配、url 的 hash 作为分配标示的规则。本质上还是要找到用户的请求中不变的要素,抽离出来,这样就可以进行分配了。


ip_hash 配置参考:


upstream server_group {    ip_hash;    server backend1.example.com;    server backend2.example.com;}
复制代码


url_hash 配置参考:


upstream server_group{   hash $request_uri consistent;   server backend1.example.com;    server backend2.example.com;    server backend3.example.com;    server backend4.example.com;}
复制代码


二、Nginx 支持一致性哈希进行分配

Nginx 支持一致性 hash 进行分配,也就是配置中 consistent。


什么是一致性 hash?为什么要引入这个机制?在生产环境下,业务节点经常会出现增加或减少的情况,就算这种增加或减少都是被动的,也可能会对 hash 分配产生影响。如何能够做到尽量减少影响呢?这时一致性 hash 被发明出来。


一致性 hash 解决两个问题:


  • 分配特别不均匀;

  • 节点变动除了对分配到这个节点上的请求有影响,还会导致其他节点上的请求重新分配。


1)如何解决分配不均的问题


将原来的每一个节点复制出 N 个虚拟节点,并且给这些虚拟节点都起个名字。


1575341713699054454.png


比如原来有 5 个节点,分配的时候经常会不均匀,现在每个节点都虚拟出 N 个节点,就是 5*N 个节点,会极大降低分配不均匀的情况。下面就要说说如何分配的问题了。


2)如何解决节点变动的问题


一致性哈希的基本思想:


  • 定义一个[0,(2^32)-1]的数值空间。相当于取长度从 0 到 2^32-1 的线段。

  • 节点映射到线段上。将每个节点,包括虚拟节点,都通过 hash 算法得到数值,然后映射到这个取值区间上。


如下图。


1575341720770062937.png


  • 计算数据的 Hash 值。把请求中的关键字符串通过 hash 算法得到一个数值,在线段中找到一个位置,如果算出来的数值大于 2^32-1 则认为是 0。按照这个规则,其实是把这个线段首尾相连形成一个环,所以也叫 hash 环。

  • 数据节点在线段上找归属的节点。沿着这个线段向右找到离得最近的节点,并把该节点作为这个数据的归属节点。


1575341727384091335.png


下面再来看节点的变化对一致性 Hash 的影响。


  • 节点减少:比如 NodeA 突然故障了,原来分配到其他节点上的数据不会发生变化,只有分配到 NodeA 上的数据会重新找离它们最近的点,从而减少了 hash 重新分配的数量。这也是一致性 hash 最大的优势。

  • 节点增加:比如现在请求量抖增,需要增加节点降低负载。当新加入节点 NodeE 时,NodeE 及它的一群虚拟节点会根据 hash 值分配在 hash 环上。这时,大部分数据再根据一致性哈希规则找其归属的 Node 节点都不会发生变化,只有那些值计算出来发现离 NodeE 更近的数据发生了变化,但数量毕竟是有限的,减少了因为节点增加造成的影响。


三、故障节点摘除与恢复

先看看经典配置,再详细解释。


upstream server_group {    server backend1.example.com ;    server backend2.example.com  max_fails=3 fail_timeout=30s;    server backup1.example.com  backup;}
复制代码


max_fails=number

这个参数决定了多少次请求后端失败后会暂停这个业务节点,不再给它发新的请求,默认值是 1。此参数需要配合 fail_timeout 一起用。


题外话:如何定义失败,有很多种类型,这里因为主要处理 HTTP 代理,所以更关注 proxy_next_upstream。


proxy_next_upstream:主要定义了当服务节点出现状况时,会将请求发给其他节点,也就是定义了怎么算作业务节点失败。


fail_timeout=time

决定了当 Nginx 认定这个节点不可用时,暂停多久。不配置默认就是 10s。


把上面两个参数联合起来考虑就是:当 Nginx 发现发送到这个节点上的请求失败了 3 次的时候,就会把这个节点摘除,摘除时间是 30s,30s 后才会再次发送请求到这个节点上。


backup

类似于 switch 语句中的 default,当主要节点都挂了的时候,会把请求打到这个 backup 节点。这是最后一个救兵了。


四、总结

由于 Nginx 采用了反向代理技术,对于请求的转发有绝对的控制权,使得负载均衡变成了可能。


本文介绍了负载均衡的概念,详细分类了 Nginx 的负载均衡策略,并提供了简单配置参考。同时介绍了一致性 hash 的原理,及常用的故障节点的摘除与恢复。下一篇将会介绍 Nginx 功能之三——HTTP 缓存,敬请期待。


本文转载自宜信技术学院网站。


原文链接:http://college.creditease.cn/detail/330


2020 年 2 月 06 日 10:34337

评论

发布
暂无评论
发现更多内容

基于DAYU的实时作业开发,分分钟搭建企业个性化推荐平台

华为云开发者社区

华为 算法 数据 dayu

区块链防伪溯源平台搭建,助力企业品牌安全体系升级

13530558032

区块链医疗应用场景有哪些?区块链医疗解决方案

13530558032

有奖话题 | 如果程序员和产品经理都会凡尔赛文学,将如何对话?

YourBatman

话题讨论 凡尔赛文学

大厂都是怎么用Java8代替SimpleDateFormat?

Java架构师迁哥

智慧警务大数据可视化平台智慧公安警务研判系统开发

13530558032

性能测试界“网红”云性能测试服务,了解一下?

华为云开发者社区

CloudTest 沙箱实验 云性能测试

原创 | 使用JPA实现DDD持久化-数据库连接配置:persistence.xml

编程道与术

Java hibernate 编程 mybatis jpa

.NET5发布,这个微软“全家桶”会是.NET的春天吗?

力软.net/java开发平台

.net

《华为数据之道》读书笔记:第 3章 差异化的企业数据分类管理框架

方志

数据中台 数据仓库 数据治理 元数据

什么是堡垒机?为什么需要堡垒机?

xcbeyond

运维

容器化时代到来!跳转机分配问题终于“有救”了

华为云开发者社区

容器 镜像 网络

打工人、打工魂、高效MES助力打工者都是人上人

Marilyn

敏捷开发 快速开发 MES系统

原创 | 使用JPA实现DDD持久化-只要O,忘记R & Maven配置

编程道与术

Java hibernate 编程 mybatis jpa

高性能网关原来是这样设计出来的

周老师

Java 编程 程序员 架构 面试

申通快递 双11 云原生应用实践

阿里巴巴云原生

阿里云 Kubernetes 运维 云原生 监控

纷享销客罗旭:拐点下的中国SaaS

ToB行业头条

SaaS

《迅雷链精品课》第七课:以太坊数据存储分析

迅雷链

区块链

三分钟带你搞懂分布式链路追踪系统原理

Java架构师迁哥

如何用CSS实现图像替换链接文本显示并保证链接可点击

陈北

CSS小技巧

程序员面试的时候突然遇到答不上的问题怎么办?

Java架构师迁哥

架构师训练营第 1 期-week10

习习

Alibaba最新《Java架构核心宝典》限时开放下载,互联网主流技术详解总结,提升技术能力的必备宝典!

Java架构之路

Java 程序员 架构 面试 编程语言

架构师训练营 1 期 -- 第十周总结

曾彪彪

极客大学架构师训练营

为什么程序员不做外包

Java架构师迁哥

都是“算法”惹的祸,字节三面处处坑,我的offer要凉了?

Java~~~

字节跳动 编程语言 算法和数据结构 面试数据结构与算法

区块链、AI与大数据加持,电子合同更安全、效率更高

CECBC区块链专委会

区块链 大数据

接口请求(get、post、head等)详解

测试人生路

HTTP

原创 | TDD工具集:JUnit、AssertJ和Mockito (二十七)运行测试-在构建工具中运行测试

编程道与术

Java 编程 TDD 单元测试 JUnit

理解三值逻辑与NULL,你离SQL高手更近了一步

华为云开发者社区

sql null 逻辑

数字经济发展势头强劲

CECBC区块链专委会

数字经济

边缘计算隔离技术的挑战与实践

边缘计算隔离技术的挑战与实践

Nginx专题(2):Nginx的负载均衡策略及其配置-InfoQ