<服务>Nginx反向代理

时间:Jan. 20, 2017 分类:

目录:

upstream模块

ngx_http_upstream_module官方文档 nginx支持多种模式,常用的支持的方式三种proxy_pass(反向代理),fastcgi_pass(和动态程序交互),memcached_pass(跟缓存数据库交互)

示例配置文件

upstream backend {
    server backend1.example.com       weight=5;
#server后边可以是域名,也可以是IP,如果不加端口默认是80,权重是代表分配的比率
    server backend2.example.com:8080;   #指定转发8080端口
    server unix:/tmp/backend3;      #指定

    server backup1.example.com:8080   backup;   
#backup是备用服务器,等上面指定的服务器都不可用的时候启用,和haproxy用法一样,当然备用还不如负载均衡使用呢
    server backup2.example.com:8080   backup;
}

server {
    location / {
        proxy_pass http://backend;
    }
}

相关说明

  1. upstream模块应该放在nginx.conf的http标签中
  2. upstream模块默认算法是wrr权重轮询,还有其他的算法例如rr,ip_hash,fair(根据后端响应时间短的优先分配,默认不支持,需要下载upstream_fair模块),url_hash(按照访问的url的hash结果进行分配请求,默认不支持,需要nginx的hash软件包,一般用于CDN公司),least_conn(最少连接数)和一致性HASH等
  3. upstream部分参数说明
参数 描述
server 192.168.0.202:80 RS配置,可以是IP或域名,端口默认为80,可以通过域名和 DNS做负载均衡
weight 权重,默认值为1
max_fails=2 最大失败尝试次数,默认为1,0代表禁止
backup 热备配置,用于RS节点
fail_timeout=20s 失败超时时间,默认为10s
down 服务器不可用

max_fails和fail_timeout需要根据集群的规模以及业务需求进行调整,对应着用户的体验。

location模块

nginx核心模块location 基于一个请求的uri进行配置,基于域名后面的uri进行处理

相关参数

Syntax: location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
Default:    —
Context:    server, location
=精确匹配,如果找到匹配=的内容,立刻停止搜索并立刻处理请求(优先级最高)
~区分大小写
^~只匹配字符串,不匹配正则表达式
~*不区分大小写
@指定一个命名的location,一般用于内部重定向请求

官方范例

Let’s illustrate the above by an example:
location = / {
    [ configuration A ]
}

location / {
    [ configuration B ]
}

location /documents/ {
    [ configuration C ]
}

location ^~ /images/ {
    [ configuration D ]
}

location ~* \.(gif|jpg|jpeg)$ {
    [ configuration E ]
}

The “/” request will match configuration A, the “/index.html” request will match configuration B, the “/documents/document.html” request will match configuration C, the “/images/1.gif” request will match configuration D, and the “/documents/1.jpg” request will match configuration E.

翻译一下就是如果直接请求'/'会匹配规则A,而请求'/index.html'会匹配规则B,而请求'/documents/document.html'会匹配规则C,而请求'/images/1.gif'有D和E两个规则符合,但是优于优先级,匹配规则D,而请求'/documents/1.jpg'有C和E两个规则符合,但是优于优先级,匹配规则E。

http-proxy模块

http-proxy模块官方文档

相关参数

参数 说明
proxy_set_header 设置由后端的服务器获取用户的主机名和真实IP,以及代理者的真实IP,这样就能让后端real server 获取
client_body_buffer_size 用于客户缓冲区大小,可以理解为先保存到本地,再传给用户
proxy_connect_timeout 表示与后端服务器连接的超时时间
proxy_send_timeout 表示与后端服务器数据回传的超时时间
proxy_read_timeout 表示与后端服务器数据回传的超时时间
proxy_buffer_size 设置缓冲区大小
proxy_buffers 设置缓冲区数量与大小
proxy_busy_buffers_size 设置系统繁忙时可使用的缓冲区的proxy_buffers,推荐为proxy_buffers*2
proxy_temp_file_write_size 指定proxy缓存的临时文件大小

实现反向代理主要参数

参数 说明
proxy_pass http://why_real_servers 用于指定反向代理的资源池
proxy_set_header HOST $host 如果后端web服务器需要用该header来区分反向代理
X-Forwarded-For $remote_addr 如果后端web服务器上的程序需要获取用户名IP从header获取

上边的我们配置的时候,我指定的是www.why.com为server_name,但是当我在我的本机上配置DNS,指定blog.why.com用192.168.0.204解析,我还是可以访问到202和203两台服务器的返回页面,这样如果后端是多个虚拟主机就没有办法正常解析。

反向代理

准备配置

参考<服务>Keepalived+Ngixn

其他配置

