Nginx 负载均衡学习实践

Nginx 是一个高性能的静态资源、反向代理服务器,现在越来越多的互联网公司使用 Nginx 托管网站,还有一个出名的静态资源服务——Apache,在 Nginx 没有出现之前 Apache 用的人很多,之后后者功能及性能更加优秀就被越来越多的人选择了。

Nginx 相较于 Apache 在具有反向代理的功能,同时在 IO 方面性能卓越。两者的详细区别可以参考以下两篇博客:

开始正文,这篇文章主要总结 Nginx 在负载均衡、反向代理、缓存等方面。

代理、正向代理、反向代理

先说代理,代理就是加个中间层,现实中就是中介,这个中介可以帮客户(Client)做事情。基于代理可以做很多事情,缓存就是常见的应用场景。

关于正向代理和反向代理详细讲解的文章: https://www.cnblogs.com/taostaryu/p/10547132.html

nginx 负载均衡

负载均衡(load balance)是指把一块业务负载分担到其他服务器,这样通过横向扩展的方式能提到系统的吞吐量和负载。

nginx 负载均衡是一种简单的负载均衡技术,所有的请求打到 nginx,然后 nginx 又发送的所有的响应,这种方式在吞吐量大的业务场景会成为业务系统瓶颈。解决的办法是使用 LVS(Linux virtual Server),这种方式通过网络底层协议进行负载均衡,可以有效提高负载均衡器的吞吐量(LVS 这是服务器端开发一块大的知识,因这篇文章总结 nginx 不再详细介绍)。

nginx 单机负载均衡

实验环境:

  • centos7.6
  • nginx 1.5+

1、实验准备,三台服务器

ip 及主机:

10.0.0.10 lb01 作为LB服务器
10.0.0.20 web01 作为web服务器1
10.0.0.21 web02 作为web服务器2

2、软件安装

在三台服务器都安装 nginx,最简单的方式通过 yum 安装,当然也可以编译安装。

这里使用 yum 安装。

yum install -y nginx

安装完后还需要了解 nginx 程序的一些信息:

  • 程序配置文件: /etc/nginx
  • 常用配置文件夹:/etc/nginx/conf.d
  • 日志路径:/var/log/nginx
  • nginx 主配置文件,这个文件通常,通常在/etc/nginx 下,名称是 nginx.conf

3、配置两台 web 服务器(web01,web02)

这两个 web 服务器不一定是 web 服务器,也可以是代理后端的反向代理服务器。

3.1 启动服务

对三台服务器都做这个操作。

# 启动服务
systemctl start nginx
# 或者, 前提环境变量配置好
nginx

3.2 设置静态网页,以区分负载均衡代理的静态网页

# nginx默认安装后,静态文件夹路径为 /usr/share/nginx/html
# 切换到静态文件所在目录
cd /usr/share/nginx/html

# 把默认文件改为有标识内容
echo "<h1>10.0.0.20 web01</h1>
" > index.html

3.3 测试

在浏览器中访问能显示“10.0.0.20 web01”。

image.png

3.4 web02 配置同上

4、配置负载均衡服务器(lb01)

4.1 在/etc/nginx/conf.d 文件夹中修改 default.conf

# 资源池
   upstream webpool {
        server 10.0.0.20:80 weight=5;
        server 10.0.0.21:80 weight=5;

        server 10.0.0.22:80 weight=5 backup;
   }
# 站点
    server {
        # 监听端口
        listen       80;
        # 站点名称
        server_name  localhost;
        # 站点资源文件夹路径
        location / {
            root /usr/share/nginx/html;
            index index.html index.htm;
            proxy_pass http://webpool;
        }
    }

4.2 重启并测试负载均衡

# 重启
systemctl restart nginx

测试效果

image.png

刷新浏览器后

image.png

5、upstream 参数

