Nginx反向代理(又称负载均衡)功能,依赖于ngx_http_upstream_module模块,支持的代理方式有proxy_pass(一般用于反向代理)、fastcgi_pass(一般用于动态程序交互)、memcached_pass(一般用于NOSQL缓存代理)。
反向代理:代理服务器接收外部连接请求,然后将请求转发给内部网络上的服务器,将从服务器得到结果返回给外部请求客户端。
正向代理:客户端向代理发送一个请求并指定目标(原始服务器),代理向原始服务器较交请求,并将获取的内容返回给客户端
upstream www_real_servers {
server 192.168.1.218:80 weight=5;
server 192.168.1.228:80 weight=5;
}
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;
}
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;
}
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;
}
}
}
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;
}
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使用 |
对于Nginx代理cache服务时,可能需要使用hash算法,此时,如果宕机时,可以通过设置down参数确保客户端用户按照当前hash算法访问。
Nginx中的location指令是NginxHttpCoreModule中的重要指令,简单、常用。是用于对url进行匹配,location指令根据URI来应用不同的配置,允许根据不同的URI来应用不同的URL配置。URI可以是字符串,也可以是正则表达式,如果是正则表达式,则必须指定前缀。
如:http://192.168.6.237/template/detail.html中/template/detail.html就是URI。
location [ = | ~ | ~* | @ | ^~] uri {
...
}
[ = ]:精确匹配,如果找到匹配=号的内容,立即停止搜索,并立即处理请求(优先级最高)
[ ~ ] :区分大小写
[ ~* ] :不区分大小写
[ ^~ ] :只匹配字符串,不匹配正则表达式
[ @ ] :指定一个命名的location,一般只用于内部重定向请求。如location @name {。。。}
location的匹配是有顺序的,不是按书写顺序进行匹配。首先,对字符串进行匹配查询,最确切的匹配将被使用。然后,正则表达式的匹配查询开始,匹配第一个结果后会停止搜索,如果没有正则表达式,将使用字符串的搜索结果。如果字符串和正则表达示都匹配,则正则表达式的优先级较高。
location = / {
[ configurationA]
}
location / {
[ configurationB]
}
location /documents/ {
[ configurationC]
}
location ^~ /images/ {
[ configurationD]
}
location ~* \.(gif|jpg|jpeg)$ {
[ configurationE]
}
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)
优先级:A > D > E > C > B
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
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
优先级:NO.F > NO.C > NO.E > NO.D 或 NO.B > NO.A
Proxy_pass指令属于ngx_http_proxy_module模块,作用是将请求转发到另一台服务器。
location /name/ {
proxy_pass http://127.0.0.1/remote/;
}
location /othername/ {
rewrite/name/([^/]+) /users?name=$1 break;
proxy_passhttp://127.0.0.1/;
}
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缓存临时文件的大小 |
参数 |
作用 |
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获取 |
可以把参数的配置放在一个配置文件中,供其它配置文件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;
}
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;
}
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"';
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) |
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;
...
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;
...
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
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
}
}
}
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
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
}
}