Nginx反向代理和负载均衡总结

对Nginx反向代理和负载均衡配置的总结

Posted by wang chong on January 31, 2019

nginx

nginx是一款HTTP服务器和代理服务器。Nginx功能丰富,除了上面的功能之外还可以支持FastCGI、SSL、Virtual Host 、 URL Rewrite 、 Gzip等功能。并且支持很多第三方模块扩展。

反向代理

nginx是一款反向代理服务器,说道反向代理,不得不说正向代理。

正向代理

正向代理:局域网内通过代理服务器去访问局域网外的东西这就叫正向代理。 如图: 上面图通过局域网内的代理服务器访问外网的网站,就是通过正向代理服务器实现的。

反向代理

反向代理:互联网外的客户端通过代理服务器访问内网的服务器叫做反向代理。

反向代理就像一个公司看大门的老大爷,当我们去这家公司去找人的时候,首先经过的就是大门。我们向大爷说找谁,大爷给我们传信说:xxx有人找。这就达到了反向代理的作用。 如图:

反向代理的用途

  1. 加密和SSL加速

    https就配置在反向代理上,把后端的压力给处理出来。

  2. 负载均衡

    当一个请求过来的时候,通过代理策略把请求分配到比较闲的服务器上去

  3. 缓存静态内容

    apache这样的服务器优点在于处理动态内容,处理静态内容返回效率很低,因此把静态内容放在反向代理上缓存。

  4. 压缩

    页面压缩,在反向代理中的配置文件中(gzip)配置。

  5. 减速上传

    可以控制上传和下载速度(例如百度云盘的下载速度就是用这个控制的)。

  6. 安全

    反向代理服务器是进入内网当中的第一道门,如果有黑客想要攻入你的网站的话,第一个要攻的就是反向代理服务器,如果把web服务器暴露在公网上,那就直接攻击web服务器了。

  7. 外网发布

    对外网显示,用于外网来访问,同样也是我们前端最关注的。

Web缓存

Nginx 可以对不同的文件做不同的缓存处理,配置灵活,并且支持FastCGI_Cache,主要用于对Fast CGI的动态程序进行缓存。配合着第三方的ngx_cache_purge,对指定的URL缓存内容可以进行增删管理。

Nginx配置文件结构

nginx安装好之后,配置文件在nginx下的con文件夹下的nginx.conf文件夹。nginx的配置文件结构如下

...         #全局块
events{     #events块
    ...    
}
http{       #http块
    ...     #http全局块
    server{         #server块
        ...         #server全局块
        location [PATTERN]  #locattion块
        {
            ...
        }
        location [PATTERN]
        {
            
        }
    }
    server{
        ...
    }
    ...     #http全局块
}
  1. 全局块:配置影响nginx全局的指令。一般有运行nginx服务器的用户组、nginx进程pid存放路径、日志存放路径、配置文件引入、允许生成worker process数等。
  2. events块:配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数、选取哪种事件驱动模型处理连接、是否允许同时接受多个网路连接、开启多个网络连接序列化等。
  3. http块:可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。如文件引入、mime-typ定义、日志自定义、是否使用sendfile传输文件、连接超时时间、单连接请求数等。
  4. server块:配置虚拟主机的相关参数,一个http中可以有多个server。
  5. location块:配置请求的路由,以及各种页面的处理情况。

nginx的基本配置

每个指令必须有分号结束。

#use admininstrator admininstrator   #配置用户或者组,默认为nobody  nobody
worker_processes 2;  #允许生成的进程数,默认为1
#pid /nginx/pid/nginx.pid;  #指定nginx进程运行文件的存放位置
error_log log/error.log debug; #制定日志路径,级别。这个设置可放在全局块,http块,server块,
                        #级别为:debug | info | notice | warn | error | crit | alert | emerg
