Nginx分布式框架详解93-101负载均衡01

负载均衡概述

早期的网站流量和业务功能都比较简单,单台服务器足以满足基本的需求,但是随着互联网的发展,业务流量越来越大并且业务逻辑也跟着越来越复杂,单台服务器的性能及单点故障问题就凸显出来了,因此需要多台服务器进行性能的水平扩展及避免单点故障出现。那么如何将不同用户的请求流量分发到不同的服务器上呢?这就需要负载均衡来处理。

负载均衡的原理及处理流程

系统的扩展可以分为纵向扩展和横向扩展。

  • 纵向扩展是从单机的角度出发,通过增加系统的硬件处理能力来提升服务器的处理能力。
  • 横向扩展是通过添加机器来满足大型网站服务的处理能力。

如上图,负载均衡涉及到两个重要的角色分别是「应用集群」和「负载均衡器」。

  • 应用集群:将同一应用部署到多台机器上,组成处理集群,接收负载均衡设备分发的请求,进行处理并返回响应的数据。
  • 负载均衡器:将用户访问的请求根据对应的负载均衡算法,分发到集群中的一台服务器进行处理。

负载均衡作用:

  • 解决服务器的高并发能力,提高应用程序的处理性能
  • 提供故障转移,实现高可用
  • 通过添加或减少服务器数量,增强网站的可扩展性
  • 在负载均衡器上进行过滤,可以提高系统的安全性

负载均衡的常用处理方式

先说明,我们常用的是 四/七层负载均衡 方式,前面两个方式可以了解。

用户手动选择

这种方式比较原始,主要实现的方式就是在网站主页上面提供不同线路、不同服务器链接方式,让用户来选择自己访问的具体服务器,来实现负载均衡。

如下图,用户点击不同的下载方式,就会跳转到不同的下载地址。这是主动式的负载均衡,我们无法控制用户的选择。如果用户全部点击第一个下载方式,那么服务器的压力将非常大。

DNS轮询方式

DNS:域名系统(服务)协议(DNS)是一种分布式网络目录服务,主要用于域名与 IP 地址的相互转换。

大多域名注册商都支持对同一个主机名添加多条 A 记录,这就是 DNS 轮询,DNS 服务器将解析请求按照 A 记录的顺序,随机分配到不同的 IP 上,这样就能完成简单的负载均衡。DNS 轮询的成本非常低,在一些不重要的服务器,被经常使用。

如下图:客户端如果想访问服务器集群,首先去 DNS 服务器获取我们曾经在 DNS 服务器保存的「记录表」,这个「记录表」将会把某个服务器的地址返回给客户端,客户端再根据这个地址,访问指定的服务器。这个「记录表」在开始期间需要我们去 DNS 服务器进行添加。

「记录表」长什么样,如下图的主机记录 www。这是我为某一个域名添加的 IP 地址,用 2 台服务器来做负载均衡。其中两个记录值都绑定了 www.nginx521.cn 地址。(一个域名可以绑定多个IP地址)

验证:

ping www.nginx521.cn

注意:记得清空本地的 DNS 缓存,如果本地有缓存,无论你怎么 ping,都会 ping 到缓存的服务器地址,无法负载均衡

ipconfig /flushdns

目前需要 ping 一次然后清理一次缓存,才能实现负载均衡的轮询效果。

我们发现使用 DNS 来实现轮询,不需要投入过多的成本,虽然 DNS 轮询成本低廉,但是 DNS 负载均衡存在明显的缺点:

  1. 可靠性低
    假设一个域名 DNS 轮询多台服务器,如果其中的一台服务器发生故障,那么所有的访问该服务器的请求将不会有所回应,即使你将该服务器的 IP 从 DNS 中去掉,但是由于各大宽带接入商将众多的 DNS 存放在缓存中,以节省访问时间,导致 DNS 不会实时更新。所以 DNS 轮流上一定程度上解决了负载均衡问题,但是却存在可靠性不高的缺点。
  2. 负载均衡不均衡
    DNS 负载均衡采用的是简单的轮询负载算法,不能区分服务器的差异,不能反映服务器的当前运行状态,不能做到为性能好的服务器多分配请求,另外本地计算机也会缓存已经解析的域名到 IP 地址的映射,这也会导致使用该 DNS 服务器的用户在一定时间内访问的是同一台 Web 服务器,从而引发 Web 服务器减的负载不均衡。