nginx web服务配置

    server {
        listen       80;
        server_name  www.why.com;
        #access_log  logs/host.access.log  main;

        location / {
            root   html/www;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
    server {
        listen       80;
        server_name  blog.why.com;
        access_log  logs/blog.access.log  main;

        location / {
            root   html/blog;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

[root@why-3 html]# cat blog/index.html 
blog 203
[root@why-3 html]# cat www/index.html 
www 203

不配置反向代理


[root@why ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.0.204 blog.why.com
[root@why ~]# curl  blog.why.com
www 202
[root@why ~]# curl  blog.why.com
www 203
[root@why ~]# curl  blog.why.com
www 203

配置反向代理

upstream why_real_servers {
        server 192.168.0.202    weight=5;
        server 192.168.0.203    weight=10;
}
server {
        listen  80;
        server_name www.why.com;
        location / {
        proxy_pass http://why_real_servers;
        proxy_set_header HOST $host;
                }
}
[root@why-1 conf]# ../sbin/nginx -s reload

配置proxy_set_header HOST $host让后端web服务获取到请求的url

检验

[root@why ~]# curl  blog.why.com
blog 203
[root@why ~]# curl  blog.why.com
blog 202
[root@why ~]# curl  blog.why.com
blog 203
[root@why ~]# curl  blog.why.com
blog 203

可以看到这样就指向了blog的虚拟主机,并且仍然后权重负载均衡。

后端获取IP用户

我们可以先看一下我们在负载均衡后的日志

[root@why-2 html]# cat ../logs/blog.access.log 
192.168.0.201 - - [26/Nov/2016:08:31:40 +0800] "GET / HTTP/1.0" 200 9 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.3.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2" "-"
192.168.0.201 - - [26/Nov/2016:08:31:41 +0800] "GET / HTTP/1.0" 200 9 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.3.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2" "-"

访问的IP指向的负载均衡nginx服务器的IP,这样就没办法统计日志了。

负载均衡nginx配置

upstream why_real_servers {
        server 192.168.0.202    weight=5;
        server 192.168.0.203    weight=10;
}
server {
        listen  80;
        server_name www.why.com;
        location / {
        proxy_pass http://why_real_servers;
        proxy_set_header HOST $host;
        proxy_set_header X-Forwarded-For $remote_addr;
                }
}

检查日志

[root@why-2 html]# cat ../logs/blog.access.log 
192.168.0.201 - - [26/Nov/2016:08:31:40 +0800] "GET / HTTP/1.0" 200 9 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.3.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2" "-"
192.168.0.201 - - [26/Nov/2016:08:31:41 +0800] "GET / HTTP/1.0" 200 9 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.3.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2" "-"
192.168.0.201 - - [26/Nov/2016:08:33:53 +0800] "GET / HTTP/1.0" 200 9 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.3.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2" "192.168.0.130"
192.168.0.201 - - [26/Nov/2016:08:34:34 +0800] "GET / HTTP/1.0" 200 9 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.3.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2" "192.168.0.130"

可以看到我们访问主机的IP 192.168.0.130 出现在最后了,而不是第一列,这个是根据默认的配置文件中配置的,可以进行调整

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';

Apache配置

需要通过修改LogFormat来实现

原格式:LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
修改为:LogFormat "\"%{X-Forwarded-For}i\" %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

然后使用combined规则即可

其他常用配置参数

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_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;

动静分离

通过不同的目录模拟访问的资源

负载均衡nginx配置

upstream why_real_servers {
        server 192.168.0.202    weight=5;
        server 192.168.0.203    weight=10;
}
upstream why_real_static_servers {
        server 192.168.0.202    weight=5;
}
upstream why_real_dynamic_servers {
        server 192.168.0.203    weight=5;
}
server {
        listen  80;
        server_name www.why.com;
        location / {
        proxy_pass http://why_real_servers;
                }
        location /static/ {
        proxy_pass http://why_real_static_servers;
                }                
        location /dynamic/ {
        proxy_pass http://why_real_dynamic_servers;
                }                
}

如果请求一个默认的规则,例如/static/1.jpg

会通过默认规则访问该地址,请求的资源不存在,就404,如果服务关闭为502

当然会有主机因为服务问题导致的502问题,这是超过一定次数我们就应该在前端剔除这个节点,就可以配置proxy_next_upstream error timeout invalid_header http_500 http_501 http_502 http_503

根据nginx尝试连接后端主机失败的次数Max_fails,当Nginx接收后端服务器返回的配置状态码,将这个请求转发到正常的后端服务器。

根据访问浏览器转发

负载均衡nginx配置

根据请求的user_agent进行转发
server {
        listen  80;
        server_name www.why.com;
        location / {
        if ($http_user_agent ~* "android"){
        proxy_pass http://why_android_servers;
        }
        if ($http_user_agent ~* "iphone"){
        proxy_pass http://why_iphone_servers;
        }     
        proxy_pass http://why_pc_servers;
                }
}

以前,访问www.qq.com,会显示一个3g.qq.com,这就是在rs上做301跳转实现的。

web服务优化

写入/etc/sysctl.conf,然后sysctl -p生效

优化配置参数

net.ipv4.tcp_fin_timeout = 2
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_keepalive_time = 600
net.ipv4.ip_local_port_range = 4000 65000
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_max_tw_buckets = 30000
net.ipv4.route.gc_timeout = 100
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_synack_retries = 1
net.core.somaxconn = 16384
net.core.netdev_backlog = 16384
net.ipv4.tcp_max_orphans = 16384
#以下参数是对防火墙生效的,防火墙不开会提示,可以忽略
对于CentOS5.8版本
net.ipv4.ip_conntrack_max = 25000000
net.ipv4.netfilter.ip_conntrack_max=25000000
net.ipv4.netfilter.ip_conntrack_tcp_timeout_established = 180
net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait = 120
net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait = 60
net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait = 120
对于CentOS6.5版本
net.nf_conntrack_max = 25000000
net.netfilter.nf_conntrack_max=25000000
net.netfilter.nf_conntrack_tcp_timeout_established = 180
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120

参数详解

  • net.ipv4.tcp_fin_timeout = 2 表示如果套接字由本端要求关闭,这个参数决定它保持在FIN-WAIT-2状态的时间,默认为60s,该参数对应的系统路径/proc/sys/net/ipv4/tcp_fin_timeout
  • net.ipv4.tcp_tw_reuse = 1 表示开启重用,允许将TIME-WAIT sockets重新用于新的TCP连接,默认值为0,表示关闭,该参数对应的系统路径/proc/sys/net/ipv4/tcp_tw_reuse
  • net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认值为0,表示关闭,该参数对应系统路径/proc/sys/net/ipv4/tcp_tw_recycle reuse和recycle两个参数是为了防止生产环境下web,squid等time_wait过多
  • net.ipv4.tcp_syncookies = 1 表示开启SYN cookies功能,当出现SYN等待队列溢出,启用cookies来处理,可以防范少量的SYN攻击,默认值为1,表示开启,该参数对应系统路径/proc/sys/net/ipv4/tcp_syncookies
  • net.ipv4.tcp_keepalive_time = 600 表示当keepalived启用时,TCP发送keepalived消息的频度,省却是7200s,即2小时,该参数对应系统路径/proc/sys/net/ipv4/tcp_keepalive_time
  • net.ipv4.ip_local_port_range = 4000 65000 选项用于设定允许系统打开的端口范围,即用于对外连接的端口范围,默认为32768 61000,该参数对应系统路径/proc/sys/net/ipv4/ip_local_port_range
  • net.ipv4.tcp_max_syn_backlog = 16384 表示SYN队列的长度,默认为1024,调大可以容纳更多等待连接的网络连接数,该参数对应系统路径/proc/sys/net/ipv4/tcp_max_syn_backlog
  • net.ipv4.tcp_max_tw_buckets = 30000 表示系统同时保持TIME—WAIT套接字的最大数量,如果超过这个将立刻被清楚并打印警告,默认为180000,对于web服务可以调低为5000~30000,例如lvs或者squid可以调的大于30000,该参数对应系统路径/proc/sys/net/ipv4/tcp_max_tw_buckets 这些参数可以很好的减少TIME-WAIT套接字数量,但是对于squid效果不佳,但也可以避免被套接字拖死
  • net.ipv4.tcp_syn_retries = 1 表示内核放弃连接前发送SYN包的数量,默认为5,该参数对应系统路径/proc/sys/net/ipv4/tcp_syn_retries
  • net.ipv4.tcp_synack_retries = 1 表示内核放弃连接前发送的SYN+ACK包的数量,默认为5,该参数对应系统路径/proc/sys/net/ipv4/tcp_synack_retries
  • net.ipv4.tcp_max_orphans = 16384 表示系统所能处理不属于任何进程的TCP sockets最大数量,如果超过这个数字,那么不属于任何进程的连接会被立刻reset,并同时警告,可以抵御简单的Dos攻击,默认值为8192,该参数对应系统路径/proc/sys/net/ipv4/tcp_max_orphans
  • net.core.somaxconn = 16384 表示系统同时发起的TCP连接数,在高并发请求中,默认值会导致连接超时或者重传,默认值为128,该参数对应系统路径/proc/sys/net/core/somaxconn
  • net.core.netdev_backlog = 16384 表示每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包最大数目,默认为1000,该参数对应系统路径/proc/sys/net/core/netdev_backlog