Linux运维学习笔记之三十:Nginx反向代理

第四十一章 Nginx反向代理

一、Nginx反向代理upstream模块

1、概念

Nginx反向代理(又称负载均衡)功能,依赖于ngx_http_upstream_module模块,支持的代理方式有proxy_pass(一般用于反向代理)、fastcgi_pass(一般用于动态程序交互)、memcached_pass(一般用于NOSQL缓存代理)。

反向代理:代理服务器接收外部连接请求,然后将请求转发给内部网络上的服务器,将从服务器得到结果返回给外部请求客户端。

正向代理:客户端向代理发送一个请求并指定目标(原始服务器),代理向原始服务器较交请求,并将获取的内容返回给客户端

2、语法示例
(1)示例1

upstream www_real_servers {

server 192.168.1.218:80 weight=5;

server 192.168.1.228:80 weight=5;

}

(2)示例2

upstream www_real_servers {

server 192.168.1.218:80;

server 192.168.1.228:80 weight=1 max_fails=1 fail_timeout=10s;

#the server config above is same

server 192.168.1.238:80 weight=1 max_fails=2 fail_timeout=20sbackup;

server 192.168.1.248:80 weight=1 max_fails=2 fail_timeout=20sbackup;

}

(3)示例解释

upstream www_real_servers {

#server固定的,后面接域名或IP。如不加端口,默认为80。weight表示权重,值越大,被分配几率越高。

server 192.168.1.218:80;

#指定socket文件

server unix:/tmp/backend3.socket;

#域名加端口。如用域名,需内网有DNS或负载均衡器的hosts文件中有域名解析

server aaa.abc.com:8080;

#备份服务器,等上面的服务器都不能访问时会启动。实际上就是高可用

server 192.168.1.238:8090 backup;

}

3、upstream模块相关说明
(1)upstream模块应放于nginx.conf配置的http{}标签内。

cat /application/nginx/nginx.conf

worker_processes  1;

events {

    worker_connections  1024;

}

http {

    include       mime.types;

    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    upstream backend {

        server 192.168.58.148:80 max_fails=3fail_timeout=30s;

        server 192.168.58.238:80 max_fails=3fail_timeout=30s;

    }

    server {

        listen       80;

        server_name  www.lb.org;

        index  index.html index.htm;

        location / {

           proxy_pass http://backend;

        }

        error_page   500 502 503 504  /50x.html;

        location = /50x.html {

            root   html;

        }

    }

}

(2)upstream模块默认算法是wrr(权重轮询weightedround-robin)

Nginx的upstream支持5种分配方式,下面将会详细介绍,其中,前三种为Nginx原生支持的分配方式,后两种为第三方支持的分配方式:

a、轮询(round-robin)

轮询是upstream的默认分配方式,即每个请求按照时间顺序轮流分配到不同的后端服务器,如果某个后端服务器down掉后,能自动剔除。

       upstream backend {

           server 192.168.1.101:8888;

           server 192.168.1.102:8888;

           server 192.168.1.103:8888;

       }

b、weight(weighted round-robin)

轮询的加强版,即可以指定轮询比率,weight和访问几率成正比,主要应用于后端服务器异质的场景下。

       upstream backend {

           server 192.168.1.101 weight=1;

           server 192.168.1.102 weight=2;

           server 192.168.1.103 weight=3;

       }

c、ip_hash       

每个请求按照访问ip(即Nginx的前置服务器或者客户端IP)的hash结果分配,这样每个访客会固定访问一个后端服务器,可以解决session一致问题。此时,负载均衡调度中不能使用weight和backup。

       upstream backend {

           ip_hash;

           server 192.168.1.101:7777;

           server 192.168.1.102:8888;

           server 192.168.1.103:9999;

       }

d、fair (第三方,NO)

fair顾名思义,公平地按照后端服务器的响应时间(rt)来分配请求,响应时间短即rt小的后端服务器优先分配请求。Nginx本身不支持fair,必须下载Nginx的upstream_fair模块。

       upstream backend {

           server 192.168.1.101;

           server 192.168.1.102;

           server 192.168.1.103;

           fair;

       }

e、url_hash(第三方,NO)

与ip_hash类似,但是按照访问url的hash结果来分配请求,使得每个url定向到同一个后端服务器,主要应用于后端服务器为缓存时的场景下,提高缓存命中率。其中,hash_method为使用的hash算法,需要注意的是:此时,server语句中不能加weight等参数。

       upstream backend {

           server 192.168.1.101;

           server 192.168.1.102;

           server 192.168.1.103;

           hash $request_uri;

           hash_method crc32;

       }

f、least_conn(最少连接数)

       upstream backend {

           server 192.168.1.101;

           server 192.168.1.102;

           server 192.168.1.103;

           least_conn;

       }

