2019-01-31 10:58:30 3

Nginx反向代理及负载均衡

前言

    Nginx是一个高性能的http和反向代理服务,优点是运行占用内存少,并发能力强,比较突出的作用是反向代理及负载均衡。反向代理就是服务器根据客户端的请求按照已有的配置转发到对应的资源上,然后再将资源返回给客户端。从客户端的角度看只知道有反向代理这个服务存在,并不知道代理服务内部所做的转发操作(以上解析参照百度百科)。通过反向代理的特性其实就可以推出Nginx具备负载均衡的特性,那就是对请求进行分发。Nginx对于请求分发的策略有很多,包括轮询、权重、最少连接等。


Nginx实现反向代理

    Nginx作为一个http服务,可以接收到http请求并转发到相应的资源上。那这个资源到底包括哪些东西呢?了解过Tomcat的都知道,tomcat可识别的资源包括浏览器可直接解析的一些静态资源,如html、css、js、图片等。那么同样作为http服务的nginx定然也是支持这类资源的操作的,所以nginx作为反向代理服务,业界常用于作为静态资源服务。除了静态资源外,由于nginx是对http请求的反向代理,所以只要是通过http协议操作的服务,都可以通过nginx来转发。

    Nginx反向代理的配置

    官网下载安装好nginx后,进入到nginx的conf配置目录(具体下载安装教程自行百度,我在centos7下安装后默认路径在/etc/nginx)。目录里主要关注nginx.conf配置文件,涉及反向代理及负载均衡的配置都是通过该文件配置。

    打开nginx.conf配置文件,内部结构大概如下

    这里配置反向代理主要关注server节点就行

    这里的server节点就好比如一个监听并转发请求的配置器,通过配置这个server可以实现对某一个请求地址和端口过来的请求进行转发到配置地址去。server节点中的listen配置的是监听请求到那个端口上,server_name配置的则是请求的地址(这个地址可以是域名或者ip,但是最终指向的都是nginx服务对应的ip),通过这两个配置就可以具体定位到某个请求的目的进程(类似socket套接字连接)。nginx通过监听所有到达这个ip和端口的请求,在进行转发操作。

    location配置的就是需要转发的目的地址。location后面跟的是监听请求的路径(可以按不同路径进行转发,通过这点可以实现静态资源服务),location内部配置的则是具体需要转发的路径。proxy_pass对应代理转发的目标地址(可以是域名或ip + 端口),proxy_set_header对应的是转发监听到请求对应的请求头信息(这里配置的目的是使得最终转发到的机器上能拿到请求客户端的头信息,包括请求原ip地址,一些自定义token等)。说白了server配置就是为了说明这个nginx服务需要监听那个位置进来的请求,在需要转发到那个目的机器上去。从上图还可以看到,这里是可以配置多个location的,这里我是吧带有/lego-image的请求统一转发到一个固定的路径上,因为我定义只要带有lego-image的都是静态资源,这样就可以直接拿到对应的图片等资源了(注:这里root必须要文件头定义,并且本地路劲.../lego-file对应的子目录要与请求/lego-image的子目录对应)。

    其他的配置都可以按需调整,包括一些传输是否压缩,client_max_body_size最大传输数据量(这个影响传输的最大数据,如果大于有可能会直接丢弃)。rewrite这个标签则是对请求进行重定向,我这里配置的目的是把所有的请求统一拦截并重定向为https的请求(具体拦截可按具体正则匹配)。

server {
    listen       80 ;
    server_name  zqliang.cn;

    rewrite ^(.*)$  https://$host$1 permanent;
    location / {
        #index   index.html index.htm;
        proxy_pass      http://www.zqliang.cn:8080;
        proxy_set_header        Host            $host;
        proxy_set_header        X-Forwarded-For         $remote_addr;
    }

    location /lego-image {
        root /usr/tomcat/spring-boot-project/lego-file;
    }

    gzip on;
    gzip_comp_level 7;
    gzip_min_length  1100; #需要压缩的最小长度
    gzip_buffers    4 8k;
    gzip_types      text/plain application/javascript text/css text/xml application/x-httpd-php; #指定需要压缩的文件类型
    output_buffers  1 32k;
    postpone_output  1460
    
    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}

    Nginx反向代理支持https

    很多时候请求使用的都是https协议操作,但是使用了nginx之后,所有请求基本都是先通过nginx再代理到其他机器上的,那这个我们应该怎么在nginx上支持对https协议的监听并代理转发呢?

    应该都知道https是安全签名的http进化协议,那么要使用https协议就必然需要用到https相关的秘钥证书(关于https协议的说明与涉及的秘钥请自行百度)。这里我使用的是crt证书及签名的私钥(有可能拿到的是csr文件,这个可以通过OpenSSL来转换,我这里是在腾讯云上直接申请的,阿里云上申请的好像是key和pem,这个一样可以)。配置的地方跟http基本一样,多了两个属性,分别是ssl_certificate用于配置证书以及ssl_certificat_key用于配置私钥。location一样可以按照http的配置,这样就可以对https的请求进行代理了(注:这里代理的目标地址不一定是要https协议,因为我们配置了私钥之后,nginx可以对签名内容解密了)。

    server {
        listen 443 ssl;
        server_name  zqliang.cn;

        ssl_certificate www.zqliang.cn.crt;
        ssl_certificate_key www.zqliang.cn.key;

        location / {
            proxy_redirect off;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_pass http://www.zqliang.cn:8080;
            proxy_connect_timeout 1;
        }

        location /lego-image {
            root /usr/tomcat/spring-boot-project/lego-file;
            proxy_redirect off;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_connect_timeout 1;
        }
    }