upstream 模块常用参数:

  • ip_hash, 以 ip 定位访问哪个服务器, 使用 ip_hash 不能使用热备

  • weight=number

    • 设置结点的权重, 权重越大 nginx 转发过去的请求越多
    • 注意: 当负载均衡调度算法为 ip_hash 时后端负载均衡的调度状态不能是 weight 和 backup
  • max_fails=number

    • 在 server 参数后使用, server xxxxxxx max_fails=number
    • 默认为 1, 0 表示禁止, 一般为 2-3 次
    • max_fails 用于设置失败尝试次数, 一般设置为 2~3, 值设置的越小故障响应时间就越短用户体验就越好, 通常这个参数配合 fail_timeout 一起使用, 当尝试 max_fails 次后, 等待 fail_timeout 再次尝试.
    • 配合 proxy_next_upstream, fastcgi_next_upstream 可以在失败尝试 number 次后直接转发到指定的结点
  • fail_timeout=number

    • 用于设置失败尝试后的等待时间,配合 max_fails 使用.
    • 时间单位是秒(s)
  • backup

    • 用于设置热备份, 也就是说当主 nginx 宕掉后, 会使用 backup 指定的.
    • 在 server 参数后使用, backup 是一个标志参数
  • down

    • 这个参数标志者服务器永远不可以, 配合 ip_hash 一起使用
  • max_conns=number

    • 设置 server 的最大连接数

upstream 完整参数:nginx upstream 参数说明文档 · 中文

6、nginx 轮询算法

  • rr 轮询(默认) 交替向结点转发请求
  • weight, 权重, 在轮询的基础上加权重(rr+weight), 权重和访问次数成正比, 权重越大访问越多
  • ip_hash, 根据请求的 ip 地址算出访问哪个结点, 特点: 客户端每次都访问固定结点, 是解决 Session 会话的一种方案(LVS 负载均衡的-p 参数, keepalived 配置的 persistence_timeout 参数), 缺点: 特殊情况下会导致负载不均
  • fair(第三方,NO) 动态算法
    • 依据响应时间分配, nginx 本身不支持 fair 算法, 使用时需要下载 upstream_fair 模块
  • url_hash(第三方,NO), 按 url 的 hash 结果来分配请求, 类似 ip_hash, 对于后端服务器作为缓存服务器时优化显著.

nginx 高可用负载均衡

使用 upstream 可以给被代理节点(后端服务)配置高可用,当后端服务访问不可用或者在一定时间内未成功响应则使用后备节点。

在原有的 nginx 配置上增加以下配置信息,lb02 拷贝 lb01 的配置。

   upstream webpool {
        # 正常工作的节点
        server 10.0.0.20:80 weight=5;
        server 10.0.0.21:80 weight=5;
        # 备份节点
        server 10.0.0.22:80 weight=5 backup;
   }

如果配置负载均衡 nginx 的高可用就需要额外的工具了,这里高可用方案是 nginx+keepalived。两台 nginx 做负载均衡器,一主一备份。

在使用 keepalived 做高可用后,此时访问 LB 服务器通过虚拟 ip 地址,即 VIP(Virtual IP)。当主 LB 宕机利用 keepalived 进行 ip 地址漂移,来实现 failover。

这篇文章侧重实践,关于 keepalive 详细内容可转到 https://www.jianshu.com/p/a6b5ab36292a

1、实验准备

准备四台服务器。

10.0.0.10 lb01 负载均衡主
10.0.0.11 lb02 负载均衡备

10.0.0.20 web01 web服务1
10.0.0.21 web02 web服务2

2、在两台 LB 服务器安装 keepalived

yum install -y keepalived

3、配置

配置文件 /etc/keepalived/keepalived.conf

lb01 配置文件:

! Configuration File for keepalived
! 全局配置
global_defs {
    ! 出问题向那个邮箱报警
   notification_email {
     acassen@firewall.loc
   }
   ! 发件人是谁
   notification_email_from Alexandre.Cassen@firewall.loc
   ! 邮件服务器的地址
   smtp_server 192.168.200.1
   ! 连接邮件服务器超时时间
   smtp_connect_timeout 30
   ! keepalived的编号, 不能相同, 与MySQL的server_id功能相同
   router_id LVS_01
   vrrp_skip_check_adv_addr
   vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

! keepalived的一个实例, 代表着一个服务, 一个ip地址
! 通常配置一组高可用 state、priority 不同,其他都要相同
vrrp_instance VI_1 {
    ! 服务器状态
    state MASTER
    ! 使用的网卡,通信端
    interface eth0
    ! 实例的id,在一个高可用组中的要相同
    virtual_router_id 51
    ! 优先级, 影响结点选举master
    priority 50
    ! 心跳间隔, 单位:秒
    advert_int 1
    ! 服务器之间通信验证, 某组高可用结点它们的认证账号密码应该一样
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    ! VIP结点, virtual 结点, 可以是多个或一个
    virtual_ipaddress {
        10.0.0.30/24
    }
}

lb02 配置

配置文件不同点 :router_id、state、priority

! Configuration File for keepalived
! 全局配置
global_defs {
    ! 出问题向那个邮箱报警
   notification_email {
     acassen@firewall.loc
   }
   ! 发件人是谁
   notification_email_from Alexandre.Cassen@firewall.loc
   ! 邮件服务器的地址
   smtp_server 192.168.200.1
   ! 连接邮件服务器超时时间
   smtp_connect_timeout 30
   ! keepalived的编号, 不能相同, 与MySQL的server_id功能相同
   router_id LVS_01
   vrrp_skip_check_adv_addr
   vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

! keepalived的一个实例, 代表着一个服务, 一个ip地址
! 通常配置一组高可用 state、priority 不同,其他都要相同
vrrp_instance VI_1 {
    ! 服务器状态
    state BACKUP
    ! 使用的网卡,通信端
    interface eth0
    ! 实例的id, 在一个高可用组中的要相同
    virtual_router_id 51
    ! 优先级, 影响结点选举master
    priority 150
    ! 心跳间隔, 单位:秒
    advert_int 1
    ! 服务器之间通信验证, 某组高可用结点它们的认证账号密码应该一样
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    ! VIP结点, virtual 结点, 可以是多个或一个
    virtual_ipaddress {
        10.0.0.30/24
    }
}

4、启动两台 lb 服务器的 keepalived 程序

# 启动
systemctl start keepalived

在 lb01 上查看虚拟 ip 地址。

# 查看虚拟ip--vip的信息, 应该看到10.0.0.30/24
ip addr

image.png

在 lb02 上查看虚拟 ip 地址,正常应该看不到 10.0.0.30 的 ip 地址,只有当主宕机备份机(lb02)才会看到 10.0.0.30ip 地址。

# 查看虚拟ip--vip的信息
ip addr

image.png

5、测试

5.1 负载均衡器测试

image.png

5.2 关闭 lb01 在次进行测试

lb01 操作

# 模拟宕机
shutdown now -h

测试正常

image.png

image.png

查看 lb02 的 ip 地址,可以看到 10.0.0.30IP 地址以及飘移过来,此时 lb02 以经成为了负载均衡器的主节点(原来时备用节点)

image.png

nginx 实现静分离

所谓动静分离即动态的请求(发向后端的)和静态资源请求分离开来,分别打到不同的反向代理节点上。

实现方式

  1. 根据请求路径, 通过 nginx 的 location 参数匹配分流
  2. 根据文件扩展名匹配分流
  3. 根据浏览器标识 user_agent(header)匹配分流

这些都通过设置 nginx 的参数实现,即根据一定的规则匹配后,把不同的请求代理到不同的资源结点。

nginx 做缓存服务器

nginx 也可以用来做缓存,第一次请求时的静态资源会保存在 nginx 上,再次请求直接返回。

实现时通过配置 nginx 的代理模块 http_proxy 参数即可实现。 ngx_http_proxy_module 模块参数

nginx 做缓存服务器详细介绍文章: https://blog.csdn.net/weixin_30826095/article/details/97062677 https://www.cnblogs.com/Eivll0m/p/4921829.html

(完)