NGINX大全 第二章 高性能负载平衡

NGINX大全 第二章 高性能负载平衡

第二章 高性能负载平衡

2.0 介绍

今天的互联网用户体验需要性能和正常运行时间。 为此,我们运行同一系统的多个副本,并对它们分配负载。 随着负载的增加,系统的另一个副本可以被启用。 这种架构技术称为水平缩放。 基于软件的基础设施因其灵活性而日益普及,并开辟了广阔的可能性。 不管用例是否为了可用性小到一组两个或者大到全球数千个,我们都需要一个与基础架构一样动态的负载平衡解决方案。 NGINX以多种方式满足了这一需求,例如HTTP,TCP和UDP负载平衡,我们将在本章中介绍。

在平衡负载时,重要的是对客户的影响必须只是正面的。许多现代Web体系结构使用无状态应用层,将状态存储在共享内存或数据库中。然而,这不是所有的现实情况。session(会话)状态在交互式应用程序中非常有价值且非常有用。出于多种原因,此状态可能被局部地存储在应用程序服务器中;例如,在某些应用程序中,正在处理的数据太大以至于网络开销在性能上太昂贵。当状态被局部地存储在应用程序服务器中时,对于用户体验来说,后续请求继续传递到同一服务器是非常重要的。这种情况的另一个方面是在会话结束之前不应该释放服务器。大规模使用有状态的应用程序需要智能的负载平衡器。NGINX Plus通过跟踪cookie或routing提供多种方法来解决此问题。本章介绍会话持久性,因为它与NGINX和NGINX Plus的负载平衡有关。

确保NGINX服务的应用程序是健康的也很重要。由于多种原因,应用程序会失败。可能是因为网络连接,服务器故障或应用程序故障等等。proxy(代理)和负载均衡器必须足够智能,以检测上游服务器的故障并停止向它们传递流量;否则,客户端将一直等待,仅收到一个超时。服务器发生故障时缓解服务质量下降的一种方法是让代理检查上游服务器的运行状况。NGINX提供两种不同类型的健康检查:被动的,在开源版本中可用;主动的,仅在NGINX Plus中可用。定期进行的主动健康检查将与上游服务器建立连接或请求,并可以验证响应是否正确。当客户端发出请求或连接时,被动健康检查会监视上游服务器的连接或响应。您可能希望使用被动健康检查来减少上游服务器的负载,并且您可能希望在客户端发生故障之前使用主动健康检查来确定上游服务器的故障。本章的结尾检查了对负载平衡中的上游应用程序服务器的运行状况的监视。

2.1 HTTP负载平衡

问题

您需要在两个或更多HTTP服务器之间分配负载。

解决方案

使用NGINX的HTTP模块的upstream块在HTTP服务器上进行负载均衡:

upstream backend {
    server 10.10.12.45:80 weight=1;
    server app.example.com:80 weight=2;
}
server {
    location / {
        proxy_pass http://backend;
    }
}

此配置平衡端口80上两个HTTP服务器的负载。weight参数指示NGINX向第二个服务器传递两倍的连接,weight参数默认为1。

讨论

HTTP upstream模块控制了HTTP的负载平衡。此模块定义了一个目标池 - Unix套接字,IP地址和DNS记录(或几种混合)的任意组合。upstream模块还定义了如何将任何单个请求分配给任何上游服务器。

每个上游目标都由server指令在上游池中定义。server指令提供了Unix套接字,IP地址或FQDN,以及许多可选参数。可选参数可以更好地控制请求的路由。这些参数包括平衡算法中服务器的weight(权重); 服务器是否处于待机模式,可用还是不可用; 以及如何确定服务器是否不可用。NGINX Plus提供了许多其他方便的参数,例如服务器的连接限制,高级DNS解析控制,以及在启动后缓慢增加与服务器的连接的能力。

2.2 TCP负载平衡

问题

您需要在两个或更多TCP服务器之间分配负载。