Nginx实现负载均衡

    我觉得负载均衡就是在反向代理的基础上增加了一些转发策略(个人理解,不一定正确,但通俗易懂),在理解了反向代理的原理及配置之后,要配置负载均衡应该十分简单了(但是要想配好就要按实际应用环境及测试结果)。通过上面反向代理的配置可以知道,server节点里会配置请求需要转发的目的地址(也就是proxy_pass对应的地址),那负载均衡用到的就是这个地址。

    负载均衡的配置涉及到一个新节点upstream,这个节点就是用于配置需要负载的多机器地址以及负载策略的。这里我把原来转发的目的地址替换成了upstream节点定义的site,这样当监听到请求过来时就会把请求转发到site中,而site里配置的地址就会按照对应的均衡策略进行转发。

    均衡策略主要包括:

    1、轮询:

    周期性的把请求循环分发到对应地址

    upstream site {
        server www.zqliang.cn:8080;
        server www.zqliang.cn:8081;
    }

    2、权重:

    按照配置的weight决定,哪个大哪个优先

    upstream site {
        server www.zqliang.cn:8080 weight=1;
        server www.zqliang.cn:8081 weight=1;
    }

    3、最少连接:

    判断哪个地址当前接收的连接数最少哪个就优先

    upstream site {
        least_conn;
        server www.zqliang.cn:8080;
        server www.zqliang.cn:8081;
    }

    4、ip_hash:

    按照目标地址的hash值固定转发(多用于没共享session的分部式架构)

    upstream site {
        ip_hash;
        server www.zqliang.cn:8080;
        server www.zqliang.cn:8081;
    }

    具体使用哪种策略按需求选择,我这边一般使用的都是权重(最主要的影响点不是请求转发的策略,而是异常处理机制)。在负载均衡配置中有一点比较重要的,就是失败超时时间,最大失败数以及连接超时时间:

    fail_timeout代表每次出现请求异常时需要等待多久后才会再把请求转发至该地址,max_fails代表当失败次数达到指定数量时停止转发请求到该地址,结合起来就是当异常次数到达指定次数后会定制指定时间后再把请求转发到该地址(防止因网络波动导致的伪异常情况)。

    proxy_connect_timeout代表请求等到多长时间没反应后标记为失败,当配置了负载均衡后,某一台机器出现异常了,请求就应该不再分派给它。这个异常的判断标准就可以通过这个连接超时时长配合max_fails来决定。

    由于nginx无法做到类似F5那样的硬件负载机制,所以软负载也是由缺陷的,当nginx服务异常,或者机器性能瓶颈都会影响nginx的负载。同时nginx只能尽可能的模拟出异常负载重试的机制。但nginx并发性能好,低成本,高效简易等特点还是具备很大优势的。


总结

    Nginx也算是目前主流的反向代理服务了,对于一般的请求分流以及静态资源访问都有很不错的效果,再搭配VUE前后端分离,那样基本能满足一般公司的请求需求了。虽然Nginx看起来使用简单,但要真正用好还是不易的。特别是在生成环境,如果出现一些特殊问题(连接数过多等)那还是需要耐心的了解下原理,必要时可以参考下正规的书籍(个人觉得网上基本是相互复制的,还是权威的书籍最有报障)。

← Previous Next →

0 Responses to "Nginx反向代理及负载均衡"

Leave a Reply

你没有登陆,必须填写name才能提交评论*

*

*

Copyright Obscura 2017. Design by zqliang. All Rights Reserved.Collect from 小梁
粤ICP备18034967号