(014)Nginx静态资源web服务_负载均衡

  1、负载均衡简介

  负载均衡可以缓解单台服务的压力,防止单点故障。负载均衡按照范围分为GSLB和SLB,区别是影响范围不同。GSLB是一个全局负载均衡,节点庞大,地域范围广,往往以国家、省地区为单位进行全局负载均衡。如图:

  

  GSLB由调度中心节点、边缘调度节点、应用服务中心节点、应用服务节点组成。不可能所有访问都去请求中心节点,而是先去请求调度节点。比如张三在北京,先去请求调度节点,调度节点返回给张三对应的地址,张三根据地址请求对应的应用服务。调度节点由调度中心节点控制。

  往往接触最多的是SLB:调度节点和服务节点在一个服务单元或一个地域里面。请求过来给调度节点,调度节点转发给服务节点,服务节点响应给客户。如图:

  

  SLB按照网络OSI模型分为:四层负载均衡和七层负载均衡。

  四层负载均衡在OSI模型中的传输层,传输层支持到TCP/IP协议的控制,它只需对客户端请求进行TCP/IP的包转发就可以实现负载均衡,好处是性能快,只需要最底层进行应用处理,而不需要进行复杂的逻辑,只需要进行包的转发。

  七层负载均衡在OSI模型中的应用层,可以完成许多应用方面协议的请求。比如HTTP的应用层负载均衡:实现HTTP信息的改写、头信息的改写、安全应用规则的控制以及转发、 Rewrite等规则,Nginx是一个典型的七层负载均衡的SLB。

  2、配置语法

  Nginx负载均衡用到了proxy_pass,它把所有客户端的请求转发到后端的服务器上,只是不是转发到一台服务器,而是一组虚拟的服务池,称为upstream server,它里面可以定义很多服务。当请求过来会通过upstream server分发到不同的服务上,实现负载均衡。语法如下:

  Syntax:upstream name {...};
  Default:-
  Context:http

  大括号中可以是域名、域名:端口、域名:端口 参数等,如下:

  upstream backend{
    server backend1.example.com weight=5;#权重
    server backend2.example.com:8080;
    server unix:/tmp/backend3;

    server backup1.example.com:8080 backup;#备份节点
    server backup2.example.com:8080 backup;
  }

  参数及其含义:

  down:当前的server暂时不参与负载均衡。
  backup:预留的备份服务器,当其它节点不存活了,再启动。
  max_fails:允许请求失败的次数,当请求失败的次数用完了就不在尝试,休息,执行fail_timeout。
  fail_timeout:经过max_fails失败后,服务暂停的时间。
  max_conns:限制最大的接收的连接数,节点性能不一致时配置。

  3、Nginx的调度算法

  轮询(默认):按时间顺序逐一分配到不同的后端服务器。
  加权轮询:weight值越大,分配到的访问几率越高。
  ip_hash:每个请求按访问IP的hash结果分配,这样来自同一个IP的固定访问一个后端服务器。
  url_hash:按照访问的URL的hash结果来分配请求,是每个URL定向到同一个后端服务器。
  least_conn:最少连接数,哪个机器连接数少就分发。
  hash关键数值:hash自定义的key。

  ip_hash缺陷:如果前端再走一层代理,那么取到的remote_addr就不是用户真实的IP。

  4、示例

  准备两台虚拟机151和152。151上配置Nginx负载均衡,152上由Nginx配置3个不同端口提供服务。

  在152上新建/opt/app/code1/index.html;opt/app/code2/index.html;opt/app/code3/index.html;内容分别为:

<html>
<head>
    <meta charset="utf-8">
    <title>server1</title>
</head>
<body style="background-color:yellow;">
    <h1>Server 1<h1>
</body>
</html>
<html>
<head>
    <meta charset="utf-8">
    <title>server2</title>
</head>
<body style="background-color:red;">
    <h1>Server 2<h1>
</body>
</html>
<html>
<head>
    <meta charset="utf-8">
    <title>server3</title>
</head>
<body style="background-color:yellow;">
    <h1>Server 3<h1>
</body>
</html>

  在152的/etc/nginx/conf.d中新建server1.conf、server2.conf、server3.conf,分别指定端口和首页路径

server {
    listen       8001;
    server_name  localhost;

    access_log  /var/log/nginx/server1.access.log  main;

    location / {
        root   /opt/app/code1;
        index  index.html index.htm;
    }
... ... }
server {
    listen       8002;
    server_name  localhost;

    access_log  /var/log/nginx/server2.access.log  main;

    location / {
        root   /opt/app/code2;
        index  index.html index.htm;
    }
... ... }
server {
    listen       8003;
    server_name  localhost;

    access_log  /var/log/nginx/server3.access.log  main;

    location / {
        root   /opt/app/code3;
        index  index.html index.htm;
    }
... ... }

  在151的/etc/nginx/conf.d中新建upstream_test.conf,其中myLoad是定义的负载名字 

