上一节介绍了轮询和加权轮询,这章讲解另外几种:

● ip_hash
● hash
● least_conn

ip_hash

image-20210414221202029.84a44a49
按访问 IP 做哈希算法,落到后端的服务节点上,也就是说如果该用户的 IP 一直不变,那么 ta 的请求将会一直落在同一个节点上

下面来看看 hash 算法是如何做的
image-20210414221500618.61feacb7

upstream tomcats {
   ip_hash;
   server 192.168.56.106:8080;
   server 192.168.56.107:8080;
   server 192.168.56.108:8080;
}

这个 ip_hash 的源码在以下路径

/home/software/nginx-1.16.1/src/http/modules/ngx_http_upstream_ip_hash_module.c

可以看看它的路径组织,在 modules 下,分模块放置的。它的源码里面写着 hash 的算法,只截取了 ip 地址的前 3 段进行计算,所以:如果你在同一个 IP 段中不同 IP 去访问的话,会被路由到同一台节点
image-20210414223549106.ce0671c9
需要特别注意的是:当新增节点或删除节点的时候会 hash 值会变化,但是在临时移除节点的时候,可以使用 down 标记,可以让 hash 值不发生变化,如下所示

upstream backend {
    ip_hash;

    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com down;
    server backend4.example.com;
}

hash 算法带来的问题

当节点数量变化后,hash 值计算后与原来的不一致,当大量用户和大量机器的时候,依赖该算法相关的业务都会受到一定的影响,比如缓存。

那么就有另外一种 hash 算法来解决这个问题:一致性哈希算法
image-20210414224733263.488cff6e
一条线,上面分布着从 0 开始到 232-1 的值,这条线可以变成一个圆圈
image-20210414225231928.552b0e05

  1. 计算机节点按照 hash 算法,分布在这个圆环上
  2. 那么用户计算访问时,它的 ip 经过 hash 算法后,也会落在这个圆环上的某一个点上
  3. 那么如果落在的不是在计算机节点上,就顺时针找到一个最近的节点

如果节点减少,那么如下图所示:只会影响到 一部分 的用户被路由到下一个节点
image-20210414225514457.4a55150e
同理,增加节点的话,也只会影响到一部分的用户
image-20210414225655785.b0f64025

url hash

基于 URL 的 hash 算法
image-20210414230024788.57b8891d
基于 URL 有一个问题:有可能某一个 URL 访问量很高,那么就会导致部分节点过热,部分节点过冷,这种情况下,可以让过热的节点上再做一个集群来分担压力
官方其实提供的是一个 hash 函数,用来计算 hash 的参数可以是任意值,这里我们使用内置变量获得 url 可以如下配置

upstream tomcats {
   hash $request_uri;
   
   server 192.168.56.106:8080;
   server 192.168.56.107:8080;
   server 192.168.56.108:8080;
}

least_conn

根据最少连接数路由
image-20210414231010180.56902ab9

upstream tomcats {
   least_conn;
   
   server 192.168.56.106:8080;
   server 192.168.56.107:8080;
   server 192.168.56.108:8080;
}