nginx负载均衡核心模块(upstream和proxy模块)及常用参数介绍

前言

环境:centos nginx 1.18.0
以下所说的反向代理服务器和负载均衡服务器其实是一个意思,因为nginx做反向代理的时候本质上做到了负载均衡的效果。

upstream模块

nginx的负载均衡功能依赖于http_upstream_module模块,所支持的代理方式包括proxy_pass、fastcgi_pass、memcached_pass等。
http_upstream_module模块允许nginx定义一组或多组节点服务器组,使用时可以通过proxy_pass代理方式把网站请求发送到事先定义好的对应upstream组名上,具体的写法为:proxy_pass http://www.server_pools,其中www.server_pools就是一个upstream节点服务器组名。

upstream模块语法:

upstream 组名{
	server IP:port 参1,参2,....;
	server IP:port 参1,参2,....;
}

说明:upstream模块放在http里面,语法结构中upstream是关键字,接着定义一个组名,server也是关键字,后面是IP或者域名,再是参数。

upstream范例如下:

upstream www.server_pools{				#www.server_pools是集群组名
	server 10.0.0.1:80  weight=15;		#可以写IP或域名,指定端口,如果不指定端口就认80端口
	server 10.0.0.2:80  weight=15;		#weight表示权重,后面会讲
}
upstream www.server_pools{				#www.server_pools是集群组名
	server www.fujiseiko.com:80;		#域名,DNS或负载均衡服务器必须做解析
	server 10.0.0.2:80   backup;		#backup表示备用服务器,除非其它都挂了,否则不会请求不会到这台服务器
	server 10.0.0.3:80 max_fails=3,fail_timeout=15s;	#表示在15秒内尝试重连3次,3次都失败就认为服务器不可用,请求就不会转发到这台服务器
}

下面讲一下server标签的一些常用参数:

weight		表示权重,其书写规则为weight=1,默认就等于1,权重数值越大表示接受的请求比例就越大;
max_fails 	表示nginx在fail_timeout 参数设置的持续时间内尝试连接后端主机失败次数,则认为服务器在fail_timeout参数设置的持续时间内不可用 。其书写规则为max_fails=2;默认max_fails=1,零值将禁用对尝试的记帐。认为失败的尝试由 proxy_next_upstream, fastcgi_next_upstream, uwsgi_next_upstream, scgi_next_upstream, memcached_next_upstream和 grpc_next_upstream 指令定义。
fail_timeout	表示在指定次数的不成功尝试与服务器通信的时间范围内,应考虑服务器不可用,其书写规则为fail_timeout=15s,默认该参数为fail_timeout=10s;
down		表示将服务器标记为永久不可用;
backup		表示当前服务器节点是备用机,只有在其他的服务器都宕机以后,请求才会被转发到这个备用服务器上;

upstream模块的调度算法

我们知道,定义一个upstream模块的时候,定义了很多server主机,那么LB服务器是如何决定将请求调度给哪一个后端主机的呢?这就涉及到调度算法的问题。
调度算法可以分为静态调度算法和动态调度算法,所谓静态调度算法就是指负载均衡服务器根据自身设定的规则进行分配,不需要考虑后端节点服务的情况,如rr、wrr、ip_hash等调度算法,而动态调度就是指根据后端节点服务器的当前状态来决定是否分发请求,如least_conn、fair等调度算法。
下面介绍一下常用的调度算法:

1、rr轮询(Round Robin,默认调度算法,静态调度算法)
	每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除;
2、wrr轮询(weight Round Robin,权重轮询,静态调度算法)
	在轮询算法的基础上加上权重weight,权重轮询和访问成正比,权重值越大,转发的请求也就越多;
3、ip_hash(静态调度算法)
	每个请求按访问的IP的hash结果分配,当新的请求到达时,先将其客户端IP通过哈希算法希出一个值,在随后请求中客户端ip的哈希值只要相同,就会被分值至同一台服务器,该调度算法可以解决网页session共享问题,但有时会导致请求分配不均和无法保证相对的负载均衡;
	注意:当调度算法是ip_hash 时,后端服务器中负载均衡调度中的状态不能有weight和backup,即使有也不会生效。