g、consistent_hash(一致性hash)

目前是缓存服务器的负载均衡的最好算法,可以保证在节点宕机后,其它服务器的缓存更改的最少,用户体验更好。

       upstream backend {

           server 192.168.1.101;

           server 192.168.1.102;

           server 192.168.1.103;

           consistent_hash $request_uri;

       }

 

(3)upstream模块部分参数说明

server

负载均衡后面的RS配置,接域名或IP。如不加端口,默认为80。如用域名,需内网有DNS或负载均衡器的hosts文件中有域名解析

weight

权重,默认是1。值越大,被分配几率越高

max_fails

最大尝试失败的次数,默认1,0表示禁止失败尝试。应用场景:2-3。如京东1次,蓝汛10次,根据业务需求配置。该参数可以配合proxy_next_upstream、fastcgi_next_upstream、memcached_next_upstream这3个参数来使用,当nginx接收到后端服务器返回这3个参数定义的状态码时,不会直接返回502给用户,而是再请求下一个服务器。

fail_timeout

失败超时时间,默认10秒。京东3秒,蓝汛3秒。常规业务:2-3秒就行。该参数实际上是在到max_fails定义的失败次数后,等待fail_timeout秒后,再次进行检查。如max_fails=5,fail_timeout=20s,则在检测5次失败后,会在20秒后再次进行检查1次,如还失败,则再等20秒再次进行检查1次,依次类推每隔fail_timeout秒检查一次,直到重启nginx。

backup

热备配置(RS节点的高可用)。当前面激活的服务器都不能访问时会启动

down

标志服务器永远不可用,一般是配合ip_hash使用

(4)特别说明

对于Nginx代理cache服务时,可能需要使用hash算法,此时,如果宕机时,可以通过设置down参数确保客户端用户按照当前hash算法访问。

二、Nginx的location指令详解

1、作用

Nginx中的location指令是NginxHttpCoreModule中的重要指令,简单、常用。是用于对url进行匹配,location指令根据URI来应用不同的配置,允许根据不同的URI来应用不同的URL配置。URI可以是字符串,也可以是正则表达式,如果是正则表达式,则必须指定前缀。

如:http://192.168.6.237/template/detail.html中/template/detail.html就是URI。

2、语法
(1)语法格式

location [ = | ~ | ~* | @ | ^~] uri {

   ...

}

(2)语法说明

[ = ]:精确匹配,如果找到匹配=号的内容,立即停止搜索,并立即处理请求(优先级最高)

[ ~ ] :区分大小写

[ ~* ] :不区分大小写

[ ^~ ] :只匹配字符串,不匹配正则表达式

[ @ ] :指定一个命名的location,一般只用于内部重定向请求。如location @name {。。。}

(3)匹配顺序

location的匹配是有顺序的,不是按书写顺序进行匹配。首先,对字符串进行匹配查询,最确切的匹配将被使用。然后,正则表达式的匹配查询开始,匹配第一个结果后会停止搜索,如果没有正则表达式,将使用字符串的搜索结果。如果字符串和正则表达示都匹配,则正则表达式的优先级较高。

3、示例1:匹配顺序
(1)示例

location = / {

[ configurationA]

}

 

location / {

[ configurationB]

}

 

location /documents/ {

[ configurationC]

}

 

location ^~ /images/ {

[ configurationD]

}

 

location ~* \.(gif|jpg|jpeg)$ {

[ configurationE]

}

(2)匹配结果

http://www.abc.org/:匹配A

http://www.abc.org/index.html:匹配B

http://www.abc.org/documents/document.html:匹配C

http://www.abc.org/images/1.gif:匹配D(匹配D和E,但D优先级高,所以匹配D)

http://www.abc.org/documents/1.jpg:匹配E(匹配C和E,但E优先级高,所以匹配E)

(3)结论

优先级:A > D > E > C > B

4、示例2:匹配顺序
(1)示例

cat /application/nginx/conf/nginx.conf

worker_processes  2;

events {

    worker_connections  1024;

}

http {

    include       mime.types;

    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    server {

        listen       192.168.1.148:80;

        server_name  www.abc.org;

            root  html/www;

            index  index.html index.htm;

        location ~ .*\.(php|php5)?$ {

            fastcgi_pass   127.0.0.1:9000;

            fastcgi_index  index.php;

            include        fastcgi.conf;

        }

    }

 

    #include extra/wiki.conf;

    include extra/order.conf;

}

cat /application/nginx/conf/extra/order.conf

