• 2.2.0Nginx代理与负载均衡


    TOC

    Nginx代理proxy_pass与负载均衡upstream

    参考:

    Nginx代理服务

    代理语法:

    Syntax: proxy_pass URL;
    Default:-
    Context:location,if in location,limit_except

    正向代理:

    案例1

    code文件夹中的html:jesonc.html

    <html>
    <head>
        <meta charset="utf-8">
        <title>jeson1</title>
    </head>
    <body >
        <h1>Jeson<h1>
    </body>
    </html>
    

    配置

    server {
        listen       80;
        server_name  localhost jeson.t.imooc.io;
    
        #charset koi8-r;
        access_log  /var/log/nginx/host.access.log  main;
    
        location / {
            # http_x_forwarded_for放的是所有d代理的ip信息
            if ( $http_x_forwarded_for !~* "^192.168.0.173") { # 192.168.0.173 是我准备的地址
                return 403;
            }
            root   /usr/share/nginx/html/code;
            index  index.html index.htm;
        }
    
        #error_page  404              /404.html;
    
        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504 404  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }

    直接访问 http://jeson.t.imooc.io/jesonc.html 提示403

    在192.168.0.173 上配置正向代理:

    192.168.0.173上的nginx配置

    server {
        listen       80;
        server_name  localhost jeson.t.imooc.io;
    
        #charset koi8-r;
        access_log  /var/log/nginx/test_proxy.access.log  main;
        resolver 8.8.8.8;   # 添加进行域名解析
        location / {
            proxy_pass http://$http_host$request_uri; # 将请求专区转到对应的 主机名,url
        }
    
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }

    浏览器设置代理:将 192.168.0.173 80 设置上

    这是访问http://jeson.t.imooc.io/jesonc.html 就会自动调用代理,就能访问到了

    在这里插入图片描述

    案例2

    Nginx正向代理只需要配置 location 中配置proxy_pass 属性即可。其指向代理的服务器地址。正如我们上一篇文章配置的百度的代理:
    在这里插入图片描述

    这是一个经典的正向代理的例子。

    Nginx的反向代理

    案例1

    html页面

    <html>
    <head>
        <meta charset="utf-8">
        <title>imooc1</title>
    </head>
    <body style="background-color:red;">
        <h1>Welcome to jeson.t.imooc.io</h1>
    </body>
    </html>
    

    host设置

    192.168.179.128 jeson.t.imooc.io

    配置1:realserver.conf

    监听了8080端口

    server {
        listen       8080;
        server_name  localhost jeson.t.imooc.io;
    
        #charset koi8-r;
        access_log  /var/log/nginx/server.access.log  main;
    
        location / {
            root   /usr/share/nginx/html/code2;
            index  index.html index.htm;
        }
    
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    
    }

    配置2:反向代理fx_proxy.conf

    监听了80端口

    当匹配 /test_proxy.html$ 的时候,会用 proxy_pass,转为请求 http://127.0.0.1:8080;

    server {
        listen       80;
        server_name  localhost jeson.t.imooc.io;
    
        #charset koi8-r;
        access_log  /var/log/nginx/test_proxy.access.log  main;
    
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }
    
        location ~ /test_proxy.html$ {
            proxy_pass http://127.0.0.1:8080;
        }
    
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    
    }

    在服务器/容器 查看nginx的端口

    在这里插入图片描述

    由于nginx服务/nginx容器只开发了80端口,所以在访问8080端口的时候 http://jeson.t.imooc.io:8080/test_proxy.html ,会无法找到页面

    在这里插入图片描述

    若是访问80端口 http://jeson.t.imooc.io/test_proxy.html 进入的就是默认的 fx_proxy.conf /设置的/test_proxy.html$配置,进而调用了http://127.0.0.1:8080 --> realserver.conf-->默认的/

    http://jeson.t.imooc.io域名改为了 http://127.0.0.1:8080 域名

    小例子

    首先启动两个应用,端口分别是8010和8020,访问/hello:

    在这里插入图片描述

    img

    然后我们在nginx中,首先反向代理一个地址:

    server {
        listen 80;
        server_name www.demo.com;
        location / {
            proxy_pass http://127.0.0.1:8080;
        }
    }

    可以看到,监听80端口,代理的是8010的端口地址,路径是/hello。然后在配置一下本地

    host

    192.168.168.129 www.demo.com

    然后访问可以看到反向代理成功:

    可以看到正向代理和反向代理在配置上区别不大,主要区别是被代理的服务的位置,一个是远程(百度),一个是局域网内部(本机8010)。

    案例3

    反向代理还有一个用途就是在多个站点配置多个二级域名,比如百度的搜索引擎是 www.baidu.com,百度图片是 image.baidu.com,百度翻译是 fanyi.baidu.com,可以看到,一级域名一样,二级域名不同,代表了不同的系统。这种方式利用nginx的反向代理也可以实现,

    server {
        listen 80;
        server_name test1.demo.com;
        location / {
            proxy_pass http://127.0.0.1:8010;
        }
    }
    server {
        listen 80;
        server_name test2.demo.com;
        location / {
            proxy_pass http://127.0.0.1:8020;
        }
    }

    host

    192.168.168.129 test1.demo.com
    192.168.168.129 test2.demo.com

    可以看到,两个不同的二级域名分别访问两个不同的端口地址,访问效果如下:

    在这里插入图片描述

    在这里插入图片描述

    这样可以做到在一个服务器上部署多个项目,分别使用有意义的二级域名。

    缓冲区:proxy_buffering

    Syntax: proxy_buffering on | off;
    Default:proxy_buffering on;
    Context:http,server,location

    扩展:proxy_buffer_size、proxy_buffers、proxy_busy_buffers_size

    减少了包个数,减少了io损耗;

    默认在内存里,内存不够在硬盘里

    跳转重定向:proxy_redirect

    Syntax: proxy_redirect default; proxy_redirect off;proxy_redirect redirect replacement;
    Default:proxy_redirect default;
    Context:http,server,location,

    头信息

    Syntax: proxy_set_header field value;
    Default:proxy_set_header Host $proxy_host;
    proxy_set_header Connection close;
    Context:http,server,location

    扩展:proxy_hide_header(隐藏一部分后,不让后端访问到)、proxy_set_body(在body中添加一些自定义字符)

    新增一个头信息,记录代理前的准确的头信息

    超时

    Syntax:proxy_connect_timeout time; #请求连接的时间
    Default:proxy_connect_timeout 60s;
    Context:http,server,location

    扩展:proxy_read_timeout(已经建立连接后,等待(处理)的时间)、proxy_send_timeout(向客户端发送的时间)

    代理相关参数

    proxy_pass   http://127.0.0.1:8080;       # 代理服务
    
    proxy_redirect default|off;  # 是否允许重定向
    
    proxy_set_header Host $host; # 传 header 参数至后端服务
    
    proxy_set_header X-Forwarded-For $remote_addr; # 设置 即客户端IP 地址
    
    proxy_connect_timeout 90; # 连接代理服务超时时间
    
    proxy_send_timeout 90; # 请求发送最大时间
    
    proxy_read_timeout 90;  # 读取最大时间
    
    proxy_buffer_size 32k; # 缓冲区第一部分头信息大小
    
    proxy_buffering on; #打开缓冲区
    
    proxy_buffers 4 128k; #缓冲区,先用这个
    
    proxy_busy_buffers_size 256k; # 再用这个
    
    proxy_temp_file_write_size 256k; # 大文件或者上面满了用这个
    

    使用 nginx -V,可以看到缓冲区配置:--http-proxy-temp-path=/var/cache/nginx/proxy_temp

    这种配置一般是通用的,可以创建一个文件,然后在location中使用 include引入;

    负载均衡

    所有客户端的请求通过proxy_pass转发到一组虚拟的服务池(upstream server:这里面的服务是能够提供相同的服务的集合),请求轮询访问服务器

    通过proxy_pass 可以把请求代理至后端服务,但是为了实现更高的负载及性能, 我们的后端服务通常是多个, 这个是时候可以通过upstream模块实现负载均衡。

    语法:

    Syntax: upstream name {...}
    Default:一
    Context:http

    upstream

    一个案例:

    upstream backend{
        server backendl.example.com weight=5;
        server backend2.example.com:8080;
        server unix:/tmp/backend3;
    
        server backupl.example.com:8080 backup;
        server backup2.example.com:8080 backup;
    }
    • upstream后面是组的名字
    • upstream里面是每一个server
      • server支持:
      • 域名
      • ip
      • 域名或者ip:端口
      • socket方式
      • server配置后面还可以加小的参数:
      • backup:这是一个备份结点
      • weight权重,越大,轮询分配的可能越高

    案例1:开启负载均衡

    启用两个服务器,其中一个启动三个服务

    #服务1 server1.conf
    server {
        listen       8001;
        server_name  localhost;
    
        access_log  /var/log/nginx/log/server1.access.log  main;
    
        location / {
            root   /opt/app/code1;
            index  index.html index.htm;
        }
        error_page   500 502 503 504 404  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }
    
    #服务2 server2.conf
    server {
        listen       8002;
        server_name  localhost;
    
        access_log  /var/log/nginx/log/server2.access.log  main;
    
        location / {
            root   /opt/app/code2;
            index  index.html index.htm;
        }
    
        error_page   500 502 503 504 404  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }
    
    #服务3 server3.conf
    server {
        listen       8003;
        server_name  localhost;
        #access_log  /var/log/nginx/log/server2.access.log  main;
    
        location / {
            root   /opt/app/code3;
            index  index.html index.htm;
        }
        error_page   500 502 503 504 404  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }

    负载均衡配置:upstream_test.conf

        upstream imooc { #名字
            server 116.62.103.228:8001; #节点
            server 116.62.103.228:8002;
            server 116.62.103.228:8003;
        }
    
    server {
        listen       80;
        server_name  localhost jeson.t.imooc.io;
    
        access_log  /var/log/nginx/test_proxy.access.log  main;
        resolver  8.8.8.8;
    
        location / {
            proxy_pass http://imooc; #把请求代理至后端服务,代理
            include proxy_params;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }

    另一台服务, 此时访问:http://jeson.t.imooc.io 访问的就是上面配置的三个服务的了,默认是轮询的

    此时关闭一个服务

    # 由于是使用的nginx配置的进程服务,若是关闭的话,只能三个一起关了,所以使用下面的
    iptables -I INPUT -p tcp --dport 8002 -j DROP # 把所有请求8002的请求关掉--不对外提供8002端口

    此时访问,请求就会在server1和server3之间轮询---server2挂掉之后,nginx就会自动处理,将server2服务下线了

    案例3

    下面来配置一个upstream:

    upstream wwwdemocom{
        server 127.0.0.1:8010;
        server 127.0.0.1:8020;
    }

    可以看到把两个服务地址都定义到了一个upstream中,并起名为wwwdemocom,下面设置反向代理:

    server {
        listen 80;
        server_name www.demo.com;
        location / {
            proxy_pass http://wwwdemocom;
        }
    }

    反向代理的配置中,只配置upstream的名字即可,刷新页面,可以看到同一个地址,不停的分别访问两个项目:

    在这里插入图片描述

    在这里插入图片描述

    这样如果我们部署多个相同的系统,可以把所有的并发流量分到多个上面,从而达到提高并发的目的。

    后端服务器在负载均衡调度中的状态

    参数 定义
    down 当前的server暂时不参与负载均衡
    backup 预留的备份服务器
    max_fails 允许请求失败的次数
    fail_timeout 经过max_fails失败后,服务暂停的时间
    max_conns 限制这个服务最大的接收的连接数
    weight 权重

    案例2:测试备份节点backup

    配置服务:upstream_test.conf

        upstream imooc {
            server 116.62.103.228:8001 down; #不提供服务
            server 116.62.103.228:8002 backup; #备份结点
            server 116.62.103.228:8003 max_fails=1 fail_timeout=10s;
        }
    
    server {
        listen       80;
        server_name  localhost jeson.t.imooc.io;
    
        access_log  /var/log/nginx/test_proxy.access.log  main;
        resolver  8.8.8.8;
    
        location / {
            proxy_pass http://imooc;
            include proxy_params;
        }
    
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }

    此时只有server3提供服务,刷新页面,也只显示了server3

    此时关掉server3,此时刷新页面,服务会很慢,过段时间,就切换到了server2(备份结点)

    若是此时开启server3,就又能继续访问server3了(server继续不能访问了)

    备份服务

    在服务器上再启动一个8030的服务

    在这里插入图片描述

    将此服务作为一个备份服务,有服务意外停止的时候,这个顶上去!

    upstream wwwdemocom{
        server 127.0.0.1:8010 weight=1;
        server 127.0.0.1:8020 weight=2;
        server 127.0.0.1:8030 backup; # 不能加weight等参数
    }

    重启nginx,先刷新页面查看效果,发现还是配置的8010和8020两个在做负载均衡,现在停止8010和8020,可以看到8030顶上来了:

    注意:关闭一个服务不会触发备用服务,只有8010和8020全都意外停止,8030才会顶上来!

    如果再把8010重新启动,那么备份服务就不会起作用了

    max_fails和fail_timeout

    nginx在原来的8010服务器重新启动以后,能很快检测到原来的8010恢复了,并投入使用,是因为nginx和8010之间有类似心跳检测的机制,实时监控8010是否能用。

    • max_fails参数就是设置失败多少次后,认为已经挂了,就剔除
    • fail_timeout参数就是剔除后从新检测这个属性也是设置恢复时检测的时长间隔,比如设置一分钟,那么服务恢复后得隔一分钟才能检测到并投入使用。

    可以想象,如果实时去检查的话,会很消耗性能,所以这两个参数非常有用。

    下面我们把失败最大重试次数设置成10次,恢复检测时长设置成30秒:

    upstream wwwdemocom{
        server 127.0.0.1:8010 weight=1 fail_timeout=30s max_fails=10;
        server 127.0.0.1:8020 weight=2 fail_timeout=30s max_fails=10;
        server 127.0.0.1:8030 backup;
    }

    重新加载,然后停止8010和8020,访问页面,可以看到加载了一会才会出现8030的结果,如果重试次数设置成100次,加载时间会更明显。我们把8010启动起来,可以看到前面三十秒左右还是8030,后面又开始访问8010:

    这两个参数也是很重要的参数,在实际生成环境中会用到。要合理设置重试次数和等待时间

    调度算法,轮询等

    算法 定义
    轮询 按时间顺序逐一分配到不同的后端服务器
    加权轮询 (默认)weight值越大,分配到的访问几率越高,缺点是,其中一个连接满了,nginx还是会加连接过去导致连接越来越多,速度越来越慢,不够自动化和智能化
    ip_hash 每个请求按访问IP的hash结果分配,这样来自同一个IP的固定访问一个后端服务器,用于保持session 一至性,解决分布式session同步问题,缺点是现在很多小区或者学校都是用的一根光纤,大部分人的ip是一样的,容易导致某个服务连接数量过多,出现负载不均衡的情况,而且机器挂掉,会话随着会丢失
    url_hash 按照访问的URL的hash结果来分配请求,是每个URL定向到同一个后端服务器,静态资源缓存,节约存储,加快速度(第三方),和ip_hash的计算方法一样,应用场景不同,通过这种算法可以把一些静态资源平均分布到各个服务中,节省空间
    least_conn 最少链接数,那个机器连接数少就分发,优先把请求分给和nginx连接最少的服务,最大化的利用资源
    hash关键数值 hash自定义的key
    least_time 最小的响应时间,计算节点平均响应时间,然后取响应最快的那个,分配更高权重(第三方),可以充分利用性能好的机器

    权重

    默认两个系统切换着访问,策略默认是轮训的,也就是无论几个系统都轮着循环访问。如果想让两台机器的访问数量按照1比2分配,那么可以设置权重:

    upstream wwwdemocom{
        server 127.0.0.1:8010 weight=1;
        server 127.0.0.1:8020 weight=2;
    }

    刷新页面可以看到,8010访问一次,紧接着8020访问两次,这种是按照权重分流,改变了原来默认的轮训策略。这种适合机器性能有区别的情况。

    ip_hash

    若是使用轮询、加权、least_conn的方式,cookie等的会比较麻烦,所以可以使用ip_hash,自同一个IP的固定访问一个后端服务器

    注意:除了把权重去掉,还有把backup的服务注释掉,两个不能同时用.

        upstream imooc {
            ip_hash; # 只需要设置一下这个参数
            server 116.62.103.228:8001;
            server 116.62.103.228:8002;
            server 116.62.103.228:8003;
        }
    
    server {
        listen       80;
        server_name  localhost jeson.t.imooc.io;
    
        access_log  /var/log/nginx/test_proxy.access.log  main;
        resolver  8.8.8.8;
    
        location / {
            proxy_pass http://imooc;
            include proxy_params;
        }
    
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }
    
    

    此时,同一个ip,定位的就是一个固定的服务器了.

    但是,若是客户走的是代理,那么获取的可能就不是客户的真实ip,可能无法做ip对应的轮询了,基于这个,出来了基于url的hash

    url_hash

    问题:

    • 我们想规定的IP请求固定的内容,让固定的IP按照IP来分配,往往无法取到用户端的IP
    • 缓存:服务器1缓存的一部分资源,服务器2缓存一部分的资源,那么当一个用户来先访问了服务器1以后,他会缓存住他返程的内容,再一次请求的时候,假设他如果跳到了服务器2,那么这样的话他又看到的是另外一部分内容,那么他看到的第1部分内容和第2部分内容是不一致的
    Syntax: hash key [consistent];
    Default:一
    Context:upstream
    This directive appeared in version 1.7.2. #发现版本

    资源:Nginx从入门到实践projecty1k2wh3-25

    静态资源html:code1、code2、code3三个文件夹,里面都有四个页面 index.html url1.html url2.html url3.html

    三个服务配置

    server {
        listen       8001; # 端口不同
        server_name  localhost;
    
        access_log  /var/log/nginx/log/server1.access.log  main;
    
        location / {
            root   /opt/app/code1;
            index  index.html index.htm;
        }
    
        error_page   500 502 503 504 404  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }

    负载均衡配置

        upstream imooc {
            hash $request_uri; # request_uri是请求的参数
            server 116.62.103.228:8001;
            server 116.62.103.228:8002;
            server 116.62.103.228:8003;
        }
    
    server {
        listen       80;
        server_name  localhost jeson.t.imooc.io;
    
        access_log  /var/log/nginx/test_proxy.access.log  main;
        resolver  8.8.8.8;
    
        location / {
            proxy_pass http://imooc;
            include proxy_params;
        }
    
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }

    注释掉hash $request_uri;:此时访问 http://jeson.t.imooc.io/url1.html,是在三个服务之间轮询

    开启hash $request_uri;:此时访问 http://jeson.t.imooc.io/url1.html,是在固定的服务器,换为url2.html,就会换一个固定的服务器了

    url_hash是根据域名来分配的





  • 相关阅读:
    第三章 C++中的C 《C++编程思想》
    网络时间协议 网络对时程序
    不相交集类应用:迷宫生成
    第一章 对象导言 第二章 对象的创建与使用
    获取本机IP MAC地址
    详解C#制做Active控件的五个步骤
    js HTML编码转换
    Web应用Word编辑
    HTML <map>标签的使用
    Web(浏览器)打开运行WinForm应用程序
  • 原文地址:https://www.cnblogs.com/ziyue7575/p/22a55d8573fad9b5593de747916efc10.html
Copyright © 2020-2023  润新知