栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

五分钟让你搞懂Nginx负载均衡原理及四种负载均衡算法,神策数据java面试

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

五分钟让你搞懂Nginx负载均衡原理及四种负载均衡算法,神策数据java面试

Syntax: keepalive connections;

Default: —

Context: upstream

1.15.3 非稳定版本新增命令

Syntax: keepalive_requests number;

Default: keepalive_requests

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

100;

Context: upstream

Syntax: keepalive_timeout timeout;

Default: keepalive_timeout 60s;

Context: upstream

keepalive connections;

指定上游服务域名解析的 resolver 指令

当使用域名访问上游服务时,可以指定一个 DNS 解析的地址,还可以设置超时等,这个时候就要用到 resolver 指令。

Syntax: resolver address … [valid=time] [ipv6=on|off];

Default: —

Context: http, server, location

Syntax: resolver_timeout time;

Default: resolver_timeout 30s;

Context: http, server, location

实战

下面我起了两个 Nginx 的进程,一个作为上游服务器,监听 8011 和 8012 端口,另一个作为反向代理向上游服务器发请求。

上游服务器的配置如下,当请求是到达 8011 端口就返回 8011 server response. ,当请求到达 8012 端口返回 8012 server response. 。

server {

listen 8011;

default_type text/plain;

return 200 ‘8011 server response.n’;

}

server {

listen 8012;

default_type text/plain;

client_body_in_single_buffer on;

return 200 ‘8012 server response.n’;

}

作为反向代理的 Nginx 服务器配置是这个样子的:

这里面 8011 端口和 8012 端口的区别在于 8011 端口设置了权重和对应的参数。

upstream rrups {

server 127.0.0.1:8011 weight=2 max_conns=2 max_fails=2 fail_timeout=5;

server 127.0.0.1:8012;

keepalive 32;

}