events{
    accept_mutex on;    #设置网络连接序列化,防止惊群现象发生,默认为on
    multi_accept on;    #设置一个进程是否同时接受多个网络连接,默认为off
    #use epoll;         #事件驱动模型
                        selete | poll | kequeue | epoll | resig |/dev/poll | eventport
    worker_connections  1024;   #最大连接数。默认为512;
}
http{
    include     mime.types;     #文件扩展名与文件类型映射表
    default_type    application/octet-stream; #默认文件类型,默认为text/plain
    #access_log off;    #取消服务日志
    log_format myFormat '$remote_addr–$remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for';
            #自定义格式
    access_log log/access.log myFormat; #combined为日志格式的默认值
    sendfile on;    #允许sendfile方式传输文件,默认为off,可以在http块,serve块
,location块
    sendfile_max_chunk 100k; #每个进程每次调用传输数量不能大于设定的值,默认为0,即不设上限
    keepalive_timeout 65;   #连接超时时间,默认为75s,可以在http、server、location块
    error_page 404 https://www,baidu.com;   #错误页
    
    upstream mysvr{     #负载均衡配置
        server 127.0.0.1:8080;
        server 127.0.0.1:8081 backup; #热备
    }
    server{
        keepalive_requests 120;     #单连接请求上限次数
        listen      80;             #监听端口
        server_name 127.0.0.1;      #监听地址
        location ~*^.+$ {   #请求url过滤,正则匹配,~为区分大小写,~*为不区分大小写。
            #root path              #根目录
            #index vv.txt;          #设置默认页
            proxy_pass  http://mysvr;    #请求转向mysvr 定义的服务器列表
            deny 127.0.0.1;         #拒绝访问的ip
            allow 172.18.5.54;     #允许访问的ip
        }
    }
    
}
配置项中需要注意的点。
  1. 配置项

    • $ remote_addr和 $ http_x_forwarded_for 用于记录客户端的ip地址
    • $remote_user 用来记录客户端用户名称
    • $time_local 用来记录访问时间和时区
    • $request 用来记录请求的url和http协议
    • $status 用来记录清请求状态:成功是200
    • body_bytes_s ent 用来记录发送给客户端文件主体内容大小
    • $http_referer 用来记录从哪个页面链接访问过来的
    • $http_user_agent 用来记录客户端浏览器的相关信息
  2. 惊群现象:一个网络链接到来,多个睡眠的进程被同时唤醒,但只有一个进行能获得链接,这样会影响系统性能。

Nginx代理服务的配置

  • 上面配置文件中的错误页面404指向百度是不起作用的,如果向让它起作用必须配合下面的这个配置一起来用。
proxy_intercept_errors on;      #如果被代理服务器返回的状态码为400或者大于400,设置的error_page配置起作用,默认为off
  • 如果我们的代理只允许接受get、post请求方法的一种
proxy_method get;       #支持客户端的请求方法。post/get;
  • 设置支持的http协议的版本
proxy_http_version 1.0; #Nginx服务器提供代理服务的http协议版本1.0,1.1,,默认为1.0版本
  • 当nginx服务器配置2台以上的web服务器做代理,负载均衡算法使用轮询方式,如果其中的一台服务器瘫痪了,也就是说web服务不能访问了,那么nginx还是会给这台不能访问的服务器分发请求,如果响应时间过长,就会导致客户端一直在响应,对用户来说体验极差。可以采用配置来作为解决方案。

proxy_connect_timeout 1;    #nginx服务器与代理服务器建立连接的超时时间,默认为60秒
proxy_read_timeout 1;       #nginx服务器想被代理服务器组发出read请求后,等待响应的超时时间,默认为60秒
proxy_send_timeout 1;       #nginx服务器想被代理服务器组发出write请求后,等待响应的超时时间,默认为60秒
proxy_ignore_client_abort on;  #客户端断网时,nginx服务器是否中断对被代理服务器的请求,默认为off
  • 如果使用upstream指令配置了一组服务器作为被代理服务器,服务器中的访问算法遵循配置的负载均衡规则,同时可以使用该指令配置在发生哪些异常情况时,将请求顺次交给下一组服务器处理。
proxy_next_upstream timeoit;    #反向代理upstream中设置的服务器组,出现故障时,被代理服务器返回的状态值。
error | timeout | invaluid_header | http_500  | http_502 | http_503 | http_504 | http_404 |off
    #error : 建立连接或向被代理的服务器发送请求或读取响应信息时服务器发生错误。
    #timeout :建立连接,向被代理服务器发送请求或读取响应信息时服务器发生超时
    #invalid_header :被代理服务器返回的响应头异常
    #off :无法将请求分发给被代理的服务器
    #http_400,... :被代理服务器返回的状态码为400、500、502等
  • 如果想通过http获取客户端的真正ip而不是获取代理服务器的ip地址,那么要做一下设置。
proxy_set_header Host $host;    #只要用户在浏览器这种访问了域名绑定了 VIP VIP下面有RS;则就用$host;host是访问URL中的域名和端口;例如:www.taibao.com:80
proxy_set_header X-Real_IP $remote_addr; #把源IP【$remote_addr,建立HTTP连接header里面的信息】赋值给X-Real-IP;这样在代码中$X-Real-IP来获取 源IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;   #在nginx 作为代理服务器时,设置的IP列表,会把经过的机器ip,代理机器ip都记录下来
                    #用【,】隔开;代码中用echo $x-forwarded-for |awk -F,'{print $1}来作为源IP'