4、fair(动态调度算法)
	按照后端服务器节点的响应时间来智能分配请求,响应时间短的优先分配,这中调度算法是更加智能的算法,这种算法可以依据页面大小和加载时间长短智能的进行负载均衡,nginx本身不支持fair,需要下载nginx的upstream_fair模块;
5、least_conn(动态调度算法)
	根据后端节点的连接数来决定分配情况,哪个后端节点连接数少就连接哪个;
6、url_hash
	与ip_hash调度算法类似,但url_hash是按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,这当后端服务器是缓存服务器时效果更显著;

upstream模块指定调度算法

直接在大括号内指定调度算法即可:

upstream 组名{
	ip_hash;					#指定调度算法,不指定的话默认rr轮询
	server IP:port ;
	server IP:port ;
}

http_proxy_module模块介绍

http_proxy_module模块可以将请求转发到另一台服务器,在实际的反向代理工作中,会通过location功能匹配指定的URL,然后把接收到的符合匹配的URL的请求通过proxy_pass指令抛给定义好的upstream服务器组池,下面是proxy_pass指令的一些使用案例;

 1、将匹配URL为ngme的请求抛给http://127.0.0.1/remote/
	 location /name/{
	 proxy_pass http://127.0.0.1/remote/;
	}
2、将匹配URL为some/path的请求抛给http://127.0.0.1/
	 location /some/path/{
	 proxy_pass http://127.0.0.1/;
	}
3、将匹配URL为name的请求应用指定的rewrite规则,然后抛给http://127.0.0.1/
	 location /some/path/{
	 	rewrite /name/([^/ ]+ ) /user?name=$1 break;
	 proxy_pass http://127.0.0.1/;
	}

nginx功能的代理功能是是通过http proxy模块来实现的。默认在安装Nginx是已经安装了http proxy模块,可以直接使用,http proxy模块参数如下:

proxy_set_header
设置http请求header项传给后端服务节点,例如:可实现让代理后端的服务节点获取访问客户端用户的真实IP地址,以及让后端服务器得知访问的哪一个server虚拟主机

client_body_buffer_size
用于指定客户端请求主体缓冲区大小,此处如果了解前面的http请求包的原理就好理解了

proxy_connect_timeout
表示反向代理与后端节点服务器连接的超时时间,即发起握手等候相应超时时间

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

proxy_read_timeout
设置Nginx从代理的 后端服务器获取信息的时间,表示连接建立成功后,Nginx等待后端服务器的相应时间,其实是Nginx已经进入后端的排队之中等候处理的时间

proxy_buffer_size
设置缓存区大小,默认该缓存区等于指令proxy_buffer设置的大小

proxy_buffer
设置缓存区的数量和大小,Nginx从代理的后端服务器获取的响应信息,会放置到缓存区

proxy_busy_buffer_size
用于设置系统很忙是可以使用的proxy_buffer大小,官方推荐大小为proxy_buffers*2

proxy_temp_file_write_size
指定proxy缓冲临时文件的大小

这里重点将一下proxy_set_header这个参数,为什么呢?因为这个参数功能很强大,我们先来假设后端节点有这样两台服务器web01,web02,
web01的主配置文件nginx.conf是带有两个或多个虚拟主机的,即这样写的:

vim nginx.conf
user  nginx;
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
   	server {
        listen       80;
        server_name  bbs.cnblogs.com;					#第1个虚拟主机bbs.cnblogs.com
        location / {
            root   html/cnblogs;
            index  index.html index.htm;
        }
    }
     server {
        listen       80;
        server_name  www.fujiseiko.com;					#第2个虚拟主机www.fujiseiko.com
        location / {
            root   html/fujiseiko;
            index  index.html index.htm;
        }
    }
}

web02的主配置文件nginx.conf也是类似这些写,再在各自的index文件里写点内容;

接下来开始配置LB负载均衡服务器(即nginx反向代理服务器),LB的nginx.conf配置如下:

vim nginx.conf
user  nginx;
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream server_pools{								#定义upstream 服务器池
		server 192.168.1.120:80 weight=1;				#这是web01	
		server 192.168.1.121:80 weight=1;				#这是web02	
	}
    server {
        listen       80;
        server_name  www.fujiseiko.com;					#虚拟主机www.fujiseiko.com
        location / {
           proxy_pass http://server_pools;				#这里只写了一句proxy_pass
        }
    }
    }

以上,配置完域名解析等工作,启动nginx没有问题的话,客户开始访问http://www.fujiseiko.com,得到了结果,但是这个结果是虚拟主机bbs.cnblogs.com的网页,看出问题了吗?我明明是想要访问www.fujiseiko.com网站的呀,按理来说负载均衡服务器应该请求到后端服务器nginx里配置的www.fujiseiko.com虚拟主机的呀,为什么现在出现的网站却是bbs.cnblogs.com的网页呢?

问题就在于是:客户访问http://www.fujiseiko.com网站时确实是带了www.fujiseiko.com主机头请求的负载均衡代理服务器,但是反向代理服务器在请求节点池中的服务器时,默认并没有在请求头中告诉后端节点服务器要找你的哪一台虚拟主机,所以后端节点服务器在发现并没有主机头信息的时候就默认把第一台虚拟主机发给了反向代理服务器,反向代理服务器就把信息返回给了前端页面。

如何解决呢?解决办法就是,当反向代理服务器向节点服务器发起请求的时候,携带主机头信息,非常明确的告知后端节点服务器要访问的是你的哪一台虚拟主机,配置非常简单,如下:

location / {
           proxy_pass http://server_pools;
           proxy_set_header Host $host;		#就是添加这一句,让反向代理服务器携带主机头信息明确访问的是节点服务器的哪一个虚拟主机
           
        }

我们再来看一个问题,当Windows访问反向代理服务器时,节点服务器web01的日志信息会是什么样子的,答案是web01服务器记录的IP是反向代理服务器的IP,并没有记录真实的客户端IP,如何解决呢?加参数proxy_set_header X-real-ip $remote_addrproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for,如下,在反向代理服务器的nginx.conf配置文件添加参数:

 location / {
           proxy_pass http://server_pools;
           proxy_set_header Host $host;		
           proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;	#用于传递真实客户端的IP地址
           #proxy_set_header X-real-ip $remote_addr;						#也可以加这个,两者能传递真实客户端的IP地址
           }

这样反向代理服务器在向后端节点服务器发起请求的主机头信息中就带有客户端的IP的字段信息了,但是这样还不够,后端节点服务器还需要设置日志格式添加$http_x_forwarded_for,下面以web01节点的日志格式为例:

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

就是这个$http_x_forwarded_for,设置完成后就会显示真实客户端Windows的IP地址,当然 $remote_addr 值还是反向代理服务器的IP,不需要可以删除这个$remote_addr变量。

总结

直接看配置吧

vim nginx.conf
user  nginx;
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream server_pools{								#定义upstream 服务器池
    	wrr;											#定义调度策略wrr为按权重轮询,不写材料默认rr轮询
		server 192.168.1.120:80 weight=2;				#这是web01	
		server 192.168.1.121:80 weight=1;				#这是web02	
	}
    server {
        listen       80;
        server_name  www.fujiseiko.com;					#虚拟主机www.fujiseiko.com
        location / {
           proxy_pass http://server_pools;				#这三个参数下面讲
           proxy_set_header Host $host;	
           proxy_set_header X-Forwarded-For $remote_addr;
        }
    }
    }

proxy_pass http://server_pools;					#请求转发到upstream定义的server_pools中去
proxy_set_header Host $host;						#反向代理服务器请求节点服务器时,在http请求头中加入host字段信息,用以指定访问的是节点服务器的哪一个虚拟主机,当节点服务器存在多个虚拟主机时,该参数非常重要;
proxy_set_header X-Forwarded-For $remote_addr;		#反向代理服务器请求节点服务器时,在http请求头中加入X-Forwarded-For字段信息,这样后端节点服务器的日志就能正常记录得客户端的ip地址信息了,而不是记录代理服务器的ip,这需要在节点服务器的日志添加$http_x_forwarded_for,为了简单化主配置文件,可以使用include proxy.conf的方式把配置参数添加进来。
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值