nginx的负载均衡

摘要:nginx利用反向代理来做负载均衡,翻翻官方文档用一台服务器实现了最简单的nginx负载均衡配置实例。

nginx负载均衡方法

nginx官方给出文档支持一下3种方式的负载均衡机制:

1、循环 - 对应用程序服务器的请求以循环方式分发。

2、最少连接 - 下一个请求被分配给活动连接数最少的服务器。

3、ip_hash - 哈希函数用于确定应为下一个请求选择哪个服务器(基于客户端的IP地址)。

循环方式分发

http {
    upstream myapp1 {
        server srv1.example.com;
        server srv2.example.com;
        server srv3.example.com;
    }

    server {
        listen 80;

        location / {
            proxy_pass http://myapp1;
        }
    }
}

上面这段配置中,在 srv1-srv3 上运行了3个相同应用程序的实例。如果未特别配置负载平衡方法,则默认为循环。所有请求都代理到服务器组 myapp1,nginx 应用 http 负载平衡来分发请求。这样每次访问就会以轮寻的方式 srv1、srv2、srv3 这三台服务器,每个服务器都循环分发,做到雨露均沾的效果。

最少连接分发

upstream myapp1 {
	least_conn;
	server srv1.example.com;
	server srv2.example.com;
	server srv3.example.com;
}

第一个循环(轮寻)方式负载机制,就是将请求平均分给每台服务器,使他们的负载大致基本相同(但是这有个前提,就是客户端的请求所占用的时间都差不多),但是客户端的请求谁也无法预料,比如这时候有个客户端要请求服务器上某个程序或者文件,但是这个程序后端处理起来需要耗费时间比较长,但是这时候再次有请求进来,循环分配方式才不会管你这台服务器是否负载过高,还是会将请求分发给你,这时候这台服务器负载会更高,也会影响用户体验度。

在这种场景下,我们就可以使用 least_conn 负载机制,它会将请求分发给不太繁忙的服务器,然后达到更好的负载均衡效果,这就是 least_conn 负载机制。

ip_hash负载均衡方式

upstream myapp1 {
    ip_hash;
    server srv1.example.com;
    server srv2.example.com;
    server srv3.example.com;
}

这里注意的就是:如果通过循环的或者最少连接分发的方式来实行负载均衡的分发机制时,就会造成客户端的请求分发每次分发到不同的服务器,无法保证客户端每次指向同一台服务器。这样会造成一个最简单的影响,就是无法保证用户 session 同步,比如用户登录将他分发到 a 服务器,用户第二次访问的时候分发到 b 服务器,这时候就会出现用户未登录的情况。

为了避免这种情况,我们可以使用 ip_hash 负载平衡机制,nginx 将客户端的 ip 地址将用作散列密钥,以确定应为客户端的请求选择服务器组中的哪个服务器。此方法可确保来自同一客户端的请求始终定向到同一服务器,但此服务器不可用时除外,如果根据 ip_hash 分配的服务器宕机了,会自动分配到其它的服务器。这样用户每次都会访问一台服务器,就可以解决这种问题了。

当然,具体使用哪种负载均衡机制要根据每台服务器配置和用户访问量来决定。没有必要为了解决 session 不同步就使用 ip_hash 来做负载均衡,负载均衡共享 session 的方式有很多种,比如数据库、memcache、redis 都可以。

加权重负载均衡方式

upstream myapp1 {
	server srv1.example.com weight=3;
	server srv2.example.com;
	server srv3.example.com;
}

通过使用 weight 来加权重就可以影响负载均衡的算法了,比如我们有 a、b、c 3台服务器来负载客户端的访问,我们使用的是循环分发方式,每台服务器都会分发一次,雨露均沾,但是这之后 b、c 服务器的配置可能会稍微差一点,我们想让 a 服务器多承担一点负载,b、c 呢,少来一点,这时候我们就在 a 服务器后面加上 weight=3(等号两边不要有空格)就像上面这段代码,这样意思是每五个请求会向 srv1 服务器分发3次,然后 srv2、srv3 各分发一次,这样就是能者多劳。

一台服务器的负载均衡配置小 demo

events {

}
http {
    #upstream 模块应放于 http 模块中,默认的分配方式是轮寻
	upstream myweb {
		server 98.142.138.117:8081 weight=3;#weight 分配权重,值越大负载的权重越大
		server 98.142.138.117:8082  down;#表示当前 server 不参与负载
		#以下表明如果此分发节点在10秒内出现2次不可用,那10秒内不会再分发到此节点,直到10秒后再次重新检测节点健康情况
		#如果将 max_fails=0 则停止检查节点健康情况 
		server 98.142.138.117:8083 max_fails=2 fail_timeout=10s;
	}

	server {
		listen 80;

	    location / {
	        #配置一个反向代理,这里的设置和上面的 upstream 相对应的,你也可以将这里设置成 http://www.baidu.com
	        #这样你访问你的ip浏览器出现的就是百度的内容了
	        #如果你将这里设置成和上面的 myweb 一样,那么所有的请求都代理到 upstream 服务器组 myweb
			proxy_pass http://myweb;
	    }
	}
	
	server {
		listen 8081;
		root /usr/local/nginx/html/web1;
	}
	
	server {
		listen 8082;
		root /usr/local/nginx/html/web2;
	}
}

为了方便看效果,我就用一台服务器搭建了下,正常来讲如果你没有多台服务器,你可以用虚拟机装一台环境,然后再克隆出两台就可以了,然后一台做负载均衡服务器分发服务,另外两台来接受分发来学习负载均衡。

上面的这段我已经配置好了,你只需要将这段配置替换掉你 nginx.conf 中的配置,然后 ip 换成你服务器的 ip 然后在 web1 和 web2 目录下新建两个不同的 index.html 文件就可以了,然后就可以访问查看效果了。

结束语:感谢您对本网站文章的浏览,欢迎您的分享和转载,但转载请说明文章出处。
Top