共计 2231 个字符,预计需要花费 6 分钟才能阅读完成。
我们都知道,Nginx 支持负载均衡,可以很方便的帮助我们进行水平扩容,然而它究竟是依据什么原则进行请求的分发,其中又有哪些负载均衡算法可供选择和配置,今天就让我们好好来了解一下。
<!– more –>
负载均衡的定义
什么叫负载均衡,我们可以参考一下图片中的这种情况:
- 当客户端发送请求时,会先到 Nginx,然后 Nginx 会将请求分发到后台不同的服务器上。
- 如果后台的服务器群中有一个宕机了,那么 Nginx 会自动忽略这台服务器,不会将请求再次分发到这台服务器上。
- 如果有新加入的服务器,Nginx 也会将请求分发到这台服务器上。
我所理解的负载均衡,就是:
能够将客户端的请求均匀地分发到后台各个应用服务器上,从而缓解服务器压力。
并且当服务器出现宕机或者扩容时,也能正常运行。
负载均衡的方法
上面了解了什么是负载均衡,那么 Nginx 是怎么实现这个功能的呢?
upstream 和 server 的使用
Nginx 中负责与上游交互的模块,统称为 upstream 模块。
而指定上游服务地址是通过 upstream
和server
指令完成的,其关系为:
指定上游服务器的 address
时,其地址可以是域名、IP 地址或者 unix socket 地址。
可以在域名或者 IP 地址后加端口,如果不加端口,那么 默认使用 80 端口
。
在 address
后面可以添加一些参数,比如:
backup
:指定当前 server 为备份服务,仅当非备份 server 不可用时,请求才会转发到该 server。
down
:标识某台服务已经下线,不再服务。
举个例子:
upstream upstream-service {
server 127.0.0.1:17002;
server 127.0.0.1:17000;
}
round-robin
在 upstream
这个模块中,它还提供了一个最基本的负载均衡算法round-robin
。
其功能是:
以加权轮询的方式访问 server 指令指定的上游服务。
这个算法是默认集成在 Nginx 的框架中,无法移除,所以后面讲解的所有算法都是基于此,所有算法在某些特殊情况下最终都会变成round-robin
。
涉及到的指令有:
-
weight
:服务访问的权重,默认是 1。 -
max_conns
:server 的最大并发连接数,仅作用于单 worker 进程。 -
max_fails
:在fail_timeout
时间内,最大的失败次数。当达到最大失败时,会在fail_timeout
时间内不允许再次被选择。 -
fail_timeout
:单位为秒,默认是 10 秒。指定一段时间内,最大的失败次数max_fails
。到达max_fails
后,该 server 不能访问的时间。
简单的 hash 模块
有的时候,正常的轮询算法并不能满足我们的需求,
比如:带有 cookie 请求状态的连接,如果应用服务没有设置专门的管理 cookie 的服务器,那么我们就希望同一个用户能被分配到同一个服务器。
再比如:我们后端应用需要针对请求当中的参数或者 URL,将相同的请求放到相同的服务器上进行处理。
针对第一种情况,就可以用upstream_ip_hash
。针对第二种情况,可以使用upstream_hash
。
upstream_ip_hash
功能:
以客户端的 IP 地址作为 hash 算法的关键字,映射到特定的上游服务器中。
- 对 IPV4 地址使用前 3 个字节作为关键字,对 IPV6 则使用完整地址。
- 可以使用
round-robin
算法的参数。- 可以基于
realip
模块修改用于执行算法的 IP 地址。
举个例子:
upstream upstream-service {
ip_hash;
server 127.0.0.1:17002;
server 127.0.0.1:17000;
}
upstream_hash
功能:
通过制定关键字作为 hash key,基于 hash 算法映射到特定的上游服务器中。
- 关键字可以含有变量、字符串。
- 可以使用
round-robin
算法的参数。
举个例子(以请求中的参数 username 作为 hash key):
upstream upstream-service {
hash user_$arg_username;
server 127.0.0.1:17002;
server 127.0.0.1:17000;
}
一致性哈希算法
hash 算法在一定程度上已经可以满足了我们的业务需求,但如果这个时候遇到应用宕机或者应用扩容,那么 hash 的总数就会变化,这样很有可能带来大量请求原本请求的服务器会更换,路由会失效,这样对于我们的应用服务也会产生极大的影响,这时候就可以采用一致性 hash 算法。
对于一致性哈希算法的理解,可以参考这篇文章:一致性哈希算法的理解与实践
它的使用也十分简单,就是在之前说的 upstream_hash
模块的 hash
指令最后,添加参数consistent
,这样 Nginx 就可以使用一致性哈希算法了。
举个例子(仍以请求中的参数 username 作为 hash key):
upstream upstream-service {
hash user_$arg_username consistent;
server 127.0.0.1:17002;
server 127.0.0.1:17000;
}
总结
以上就是 Nginx 中比较常见的负载均衡方法了,还有一些比如 最少连接算法
等,都是在此之上的一些应用。如果大家有什么疑问,欢迎在下方留言。
有兴趣的话可以访问我的博客或者关注我的公众号、头条号,说不定会有意外的惊喜。
https://death00.github.io/