解决方案

使用NGINX的stream模块的upstream块在TCP服务器上进行负载均衡:

stream {
    upstream mysql_read {
        server read1.example.com:3306 weight=5;
        server read2.example.com:3306;
        server 10.10.12.34:3306 backup;
    }
    server {
        listen 3306;
        proxy_pass mysql_read;
    }
}

此示例中的server块指示NGINX侦听TCP端口3306并平衡两个MySQL数据库读取副本之间的负载,并列出另一个作为备份,万一首选的坏了则将传递流量给它。此配置不会添加到conf.d文件夹,因为该文件夹包含在http块中; 相反,你应该创建另一个名为stream.conf.d的文件夹,打开nginx.conf文件中的stream块,并把新文件夹include进来用于stream配置。

讨论

TCP负载平衡由NGINX的stream模块定义。stream模块与HTTP模块一样,允许您定义服务器的upstream池并配置一个监听服务器。当配置服务器来侦听给定端口时,你必须定义要侦听的端口,或者也可以定义一个地址和一个端口。在那里,必须配置一个目标,无论它是另一个地址的直接反向代理还是资源的upstream池。

TCP负载平衡的upstream非常类似于HTTP的upstream,因为它将upstream资源定义为服务器,配置了Unix套接字,IP或完全限定的域名(FQDN),以及服务器权重,最大连接数, DNS解析器和连接加速期; 如果服务器处于活动,关闭或备份模式。

NGINX Plus为TCP负载平衡提供了更多功能。 NGINX Plus中提供的这些高级功能可以在本书中找到。 所有负载平衡的运行状况检查将在本章后面介绍。

2.3 UDP负载均衡

问题

您需要在两个或更多UDP服务器之间分配负载。

解决方案

使用NGINX的stream模块的被定义为udp的upstream块在UDP服务器上进行负载均衡:

stream {
    upstream ntp {
        server ntp1.example.com:123 weight=2;
        server ntp2.example.com:123;
    }
    server {
        listen 123 udp;
        proxy_pass ntp;
    }
}

此部分配置使用UDP协议平衡两个upstream网络时间协议(NTP)服务器之间的负载。指定UDP负载平衡简单到只要在listen指令中使用udp参数即可。

如果正在负载均衡的服务需要在客户端和服务器端之间来回发送多个数据包,你可以指定reuseport参数。这些种类的服务的例子有OpenVPN,因特网协议语音(VoIP),虚拟桌面解决方案和数据报传输层安全(DTLS)。以下是使用NGINX处理OpenVPN连接并将其代理到本地运行的OpenVPN服务的示例:

stream {
    server {
        listen 1195 udp reuseport;
        proxy_pass 127.0.0.1:1194;
    }
}

讨论

您可能会问:“既然我可以在DNS A或SRV记录中用多个主机,为什么还需要负载均衡器?” 答案是,不仅因为它有我们可以用的另外的平衡算法,而且我们可以在DNS服务器本身上进行负载平衡。在网络系统中UDP服务构成了许多我们依赖的服务,例如DNS,NTP和VoIP。UDP负载平衡可能不太常见,但在大规模的世界中同样有用。

你可以在stream模块中找到UDP负载平衡,就像TCP一样,并且以几乎相同的方式配置它。主要区别在于listen指令指定打开的套接字用于处理数据报。使用数据报时,还有一些其他的TCP中不存在的指令可以使用,例如proxy_response指令,它指定NGINX可以从upstream服务器接收多少预期响应。默认情况下,这是无限的,直到达到proxy_timeout的限制为止。

reuseport参数指示NGINX为每个工作进程创建一个单独的侦听套接字。这允许内核在工作进程之间分配传入连接,以处理在客户端和服务器之间发送的多个数据包。reuseport功能仅适用于Linux内核3.9及更高版本,DragonFly BSD和FreeBSD 12及更高版本。

