阅读 119

Nginx 实战一(负载均衡)

一个最简单的 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;  # 默认50x对应的访问页面
        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 backserver {  # 配置后端服务器具体地址,负载均衡配置不可或缺
        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://backserver;
        }

        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 backserver {
        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://backserver;
        }

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

我们在每个服务地址后面加上 weight 参数来表示权重, 这里的意思是 9000 端口处理50%的请求, 9001 端口处理25%的请求, 9002 端口处理25%的请求。
再来测试下,批量发送 100 个请求看看结果:

image.png

ip_hash 策略

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

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    
    upstream backserver {
        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://backserver;
        }

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

这里还是因为条件不允许,照理要用多个客户端来访问,并在控制台打出 ip 来看结果,但是我只有本机一台机器,所以做不了这个实验。
用迂回一点的方式来验证下,既然是根据 ip 来分配请求的,那我本机发 100 个请求,这 100 个请求应该会被打到同一台服务器上,另外两台接收到的请求数量为 0,来测试下:

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

least_conn

把请求转发给连接数较少的后端服务器

upstream backserver {
    least_conn; 
    server 0.0.0.0:9000;
    server 0.0.0.0:9001;
    server 0.0.0.0:9002;
}
复制代码

url_hash

按照访问的url的hash结果分配请求,每个url会指向后端固定的某个服务器,可以在nginx做静态服务器的情况下提高缓存效率。如需使用,需安装nginx的hash软件包。

upstream backserver {
    hash $request_uri;  # 实现每个url定向到同一个后端服务器
    hash_method crc32;  # hash_method是使用的hash算法
    server 0.0.0.0:9000;
    server 0.0.0.0:9001;
    server 0.0.0.0:9002;
}
复制代码

fair

按后端服务器的响应时间分配,响应时间短的优先分配,依赖第三方插件 nginx-upstream-fair,需要先安装;

upstream backserver {
    fair; #实现响应时间短的优先分配
    server 0.0.0.0:9000;
    server 0.0.0.0:9001;
    server 0.0.0.0:9002;
}
复制代码
文章分类
前端
文章标签