• (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支持表达式。

      

  • 相关阅读:
    flex,flashDevelop和gumbo编译器比较
    用侦听器的useCapture属性决定事件哪个阶段做处理
    关于显示对象的parent,stage属性的说明
    ASP.NET MVC 1.0 Result 几何?
    MVC Controller与ActionResult的返回值
    C# 可空类型和空接合运算符(??)
    C# 2.0新特性与C# 3.5新特性
    创建返回Excel的自定义ActionResult
    jQuery getJSON()函数及getScript()函数
    如何使用ASP.NET MVC的Filter
  • 原文地址:https://www.cnblogs.com/javasl/p/12878408.html
Copyright © 2020-2023  润新知