server {

        listen       192.168.1.148:8000;

        server_name  www.wiki.org;

        #NO.A 

        location / {

            return 500;

        }

        #NO.B  D有冲突,先注释掉

        #location /test/ {

        #   return 404;

        #}

        #NO.C  

        location ~* \.jpg$ {

            return 403;

        }

        #NO.D 

        location ^~ /test/ {

            return 402;

        }

        #NO.E 

        location /test/a.jpg {

            return 401;

        }

        #NO.F 

        location = /test/a.jpg {

            return 400;

        }

}

#检查语法

/application/nginx/sbin/nginx -t   

nginx: theconfiguration file /application/nginx1.6.2/conf/nginx.conf syntax is ok

nginx:configuration file /application/nginx1.6.2/conf/nginx.conf test is successful

#重新加载nginx

/application/nginx/sbin/nginx -s reload

(2)匹配结果

a、第1步

curl -o /dev/null -s -w "%{http_code}\n" 192.168.1.148:8000/test/a.jpg

400  #<-- 匹配F

b、第2步

注释NO.F 项

#重新加载nginx

/application/nginx/sbin/nginx -s reload

curl -o /dev/null -s -w "%{http_code}\n" 192.168.1.148:8000/test/a.jpg

403  #<-- 匹配C

c、第3步

注释NO.C 项

#重新加载nginx

/application/nginx/sbin/nginx -s reload

curl -o /dev/null -s -w "%{http_code}\n" 192.168.1.148:8000/test/a.jpg

401  #<-- 匹配E

d、第4步

注释NO.E 项

#重新加载nginx

/application/nginx/sbin/nginx -s reload

curl -o /dev/null -s -w "%{http_code}\n" 192.168.1.148:8000/test/a.jpg

402  #<-- 匹配D

e、第5步

注释NO.D 项

打开NO.B项

#重新加载nginx

/application/nginx/sbin/nginx -s reload

curl -o /dev/null -s -w "%{http_code}\n" 192.168.1.148:8000/test/a.jpg

404  #<-- 匹配B

f、第6步

注释NO.B项

#重新加载nginx

/application/nginx/sbin/nginx -s reload

curl -o /dev/null -s -w "%{http_code}\n" 192.168.1.148:8000/test/a.jpg

500  #<-- 匹配A

(3)结论

优先级:NO.F > NO.C  > NO.E > NO.D 或 NO.B  > NO.A

三、Nginx的http_proxy_module模块详解

1、Proxy_pass指令
(1)作用

Proxy_pass指令属于ngx_http_proxy_module模块,作用是将请求转发到另一台服务器。

(2)语法

location /name/ {

proxy_pass http://127.0.0.1/remote/;

}

location /othername/ {

rewrite/name/([^/]+) /users?name=$1 break;

proxy_passhttp://127.0.0.1/;

}

2、httpproxy模块参数

Nginx的代理功能是通巡http proxy模块来实现,nginx默认安装,因此,可以直接使用http proxy模块。主要参数如下:

参数

作用

proxy_set_header

设置由后端的服务获取用户主机名或真实IP,以及代理者的真实IP

client_body_buffer_size

用于指定客户端请求主体缓冲区大小,可以理解为先保存到本地再传给用户

proxy_connect_timeout

表示与后端服务器连接的超时时间,即发起握手等候响应的超时时间

proxy_send_timeout

表示后端服务器的数据回传时间,即在规定时间内后端服务器必须传完所有数据,否则Nginx将断开这个连接

proxy_read_timeout

表示Nginx从后端服务器获取信息的时间,即在建立连接成功后,Nginx等待后端服务器的响应时间,也就是在后端服务器上的排队中的等候处理的时间

proxy_buffer_size

设置缓冲区大小,默认为指令proxy_buffers参数设置的大小

proxy_buffers

设置缓冲区的数量和大小

proxy_busy_buffers_size

设置系统很忙时可以使用的proxy_buffers大小,官方推荐为proxy_buffers的2倍

proxy_temp_file_write_size

设置proxy缓存临时文件的大小

3、参数用法
(1)主要参数用法说明

参数

作用

proxy_set_header Host $host

当后端Web服务器上也配置有多个虚拟主机时,需要用该Header来区分反向代理哪个虚拟主机

proxy_set_header X-Forwarded-For $remote_addr

如查后端Web服务器上的程序需获取用户真实IP(默认是负载均衡服务器的IP),从该Header头获取. $remote_addr表示用户IP,需要修改后端Web服务器获取IP的方式,指定从X-Forwarded-For获取

(2)参数用法

可以把参数的配置放在一个配置文件中,供其它配置文件include引用。如

cat /application/nginx/conf/extra/myproxy.conf

proxy_set_header Host $host;

proxy_set_header X-Forwarded-For $remote_addr;

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;

cat cat /application/nginx/conf/extra/upstream.conf

upstream backend {

server 192.168.1.101 weight=1;

server 192.168.1.102 weight=2;

server 192.168.1.103 weight=3;

}

