一、负载均衡
就是当数据量过大的时候,代理服务器充分当作一个调度者的身份,来将这些请求合理的分配到后端各个服务器上,保证服务器的性能能够充分发挥。在Nginx有常用的几种实现负载均衡的方式,下面就给大家介绍下。
二、Nginx路径匹配规则
在介绍负载均衡之前,先给大家介绍Nginx常用的几种路径匹配规则。
= | =/aaa/1.jpg | 路径严格匹配,路径必须一模一样才会匹配到 |
^~ | ^~/aaa | 只要是指定路径开头的路径都可以匹配 |
~ | ~.png$ | 区分大小写按正则匹配路径 |
~* | ~*.png$ | 不区分大小写按正则匹配路径 |
/ | / | 通用匹配,所有路径都可以匹配到 |
优先级:
- 首先匹配 =
- 其次匹配 ^~
- 其次是按文件中顺序的正则匹配
- 最后是交给 / 通用匹配
- 当有匹配成功时候,停止匹配,按当前匹配规则处理请求
总的规律是,精度越高优先级越高
案例:
upstream ccc{
server localhost:8081;
server localhost:8082;
server localhost:8083;
}
server {
listen 80;
server_name www.cccmall.com;
location /{
proxy_pass http://ccc;
}
}
listen 表示监听的端口号
server_name 表示访问的主机名
location 表示处理的请求地址,一个server中可以配置多个location
server 表示虚拟服务器,一个http中可以配置多个server
upstream 用于配置一组服务器地址供后续使用
三、轮询方式
轮询方式是Nginx默认处理负载方式,它的工作原理,就如其名称,根据请求顺序轮流的分配到后端服务器上,举个例子,假设后端有3台服务器,此时有5个连接发送过来,如果使用轮询,它是这样工作的,A->1,B->2,C->3,A->4,B->5。轮流处理请求。
实现:
upstream ccc{
server localhost:8081;
server localhost:8082;
server localhost:8083;
}
server {
listen 80;
server_name www.cccmall.com;
location /{
proxy_pass http://ccc;
}
}
- upstream,表明有几台服务器。
- 在location中,通过proxy_pass 引用upstream
如果不指定负载均衡方式,那么默认就是轮询的方式。
但是,这种方式有一点问题,大家有没有想过,假设有这样一个场景,A服务器处理了张三的登录请求,并将张三的信息保存在Session域中,重所周知,Session域中的内容是保存在服务器中的。此时,张三点击了一下购买商品,此时是B服务器处理的购买请求,B服务器中没有张三的个人信息,所以服务器要求张三去登录。但是,第二次登录的请求是又被A服务器处理了,A服务器中有张三的信息,显示您已经登录,请不要重复登录。然后,张三在点击购买,此时又被B服务器处理,张三又被要求去登录。此时,张三肯定会崩溃的。所以,轮询的方式也是有一点问题的。
三、hash方式
由于,不同服务器之间不能共享数据,所以Nginx提供了一种基于Hash的方式,用以提供负载均衡。
处理公式:abs(客户端ip.hash())%服务器数量
因为客户端的ip地址是唯一不变的,所以,通过hash算法计算出ip地址对应的哈希码值,通过哈希码值对服务器的数量进行一个求模运算。这样就可以保证每个客户端访问的服务器都是保持不变的,因为hash算法的散列特点,也可以近似的当作平均分配。
实现:
upstream czf{
ip_hash;
server localhost:8081;
server localhost:8082;
server localhost:8083;
}
server {
listen 80;
server_name www.cccmall.com;
location /{
proxy_pass http://czf;
}
}
通过ip_hash;就可以实现基于Hash的负载均衡的方式。
但是,正如hash算法的散列特点,因为它的不确定性,可能会造成某个A服务器处理请求的数量是100,B服务器处理请求的数量是50,C服务器处理请求的数量是0,如果,在来一条请求,那么按照我们所想的,最好是可以分配到C服务器上。所以,Nginx又为我们提供了另外一种方式,用来解决以上问题,这个方式就是基于最小连接数的负载均衡方式。
四、最小连接方式
基于最小连接的负载均衡方式,Nginx会将请求发送给当前处理请求数量最少的服务器上。可以分担各个服务器之间的压力。
实现:
upstream czf{
least_conn;
server localhost:8081;
server localhost:8082;
server localhost:8083;
}
server {
listen 80;
server_name www.cccmall.com;
location /{
proxy_pass http://czf;
}
}
通过least_conn;就可以实现基于最小连接数的负载均衡方式。
但是,大家有没有想过这样一个情况。在公司里,有三台服务器,A服务器采购于2000年,最高处理并发数100,B服务器采购于2010年。最高处理并发数500,C服务器采购于2018年,最高处理并发数1000。如果,此时A服务器处理请求数为99,B服务器处理请求数为300,C服务器请求数为500,如果是你,进行分配资源的话,我想更倾向于C服务器吧,C虽然处理了很多请求,但是任然没有到达它的处理瓶颈。但是,根据最小连接数的规则,这条请求应该是A服务器处理,但很有可能就是压死骆驼的最后一根稻草。所以,给大家在介绍一种处理规则,基于权重的负载均衡方式。
五、权重方式
基于权重的负载均衡方式,Nginx会根据服务器设置的权重,进行合理分配请求连接数。
实现:
upstream czf{
server localhost:8081 weight=5;
server localhost:8082 weight=3;
server localhost:8083 down;
}
server {
listen 80;
server_name www.cccmall.com;
location /{
proxy_pass http://czf;
}
}
通过设置weight的比重,来进行资源分配。
补充两个关键字:
- down,表示当前服务器不参与负载均衡。
- backup,预留的备份服务器。当其他所有的非backup机器出现故障或者忙的时候,才会请求backup机器,因此这台机器的压力最轻。
六、选择方式
通过以上的介绍,我想大家都应该对不同的负载均衡方式应该有所取舍。如果大家担心因为共享资源的问题,而去选择基于Hash的均衡方式,其实不然,这种方式,真正开发使用的次数其实也不是很多。现在市面上,也有许多解决共享资源的问题。像redis+sso就可以处理该问题。