2.4 负载均衡方法

问题

round-robin(循环)负载平衡不适合您的用例,因为您有异构的工作负载或服务器池。

解决方案

使用NGINX负载均衡方法中的一种,例如least connections(最少连接),least time(最少时间),generic hash(通用哈希),IP hash(IP哈希)或random(随机):

upstream backend {
    least_conn;
    server backend.example.com;
    server backend1.example.com;
}

此示例将后端的upstream池的负载平衡算法设置为最少连接算法。所有负载平衡算法(通用散列,随机和最小时间除外)都是独立的指令,例如前面的示例。接下来的讨论中解释了这些指令的参数。

讨论

并非所有请求或数据包都具有相同的权重。鉴于此,循环算法,甚至前面示例中使用的加权循环算法,将不适合所有应用程序或交通流量的需要。NGINX提供了许多负载平衡算法,您可以使用它们来适应特定的用例。除了能够选择这些负载均衡算法或方法之外,您还可以配置它们。以下负载平衡方法可用于upstream HTTP,TCP和UDP池。

Round robin(循环算法)

这是默认的负载平衡方法,它按照upstream池中服务器列表的顺序分配请求。您还可以考虑加权循环的权重,如果upstream服务器的容量不同,您可以使用加权循环。权重的整数值越高,服务器在循环中的优势就越大。权重背后的算法只是加权平均的统计概率。

Least connections(最少连接算法)

此方法通过将当前请求代理到具有最少数量的打开连接的upstream服务器来平衡负载。在决定向哪个服务器发送连接时,就像循环算法那样,最小连接算法也会考虑权重。指令名称是'least_conn`。

Least time(最少时间算法)

只能在NGINX Plus中使用。下略。

Generic hash(通用哈希算法)

管理员使用给定文本,请求或运行时的变量,或两者兼有,来定义哈希。NGINX通过为当前请求生成哈希并将其放在upstream服务器上的方式来在服务器之间分配负载。当您需要更多地控制请求被送到哪去或确定哪个upstream服务器最可能有缓存数据时,此方法非常有用。请注意,在池中添加或删除服务器时,将重新分配被哈希过的请求。该算法具有一致的可选参数,以最小化重新分配的影响。指令名称是hash

Random(随机算法)

此方法用于指示NGINX从组中选择随机服务器,并考虑服务器权重。可选的two [method]参数指示NGINX随机选择两个服务器,然后使用提供的负载平衡方法在这两个服务器之间取得平衡。默认情况下,如果传递two时没有传method,则使用least_conn方法。随机负载平衡的指令名称是random

IP hash(IP哈希算法)

此方法仅适用于HTTP。IP哈希使用客户端IP地址作为哈希。与通用哈希算法中使用远程变量略有不同,此算法使用IPv4地址的前三个八位字节或整个IPv6地址。只要该服务器可用,此方法就可确保客户端被代理到同一个upstream服务器,这在用了会话状态且会话状态不由应用程序的共享内存处理时非常有用。在分发哈希时,此方法还会考虑weight参数。指令名称是ip_hash

2.5 持久性Cookie

只能在NGINX Plus中使用。下略。

2.6 持久性Learn

只能在NGINX Plus中使用。下略。

2.7 持久性Routing

只能在NGINX Plus中使用。下略。

2.8 连接排除

只能在NGINX Plus中使用。下略。

2.9 被动健康检查

问题

您需要被动地检查upstream服务器的运行状况。

解决方案

使用具有负载平衡的NGINX健康检查以确保仅使用健康的upstream服务器:

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

此配置被动监视upstream的运行状况,将max_fails指令设置为3,将fail_timeout设置为3秒。这些指令参数在流服务器和HTTP服务器中的工作方式相同。

讨论