负载不均衡则会导致某几台服务器负荷很低,而另外几台服务器负荷确很高,处理请求的速度慢,配置高的服务器分配到的请求少,而配置低的服务器分配到的请求多。

负载均衡实现之四层/七层负载

介绍四/七层负载均衡之前,我们先了解一个概念,OSI(open system interconnection),叫开放式系统互联模型,这个是由国际标准化组织 ISO 指定的一个不基于具体机型、操作系统或公司的网络体系结构。该模型将网络通信的工作分为七层。

  • 应用层:为应用程序提供网络服务
  • 表示层:对数据进行格式化、编码、加密、压缩等操作
  • 会话层:建立、维护、管理会话链接
  • 传输层:建立、维护、管理端到端链接,常见的有TCP/UDP
  • 网络层:IP寻址和路由选择
  • 数据链路层:控制网络层与物理层之间的通信
  • 物理层:比特流传输
什么是四层负载均衡

所谓四层负载均衡指的是 OSI 七层模型中的传输层,主要是基于 IP + PORT 的负载均衡
实现四层负载均衡的方式:
硬件:F5 BIG-IP、Radware 等,性能好,成本高、无法扩展
软件:LVS、Nginx、Hayproxy 等,性能较好,成本低、可以扩展

什么是七层负载均衡

所谓的七层负载均衡指的是在应用层,主要是基于虚拟的 URL 或主机 IP 的负载均衡
实现七层负载均衡的方式:
软件:Nginx、Hayproxy 等

四层和七层负载均衡的区别
  • 四层负载均衡数据包是在底层就进行了分发,而七层负载均衡数据包则在最顶端进行分发,所以四层负载均衡的效率比七层负载均衡的要高(四层比七层少,速度块,效率高,但是可能请求丢失等)
  • 四层负载均衡不识别域名,而七层负载均衡识别域名
    处理四层和七层负载以外,其实还有二层、三层负载均衡,二层是在数据链路层基于 mac 地址来实现负载均衡,三层是在网络层一般采用虚拟 IP 地址的方式实现负载均衡。
    实际环境采用的模式:四层负载(LVS)+ 七层负载(Nginx)

nginx七层负载均衡配置

Nginx 要实现七层负载均衡需要用到 proxy_pass 代理模块配置。Nginx 默认安装支持这个模块,我们不需要再做任何处理。Nginx 的负载均衡是在 Nginx 反向代理的基础上把用户的请求根据指定的算法分发到一组「upstream 虚拟服务池」。

七层负载均衡指令

upstream指令
该指令是用来定义一组服务器,它们可以是监听不同端口的服务器,并且也可以是同时监听 TCP 和 Unix socket 的服务器。服务器可以指定不同的权重,默认为 1。

语法 默认值 位置
upstream http

server指令
该指令用来指定后端服务器的名称和一些参数,可以使用域名、IP、端口或者 Unix socket。

语法 默认值 位置
server [paramerters] upstream

server 后的 name 就是 upstream 后的 name,两者保持一致。

七层负载均衡指令案例

准备四台服务器,一台用来做负载均衡器,三台用来接收负载均衡器的请求。

主机上部署的nginx做负载均衡器,通过docker启动3个web服务来接收负载均衡器的请求,
通过docker启动3个web服务,在同一台主机上,只是端口不同:

$root@debian-01:/usr/local/nginx# docker ps -a|grep gin_blog*