upstream myLoad {
    server 192.168.7.152:8001;
    server 192.168.7.152:8002;
    server 192.168.7.152:8003;
}

server {
    listen       80;
    server_name  localhost;

    access_log  /var/log/nginx/test_upstream.access.log  main;
    resolver  8.8.8.8;
    
    location / {
        proxy_pass http://myLoad;
        include proxy_params;
    }
... ... }

  1)演示轮询和某节点宕机后依然能正常访问

  启动152和151的Nginx,浏览器输入:http://192.168.7.151/,验证是轮流访问3个端口。

  验证一个节点宕机,剩余的节点可以正常服务。现在用的是一台虚拟机模拟3个应用,手动禁掉8002端口:

iptables -I INPUT -p tcp --dport 8002 -j DROP

  再次访问http://192.168.7.151/,验证是轮流访问8001和8003端口。清除掉临时的规则,使8002端口可以正常访问:

iptables -F

  清除掉规则后,浏览器输入:http://192.168.7.151/,变成了3个端口轮流访问。

  2)演示backup

  重新修改151上的配置文件,负载均衡部分改为如下:

upstream myLoad {
    server 192.168.7.152:8001 down;
    server 192.168.7.152:8002 backup;
    server 192.168.7.152:8003 max_fails=1 fail_timeout=10s;
}

  重新启动Nginx,并访问http://192.168.7.151/,发现不在再轮询,只有8003能访问。使用iptables禁掉8003后发现8002顶了上来,8002可以访问。重新启用8003后,8002不可以访问了,只有8003可以访问。

  3)演示加权轮询

  重新修改151上的配置文件,负载均衡部分改为如下:

upstream myLoad {
    server 192.168.7.152:8001;
    server 192.168.7.152:8002 weight=5;
    server 192.168.7.152:8003;
}

  重新启动Nginx,并访问http://192.168.7.151/,发现访问7次,有5次访问的是端口8002,其它各访问了1次。

  4)演示ip_hash

  重新修改151上的配置文件,负载均衡部分改为如下:

upstream myLoad {
    ip_hash;
    server 192.168.7.152:8001;
    server 192.168.7.152:8002;
    server 192.168.7.152:8003;
}

  重新启动Nginx,并访问http://192.168.7.151/,多次刷新发现一直访问8002,因为基于$remote_addr做hash,客户端IP固定。

  5)演示hash key

  说明:ip_hash可以理解为hash key的变体,ip_hash是固定的ip访问同一台服务器,hash key是固定的key访问同一台服务器。在实际工作中,我们会遇到这种情况,浏览器请求一个url,访问的是服务器1,服务器1缓存了一部分内容,浏览器又请求了一遍该url,访问的是服务器2,服务器2又缓存了一部分内容,这两部分内容可能不一致,这样浏览器访问同一个url可能会出现不一致的结果。原则上使用ip_hash可以解决,但是往往无法取到客户端的ip。这时可以使hash key实现。语法如下:

  Syntax:hash key [consistent];
  Default:-
  Context:upstream
  This directive appeared in version 1.7.2.(该版本后推出)

  下面演示一下hash $request_uri,请求的是同一个url的时候就定位到同一台服务器上。

  在152上的/opt/app/code1、code2、code3中分别新建url1.html、url2.html、url3.html共9个文件,内容分别为:

<html>
<head>
    <meta charset="utf-8">
    <title>server1</title>
</head>
<body style="background-color:yellow;">
    <h1>Server 1 url 1<h1>
</body>
</html>

  其余8个html文件基本类似,修改一下背景色和显示内容即可

code1/url2.html:背景色yellow,显示内容Server 1 url 2
code1/url3.html:背景色yellow,显示内容Server 1 url 3
code2/url1.html:背景色red,   显示内容Server 2 url 1
code2/url2.html:背景色red,   显示内容Server 2 url 2
code2/url3.html:背景色red,   显示内容Server 2 url 3
code3/url1.html:背景色blue,  显示内容Server 3 url 1
code3/url2.html:背景色blue,  显示内容Server 3 url 2
code3/url3.html:背景色blue,  显示内容Server 3 url 3

  重新修改151上的配置文件,负载均衡部分改为如下:

upstream myLoad {
  hash $request_uri;
   server 192.168.7.152:8001;
   server 192.168.7.152:8002;
   server 192.168.7.152:8003;
}

  重新启动Nginx,并访问http://192.168.7.151/url1.html,多次刷新发现同一个url访问同一台服务器。

  备注:实际url可能很长,可以根据规则,使用表达式截取后的来定位同一台服务器。hash key支持表达式。

  

 

posted @ 2020-05-12 20:31  雷雨客  阅读(755)  评论(0编辑  收藏  举报