【 nginx-负载均衡 】图文并茂,一看就会

avatar

掘金引流终版.gif

陆阳阳,微医前端技术部前端开发工程师,做一条安静的咸鱼。

前言

这篇文章需要一点点的 nginx 基础知识

image.png

不会也没关系,先给各位贴一个最简单的 nginx.conf 配置,看完就会

    
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server {

        listen       8081;
        server_name  localhost;

        location / {
            proxy_pass      http://0.0.0.0:9000;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

并且起一个最简单的 node 服务:

const http = require('http');
const server = http.createServer();
const host = '0.0.0.0'
const port = 9000
let n = 0
server.on('request', function (req, res) {
  n += 1
  console.log('请求来了: ', n)
  res.write('Hello World!!!');
  res.end();
});
server.listen(port, host, function () {
  console.log(`服务器启动了,请访问:http://${host}:${port}`);
})

访问 http://localhost:8081/nginx 已经能把请求正常打到 node 9000 端口的服务了

image.png

接下来进入正题,讲讲负载均衡了

什么是负载均衡

  举个例子,工地上新到了一车砖,老板要求天黑之前需要搬完。但是工地上只有一个工人,这种情况下每趟要搬 1000 斤才有可能在天黑前搬完。但是如果 1000 斤的砖扛在肩上,那这个工人一下就被打死了。这个时候包工头另外招了两个人,三个人一起干,每个人扛 300 斤,那大家都很轻松的把活干完了,没人会死

image.png

  放到服务器上也是同样的道理。现在假设每秒钟有 1000 个请求,一台服务器处理不过来,分分钟会挂掉。我们把服务器加到 3 台,这样每台处理 300 个,每台都轻轻松松。

   image.png  

  那么问题来了,三个工人的身体强弱是有区别的。包工头在安排活的时候是做到绝对的公平每人背 300 斤?还是按照实工人实际身体情况,能者多劳?

  服务器也是一样的道理,不同的服务器处理能力是不一样的。nginx 负载均衡 做的事情就是根据服务器的能力去 平衡 大量请求到达各个服务器的数量。这里的 平衡 并不是绝对的 平均,具体怎么样去平衡请求,我们可以根据自己的需求去设置不同的 平衡策略

负载均衡策略

轮询策略(默认)

  按照上面讲的,要玩负载均衡,首先得是多台机器,一台也玩不起来啊。但是条件有限,我这边在不同端口起多个相同的 node 服务来表示多台机器

image.png

  如上图,三个服务完全相同,分别用 900090019002 端口启动,接下来修改 nginx.conf 文件,nginx 负载均衡 主要是通过配置 upstream 来实现的:

    
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    
    upstream test {
	server 0.0.0.0:9000;
	server 0.0.0.0:9001; 
	server 0.0.0.0:9002;
    }
    
    server {

        listen       8081;
        server_name  localhost;

        location / {
            proxy_pass      http://test;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

  从上面代码可以看出,改动是比较简单的,增加了一个 upsteam 配置。这个是最简单的 轮询策略,大量请求打过来后,nginx 将这些请求 平均 分配到 3 台服务器上。接下来我们通过工具批量发送 600 个请求, 来测试下我们的配置是否生效:

image.png

  从结果来看符合预期, 每个服务处理 200 个请求。

加权轮询策略

  这个也很简单,从名字可以猜出来一些,这个是按照我们指定的权重来轮询,nginx.conf 修改如下:

    
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    
    upstream test {
	server 0.0.0.0:9000 weight=2;
	server 0.0.0.0:9001 weight=1; 
	server 0.0.0.0:9002 weight=1;
    }
    
    server {

        listen       8081;
        server_name  localhost;

        location / {
            proxy_pass      http://test;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

  我们在每个服务地址后面加上 weight 参数来表示权重, 这里的意思是 9000 端口处理50%的请求, 9001 端口处理25%的请求, 9002 端口处理25%的请求。

image.png

  再来测试下,批量发送 100 个请求看看结果:

image.png

  符合预期

ip_hash 策略

  这个也很简单,看名字也能猜出来一点,根据 ip 来分配请求。固定的客户端发出的请求会被固定分配到一台服务器。接着修改 nginx.conf 配置

    
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    
    upstream test {
        ip_hash;
	server 0.0.0.0:9000;
	server 0.0.0.0:9001; 
	server 0.0.0.0:9002;
    }
    
    server {

        listen       8081;
        server_name  localhost;

        location / {
            proxy_pass      http://test;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {w
            root   html;
        }
    }
}

  这里还是因为条件不允许,照理要用多个客户端来访问,并在控制台打出 ip 来看结果,但是我只有本机一台机器,所以做不了这个实验。

image.png

  用迂回一点的方式来验证下,既然是根据 ip 来分配请求的,那我本机发 100 个请求,这 100 个请求应该会被打到同一台服务器上,另外两台接收到的请求数量为 0,来测试下:

image.png

  从结果来看也是符合预期的,这里只有 9002 端口起的服务收到了 100 个请求,其他两个服务收到的请求数量为 0

image.png

总结

  虽然短小了点,但是花5分钟应该能完全看懂 nginx 负载均衡 了,以后再也不怕别人装逼了

image.png

纳盐.gif