6dc39901dd7c   gin_blog01     "./gin_blog"             19 hours ago   Up 18 hours                172.17.82.242:8000->8000/tcp   gin_blog01
edda73ed0ba6   gin_blog03     "./gin_blog"             9 days ago     Up 24 hours                172.17.82.242:8002->8002/tcp   gin_blog03
34ea93c8381e   gin_blog02     "./gin_blog"             9 days ago     Up 24 hours                172.17.82.242:8001->8001/tcp   gin_blog02

负载均衡器设置:这是一个Nginx代理服务器,让它去负载均衡访问三个服务器,配置:

http {
    upstream gin-blog {
        server 172.17.82.242:8000 weight=2;  # weight=2配置权重,如果有4个请求到来,会有两个请求转发到该服务器
        server 172.17.82.242:8001 weight=1;
        server 172.17.82.242:8002 weight=1;
    }

    server {
            listen 80;
            server_name www.mayanan.cn mayanan.cn;
            location / {
                root html;
                index index.html index.htm;
            }

            location /apis/ {
                proxy_pass http://gin-blog/;
            }
        }
}

访问负载均衡器的地址,如 http://mayanan.cn/apis/test,它会找到 proxy_pass 后的地址,比如上方,它会根据 gin_blog 找到对应的 upstream 里内地址,替换掉 backend,变成:

nginx负载均衡状态介绍

代理服务器在负载均衡调度中的状态有以下几个:

状态 概述
down 当前的 server 暂时不参与负载均衡
backup 预留的备份服务器
max_fails 允许请求失败的次数
fail_timeout 经过 max_fails 失败后,服务暂停时间
max_conns 限制最大的接收连接数

nginx负载均衡状态值down

down 指令将该服务器标记为永久不可用,那么负载均衡器将不参与该服务器的负载均衡。
如下,如果不希望负载均衡器以负载均衡来处理 172.17.82.242:8002 服务器:

http {
  upstream gin-blog {
      server 172.17.82.242:8000 weight=2;
      server 172.17.82.242:8001 weight=1;
      server 172.17.82.242:8002 weight=1 down;
  }
}

该状态一般会对需要停机维护的服务器进行设置。

nginx负载均衡状态值backup

backup 指令将该服务器标记为备份服务器,当主服务器不可用时,才用备份服务器来传递请求。
它不同于 down 指令,down 指令将服务器永久禁止,而 backp 指令仅仅临时禁止,当主服务器不可用后,临时禁止的服务器就会站出来。

upstream gin-blog {
    server 172.17.82.242:8000 weight=2;
    server 172.17.82.242:8001 weight=1 backup;
    server 172.17.82.242:8002 weight=1 down;
}

上方代码中 8002 服务器永久禁止,而 8001 服务器是备份服务器,所以 8000 服务器是主服务器。
此时需要将8000端口所在的docker服务停止docker stop gin_blog01,用它来模拟当唯一对外提供访问的服务宕机以后,backup 的备份服务器就能开始对外提供服务。

经过测试,停掉8000服务端口后,再次访问负载均衡器,它只会请求 8001 端口的服务器(备份服务器),而恢复 8000 端口,只会请求 8000 端口的服务器。

nginx负载均衡状态值max_conns、max_fails、fail_timeout

max_conns 指令用来限制同时连接到 upstream 负载上的单个服务器的最大连接数。默认为 0,表示不限制,使用该配置可以根据后端服务器处理请求的并发量来进行设置,防止后端服务器被压垮。

语法 默认值 位置
max_conns= 0 upstream

number 是大于 0 的数字。

max_fails 指令设置允许请求代理服务器失败的次数,默认为 1。

fail_timeout 指令设置经过 max_fails 失败后,服务暂停的时间,默认是 10 秒。

语法 默认值 位置
max_fails= 1 upstream
fail_timeout= 10 秒 upstream
  • number是大于0的数字
  • time是时间,单位为秒
posted @ 2022-09-25 15:32  专职  阅读(169)  评论(0编辑  收藏  举报