nginx的负载均衡

Nginx是一个通过反向代理是实现负载均衡的服务器,使用Nginx服务实现负载均衡的时候,用户的访问首先会访问到Nginx服务器,然后Nginx服务器再从服务器集群表中选择压力较小的服务器,然后将该访问请求引向该服务器。若服务器集群中的某个服务器崩溃,那么从待选服务器列表中将该服务器删除,也就是说一个服务器假如崩溃了,那么Nginx就肯定不会将访问请求引入该服务器了。

负载均衡的策略

nginx负载均衡有两种策略:内置策略和扩展策略。内置策略为:轮询、加权轮询、Ip hash;扩展策略就很多了。

内置策略

轮询

通过一下要说的upstream模块进行配置负载均衡,默认的是轮询。即每一台服务器按个访问一次。

加权轮询

加权轮询就是通过对每一台服务器加权重,已达到不同的轮询效果。比如说一台服务器比较好,那么这太服务器的权重就大些,那么落在这台服务器上的请求就会多。

Ip hash

Ip hash 对客户端的ip进行hash操作,然后根据hash结果将同一个客户端ip的请求分发给同一台服务器进行处理,可以解决session不共享的问题。

在负载均衡系统中,假如用户在某台服务器上登录,那么如果该用户第二次请求的时候,因为我们是负载均衡系统,每次请求都会重新定位到服务器集群中的一个服务器,那么此时如果将已经登录服务器A的用户再定位到其他服务器,显然不妥。故而,我们可以采用ip_hash指令解决这个问题,如果客户端请求已经访问了服务器A并登录,那么我们第二次请求的时候,会将该请求通过哈希算法自动定位到该后端服务器中。

HTTP upstream模块

upstream模块用来配置代理服务器和负载均衡,有两种写法:

第一种:

upstream mysvr {    #mysvr是这个反向代理的名字
    server 192.168.10.121:3333;
    server 192.168.10.122:3333;
}
server{
    ....
    location ~*^.+${
        proxy_pass http://mysvr #将请求转向mysvr 定义的服务器列表
    }
}

第二种:

upstream mysvr{
    server http://192.168.10.121:3333;
    server http://192.168.10.122:3333;
}
server{
    ....
    location ~*^.+${
        proxy_pass mysvr #将请求转向mysvr 定义的服务器列表
    }
}

两种都有共同点就是代理服务器路径必须完整。例如:http://exmple.com:3333。第一种是把http前缀写在了location里面;第二种是把http前缀写在了upstream里面。

负载均衡的参数解析及内置策略解析

热备

比如说如果有两台服务器,当一台服务器发生事故时,才启用第二台服务器给提供服务。服务器处理请求的顺序:AAAAAA(A突然挂了),BBBBB…..

upstream mysvr{
    server 127.0.0.1:7878;
    server 192.168.10.121:3333 backup;  #热备
}
轮询

nginx默认的轮询其权重都默认为1,服务器处理请求的顺序:ABABABA…

upstream mysvr{
    server 127.0.0.1:7878;
    server 192.168.10.121:3333;
}
加权轮询

加权轮询是根据每一台负载均衡服务器的权重来分发不同数量的请求。如果不设置,就默认为1,下面请求是ABBABBABBABB…

upstream mysvr{
    server 127.0.0.1:7878 weight=1;
    server 192.168.10.121:3333 weight=2;
}
Ip_hash

Ip_hash会根据hash算法来让相同的客户端ip请求相同的服务器。

upstream mysvr{
    server 127.0.0.1:7878;
    server 192.168.10.121:3333;
    ip_hash;
}
其他参数
  1. down:表示当前的server暂时不参与负载均衡。
  2. backup:预留的备份机器。当其他所有的非backup机器出现故障或者忙的时候,才会请求backup机器,因此这台机器的压力最轻。
  3. max_fails:允许请求失败的次数,默认为1.当超过最大次数时,返回proxy_next_upstream模块定义的错误。
  4. fail_timeout:在经历了max_fails次失败后,暂停服务的时间。max_fails可以和fail_timeout一起使用。
upstream mysvr {
    server 127.0.0.1:7878 weight=2 max_fails=2 fail_timeout=2;
    server 192.168.10.121:3333 weight=1 max_fails=2 fail_timeout=1;
}

最后几个nginx命令

nginx -s reload 重启nginx

nginx -s stop 关闭nginx

nginx -t 确定配置是否有效

nginx -c xxx.conf 指定自己的配置文件且不对源文件生效