server {

server_name rrups.ziyang.com;

error_log myerror.log info;

location /{

proxy_pass http://rrups;

proxy_http_version 1.1;

proxy_set_header Connection “”;

}

两个 Nginx 都配置好之后,来测试一下:

➜ nginx curl rrups.ziyang.com

8011 server response.

➜ nginx curl rrups.ziyang.com

8011 server response.

➜ nginx curl rrups.ziyang.com

8012 server response.

由于 8011 端口的权重设置的是 2,所以根据 rr 算法,每次都是先两个连接负载到 8011 端口上然后是 8012 端口。

这一节讲了 rr 负载均衡算法,rr 算法是所有负载均衡算法的基础,在其他负载均衡算法失效的情况下,Nginx 也会使用 rr 算法进行负载均衡。

负载均衡哈希算法,ip_hash 与 hash 模块

rr 轮询算法没有办法保证请求由某一台指定的服务器去处理,只能轮询处理请求,在 AKF 立方体中只能在 x 轴方向上进行水平扩展。如果基于 z 轴扩展,就可以采用哈希算法保证某一类请求只由特定的服务器处理。

  • 功能:以客户端的 IP 地址作为 hash 算法的关键字,映射到特定的上游服务器中对 IPv4 地址使用前 3 个字节作为关键字,对 IPv6 则使用完整地址可以使用 rr 算法的参数可以基于 realip 模块修改用于执行算法的 IP 地址

  • 模块: ngx_http_upstream_ip_hash_module ,通过 --without-http_upstream_ip_hash_module 禁用模块

指令的话比较简单,就是 ip_hash 出现在 upstream 上下文中。

Syntax: ip_hash;

Default: —

Context: upstream

这里面不得不提到的一个模块就是 realip 模块,哈希算法是根据 remote_addr 这个变量的值来进行哈希的,这个变量已经出现了好多次了,可见是多么常用的一个变量。不熟悉的还是到前面Nginx 的 11 个阶段 重新复习一下。

还有另外一个模块 upstream_hash 模块,这个模块可以基于任意的关键字实现 hash 算法的复杂均衡。

基于任意关键字实现 hash 算法的负载均衡:upstream_hash 模块
  • 功能:通过指定关键字作为 hash key,基于 hash 算法映射到特定的上游服务器中关键字可以含有变量、字符串可以使用 rr 算法的参数

  • 模块: ngx_http_upstream_hash_module ,通过 --without-http_upstream_ip_hash_module 禁用模块

指令的话就是 hash 指令,后面可以跟关键字作为 key。

Syntax: hash key [consistent];

Default: —

Context: upstream

实战

配置文件如下所示:

log_format varups '$upstream_addr $upstream_connect_time $upstream_header_time $upstream_response_time ’

'$upstream_response_length $upstream_bytes_received ’

‘$upstream_status $upstream_http_server $upstream_cache_status’;

upstream iphashups {

ip_hash;

#hash user_$arg_username;

server 127.0.0.1:8011 weight=2 max_conns=2 max_fails=2 fail_timeout=5;

server 127.0.0.1:8012 weight=1;

}

server {

set_real_ip_from 127.0.0.1;

real_ip_recursive on;

real_ip_header X-Forwarded-For;

server_name iphash.ziyang.com;

listen 80;

error_log myerror.log info;

access_log logs/upstream_access.log varups;

location /{

proxy_pass http://iphashups;

proxy_http_version 1.1;

proxy_set_header Connection “”;

}

}

实际验证一下,会发现不同的 ip 地址实际上是会被不同的上游服务器处理的,如果是同一个 ip 地址,那么只会被一个上游服务器处理。

➜ nginx curl -H ‘X-Forwarded-For: 10.200.20.20’ iphash.ziyang.com

8012 server response.

➜ nginx curl -H ‘X-Forwarded-For: 1.200.20.20’ iphash.ziyang.com

8011 server response.

基于 IP 或者基于自定义 key 的 hash 算法有一个严重的问题,那就是当上游服务器挂掉的话,Nginx 依然会向这台服务器发请求,这是因为,如果负载的不同的服务器上去,可能会得到异常的响应,同时还可能导致大量的路由变更。下面的一致性哈希可以解决这个问题。

一致性哈希算法:hash 模块

刚才说了基于 IP 的哈希算法存在一个问题,那就是当有一个上游服务器宕机或者扩容的时候,会引发大量的路由变更,进而引发连锁反应,导致大量缓存失效等问题。那么为什么会造成这种情况呢?

假设我们基于 key 来做 hash,现在有 5 台上游服务器,如果基于最简单的 hash 算法对 key 取模,会将 key 和 server 一一对应起来。

当有一台服务器宕机的时候,就需要重新对 key 进行 hash,最后会发现所有的对应关系全都失效了,从而会引发缓存大范围失效。

而一致性 hash 算法则可以解决这个问题。

一致性哈希算法的原理是,将一个环分成了 2^32 个区间范围,四个节点将这个环划分成为了四个区间,每个区间的请求都由对应的节点去处理。来看看当扩容的时候会发生什么。

假设这时候发现 node4 负载过高,因此决定再添加一个节点进去分担压力,那么影响的也只是这个节点之后的请求,可能会缓存失效,而其他的三个节点是不会有任何影响的。

这就是一致性 hash 算法的原理,一致性 hash 算法使用也很简单,只需要将上一节指令中的参数打开即可:

Syntax: hash key [consistent];

Default: —

Context: upstream

这里只需要指明 consistent 参数即可。

最少连接数算法

再来看一个最少连接数算法。这个算法顾名思义,它会优先选择连接最少的上游服务器,是由 upstream_least_conn 模块提供的。

  • 功能:从所有上游服务器中,找出当前并发连接数最少的一个,将请求转发到它如果出现多个最少连接服务器的连接数都是一样的,使用 rr 算法

  • 模块: ngx_http_upstream_least_conn_module ,通过 --without-http_upstream_ip_hash_module 禁用模块

指令的用法也很简单,直接在 upstream 模块中开启 least_conn 指令即可。

Syntax: least_conn;

Default: —

Context: upstream

负载均衡策略对所有 worker 进程生效:upstream_zone 模块

上面说的所有的负载均衡算法对于 worker 进程来说都是独立的,每个 worker 进程之间并不互通,这样在很多时候并不是我们期望的。

我们期望的应该是负载均衡算法对所有的 worker 进程生效。

  • 功能:分配出共享内存,将其他 upstream 模块定义的负载均衡策略数据、运行时每个上游服务器的状态数据存放在共享内存上,以对所 Nginx worker 进程生效

  • 模块: ngx_http_upstream_zone_module ,通过 --without-http_upstream_ip_hash_module 禁用模块

一个指令,指定 zone 的名字以及对应的大小:

Syntax: zone name [size];

Default: —

Context: upstream

除此之外,各个负载均衡模块之间是要遵循一定的顺序的:

ngx_module_t *ngx_modules[] = {

… …

&ngx_http_upstream_hash_module,

&ngx_http_upstream_ip_hash_module,

&ngx_http_upstream_least_conn_module,

&ngx_http_upstream_random_module,

&ngx_http_upstream_keepalive_module,

&ngx_http_upstream_zone_module,

… …

};

注意,这个模块的顺序是从上到下执行的,而不是我们前面过滤模块的从下到上。

可以看到,zone 模块在最后,也就是说,上面各个算法定义的参数和配置,最终 zone 模块会把这些配置放到共享内存里面生效。

这一节介绍了负载均衡的原理以及四种负载均衡算法,也可以说是三种,就是轮询、哈希、最少连接数算法。每一种算法都有各自的应用场景,rr 算法是最基础的负载均衡算法,在某些情况下其他算法失效的时候,会退化为 rr 算法。

upstream 提供的变量
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/643217.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号