server {

listen       80;

server_name  www.lb.org;

index  index.html index.htm;

location / {

proxy_pass http://backend;

include extra/myproxy.conf;

}

4、示例
(1)修改负载均衡服务器上的nginx配置文件

cat /application/nginx/conf/extra/upstream.conf

upstream backend {

server 192.168.1.101 weight=1;

server 192.168.1.102 weight=2;

server 192.168.1.103 weight=3;

}

server {

listen       80;

server_name  www.lb.org;

index  index.html index.htm;

location / {

proxy_pass http://backend;

proxy_set_headerHost $host;

proxy_set_headerX-Forwarded-For $remote_addr;

}

(2)修改后端Web服务器上的获取IP的方法

a、Apache服务器

根据扩展配置文件httpd-vhosts中指定的日志类型,在主配置文件httpd.conf中修改日志格式。如:

httpd-vhosts中指定的日志类型:combined

    ServerAdmin [email protected]

    DocumentRoot"/var/html/blog"

    ServerName 192.168.158.99

    ErrorLog"logs/blog-error-log"

    CustomLog"logs/blog-access-log" combined

httpd.conf中修改日志格式

    LogFormat "\"%{X-Forwarded-For}i\"%t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""combined

    LogFormat "%h %l %u%t \"%r\" %>s %b" common

   

      # You need to enablemod_logio.c to use %I and %O

      LogFormat "%h %l %u%t \"%r\" %>s %b \"%{Referer}i\"\"%{User-Agent}i\" %I %O" combinedio

   

    CustomLog"logs/access_log" combined

b、nginx服务器(一般不需要改,默认就有)

在后端Web服务器的配置文件nginx.conf中的日志功能块中

error_log logs/error.log error;    #添加错误日志功能

worker_processes  2;

events {

    worker_connections  1024;

}

http {

    include       mime.types;

    default_type  application/octet-stream;

    sendfile        on;

keepalive_timeout  65;

#定义访问日志格式

    log_format  main '$remote_addr - $remote_user [$time_local] "$request" '

                      '$status$body_bytes_sent "$http_referer" '

                     '"$http_user_agent" "$http_x_forwarded_for"';

 

四、根据URI及location实现动静分离实战

1、演示环境

Host

OS

role

192.168.1.217

CentOS6.5_32

负载均衡服务节点nginx

192.168.1.218

CentOS6.5_32

RS1(静态服务节点nginx)

192.168.1.219

CentOS6.5_32

RS2(动态服务节点nginx)

2、部署模拟环境
(1)静态服务节点192.168.1.218

cd /application/nginx/html/blog

mkdir static

cd static

echo "static 218" > index.html

vi nginx.conf

...

#include extra/www.conf;

#include extra/bbs.conf;

include extra/blog.conf;

...

(2)动态服务节点192.168.1.219

cd /application/nginx/html/blog

mkdir dynamic

cd dynamic

echo " dynamic 219" > index.html

vi nginx.conf

...

#include extra/www.conf;

#include extra/bbs.conf;

include extra/blog.conf;

...

(3)测试Web服务器

curl http://192.168.1.218/static/

static 218

curl http://192.168.1.218/

static web

curl http://192.168.1.219/dynamic/

dynamic 219

curl http://192.168.1.219/

dynamic web

 

(4)配置负载均衡服务器192.168.1.217

vi /application/nginx/conf/nginx.conf

worker_processes  1;

events {

    worker_connections  1024;

}

http {

    include      mime.types;

    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    upstream static_pools {

        server 192.168.1.218:80 weight=5;

    }

    upstream dynamic_pools {

        server 192.168.1.219:80 weight=5;

    }

 

    server {

        listen       80;

        server_name  www.lb.org;

        index  index.html index.htm;

        location / {

           proxy_pass http://dynamic_pools;

           include extra/proxy.conf

        }

        location /static/ {

           proxy_pass http://static_pools;

           include extra/proxy.conf

        }

        location /dynamic/{

           proxy_pass http://dynamic_pools;

           include extra/proxy.conf

        }

    }

}

(5)测试动静分离

curl http://192.168.1.217/static/

static 218

curl http://192.168.1.217/dynamic/

dynamic 219

curl http://192.168.1.217/

dynamic web

(6)根据手机操作系统分离

    server {

        listen       80;

        server_name  www.lb.org;

        index  index.html index.htm;

        location / {

           if($http_user_agent ~* "android") {

                proxy_pass http://dynamic_pools;

           }

if($http_user_agent ~* "iphone") {

                proxy_pass http://static_pools;

           }

proxy_pass http://static_pools;

           include extra/proxy.conf

        }

    }

你可能感兴趣的:(Linux)