NGINX的开源版本中提供了被动健康检查。 当客户的请求连接通过NGINX时,被动监控会监视失败或超时连接。 默认情况下被动健康检查是启用的; 这里提到的参数允许你调整他们的行为。 对所有类型的负载平衡进行健康监控非常重要,不仅从用户体验的角度来看,而且对业务连续性也是如此。 NGINX被动地监视上游HTTP,TCP和UDP服务器,以确保它们健康和正常运行。

2.10 主动健康检查

只能在NGINX Plus中使用。下略。

2.11 慢启动

问题

您的应用程序需要在承担全部生产负载之前加速。

解决方案

当一个服务器被重新引入upstream负载平衡池时,使用server指令中的slow_start参数逐渐增加指定时间内的连接数:

upstream {
    zone backend 64k;
    server server1.example.com slow_start=20s;
    server server2.example.com slow_start=15s;
}

server指令配置会将流量缓慢增加到upstream服务器,在他们被重新引入池后。 server1将在20秒内缓慢增加连接数,而server2则是15秒内。

讨论

慢启动的概念是在一段时间内缓慢增加代理到服务器的请求数量。慢启动允许应用程序通过填充缓存,启动数据库连接来启动,而不会在连接启动时被连接淹没。当健康检查失败的服务器再次开始运作并重新进入负载平衡池时,此功能将生效。

2.12 TCP健康检查

问题

您需要检查upstream TCP服务器的健康状况,并从池中删除不健康的服务器。

解决方案

使用server块中的health_check指令进行活跃的运行状况检查:

stream {
    server {
        listen 3306;
        proxy_pass read_backend;
        health_check interval=10 passes=2 fails=3;
    }
}

该示例主动地监视upstream服务器。 如果upstream服务器无法响应NGINX发起的3个或更多的TCP连接,则会被认为是不健康的。 NGINX每10秒执行一次检查。 通过2次健康检查后,服务器才会被视为健康。

讨论

NGINX Plus可以被动或主动地验证TCP健康状况。被动健康监视是通过注意客户端和upstream服务器之间的通信来完成的。如果upstream服务器超时或拒绝连接,则被动健康检查会认为该服务器运行状况不佳。主动健康检查将发起自己的可配置的检查以确定运行状况。主动健康检查不仅可以测试与upstream服务器的连接,还可以期望一个给定的响应。

猜你喜欢
NGINX大全 第十一章 容器/微服务
阅读 1232

本章重点介绍如何构建NGINX和NGINX Plus容器镜像,使容器化环境更容易工作的特性,以及在Kubernetes和OpenShift上部署镜像。

NGINX大全 第三章 流量管理
阅读 1319

本章介绍NGINX的基于百分比分割客户端请求,利用客户端的地理位置还有以速率,连接和带宽限制的形式控制流量的能力。

NGINX大全 第七章 安全控制
阅读 1165

在本章中,我们将通过许多不同的方式使用NGINX和NGINX Plus来保护您的Web应用程序。您可以将这些安全方法中的许多方法相互结合使用,以帮助加强安全性。

NGINX大全 第一章 基础
阅读 1568

在本章中,您将学习如何安装主要配置文件所在的NGINX以及管理命令。 您还将学习如何验证安装并向默认服务器发出请求。

NGINX大全 第十六章 实用操作提示和结论
阅读 2143

在本章中,我将介绍如何确保配置文件简洁明了以及调试配置文件。

NGINX大全 第十二章 高可用性部署模式
阅读 1443

本章详细介绍了如何运行多个NGINX服务器以确保负载均衡层中的高可用性的技术。

NGINX大全 第六章 验证
阅读 1492

NGINX能够验证客户端。通过NGINX验证客户端请求降低了工作量,并可以阻止未经身份验证的请求到达应用程序服务器。

NGINX大全 第十四章 使用访问日志,错误日志和请求跟踪进行调试和故障排除
阅读 2647

在本章中,我们将讨论访问和错误日志,通过Syslog协议进行流传输以及使用NGINX生成的请求标识符来端到端地跟踪请求。