Brc's blog
首页
前端
后端
运维
  • 工作笔记
  • 分类
  • 标签
  • 归档
关于

Brc

努力中
首页
前端
后端
运维
  • 工作笔记
  • 分类
  • 标签
  • 归档
关于
  • Linux基础

  • Linux进阶

    • shell

    • nginx

      • nginx快速入门
      • LNMP架构
      • Nginx反向代理
      • Nginx七层负载均衡
        • Nginx负载均衡基本概述
          • 什么是负载均衡
          • 为什么需要负载均衡
          • 负载均衡与代理区别
        • Nginx负载均衡应用场景
          • 四层负载均衡
          • 七层负载均衡
          • 四层与七层区别
        • Nginx负载均衡配置场景
          • 负载均衡场景环境规划
          • 后端Web节点配置实例
          • 前端接入Nginx负载均衡
          • 浏览器访问测试负载效果
        • Nginx负载均衡调度算法
          • 轮询调度算法
          • 加权轮询调度算法
          • ip_hash调度算法
          • 一致性hash调度算法
          • url_hash调度算法
          • least_conn调度算法
        • Nginx负载均衡后端状态
          • max_conns限制连接数
          • down标识关闭状态
          • backup标识备份状态
          • maxfails与failtimeout
        • Nginx负载均衡会话共享
          • 什么是会话保持
          • 为什么需要会话保持
          • 如何实现会话保持
          • 会话保持场景演示
          • 配置web节点
          • 配置负载均衡
          • 配置Redis服务
          • 配置php连接Redis
          • 测试集群会话共享
      • Rewrite重写
      • HTTPS
    • keepalived

    • LVS

    • ansible

    • docker

    • mysql

  • 其他

  • 运维
  • Linux进阶
  • nginx
Brc
2021-08-16
目录

Nginx七层负载均衡

# Nginx负载均衡基本概述

# 什么是负载均衡

负载均衡Load Balance ,指的是将用户访问请求所产生的流量,进行平衡,分摊到多个应用节点处理。

负载均衡扩展了应用的服务能力,增强了应用的可用性。

# 为什么需要负载均衡

当我们的 Web服务器直接面向用户,往往要承载大量并发请求,单台服务器难以负荷,我使用多台Web服务器组成集群,前端使用Nginx负载均衡,将请求分散的打到我们的后端服务器集群中,实现负载的流量分发。从而提升整体性能、以及系统的容灾能力。

image-20210817141341049

# 负载均衡与代理区别

  • Nginx负载均衡与Nginx反向代理不同地方在于:
    • Nginx代理仅代理一台服务器。
    • Nginx负载均衡则是将客户端请求通过proxy_pass 代理至一组upstream资源池。

# Nginx负载均衡应用场景

# 四层负载均衡

四层负载均衡指的是 OSI 七层模型中的传输层,四层仅需要对客户端的请求进行TCP/IP协议的包转发就可以实现负载均衡。

四层负载均衡的性能极好,因为只需要底层进行转发处理,而不需要进行一些复杂的逻辑。

image-20210817141600686

# 七层负载均衡

七层负载均衡工作在应用层,它可以完成很多应用方面的协议请求,比如我们说的http应用负载均衡,它可以实现 http头信息的改写、安全应用规则控制、URI匹配规则控制、及rewrite等功能,所以在应用层里面可以做的内容就更多了。

image-20210817141722180

# 四层与七层区别

  • 四层负载均衡:传输层
    • 优点:性能高,数据包在底层就进行了转发
    • 缺点:仅支持ip:prot转发,无法完成复杂的业务逻辑应用
  • 七层负载均衡︰应用层
    • 优点:贴近业务,支持URI路径匹配、Header改写、Rewrite等
    • 缺点:性能低,数据包需要拆解到顶层才进行转发

# Nginx负载均衡配置场景

  • Nginx实现负载均衡需要两个模块:
    • proxy_pass代理模块
    • upstream虚拟资源池模块
Syntax : upstream name { ... }
Default: -
Context: http

#upstream例
upstream backend {
    server backend1.example.com	weight=5;
    server backend2.example.com:8080;
    server unix:/tmp/backend3;
    server backup1.example.com:8080 backup;
}
server {
    location / {
    	proxy_pass http://backend;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 负载均衡场景环境规划

  • 负载均衡场景架构图规划

image-20210817143135334

  • 负载均衡场景地址规划
角色 主机名 外网IP(NAT) 内网IP(LAN)
Proxy proxy01 eth0:10.0.0.5 eth1:172.16.1.5
web01 web01 eth0:10.0.0.7 eth1:172.16.1.7
web02 web02 eth0:10.0.0.8 eth1:172.16.1.8

# 后端Web节点配置实例

1.Web01服务器上配置为应用服务节点,创建对应html 文件

[root@web01 ~]# cat /etc/nginx/conf.d/web.birenchong.cn.conf
server {
    listen 80;
    server_name web.birenchong.cn;
    root /web;

    location / {
    	index index.html;
    }
}
[root@web01 ~]# mkdir/web
[root@web01 ~]# echo "web01..." > /node/index.html
[root@web01 ~]# systemctl restart nginx
1
2
3
4
5
6
7
8
9
10
11
12
13

2.Web02服务器上配置为应用服务节点,创建对应html文件

[root@web02 ~]# cat /etc/nginx/conf.d/web.birenchong.cn.conf
server {
    listen 80;
    server_name web.birenchong.cn;
    root /web;

    location /{
    	index index.html;
    }
}
[root@web02 ~]# mkdir /web
[root@web02 ~]# echo "web02..." > /node/index.html
[root@web02 ~]# systemctl restart nginx
1
2
3
4
5
6
7
8
9
10
11
12
13

# 前端接入Nginx负载均衡

1.将proxy01配置为负载均衡,将所有请求代理至虚拟资源池

[root@proxy01 ~]# cat /etc/nginx/conf.d/proxy_web.birenchong.cn.conf
upstream web {
	server 172.16.1.7:80;
	server 172.16.1.8:80;
}

server {
    listen 80;
    server_name web.birenchong.cn;

    location /{
    	proxy_pass http://web;
    	include proxy_params;
    }
}
[root@proxy01 ~]# systemctl restart nginx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

2.准备Nginx负载均衡需要使用的proxy_params文件

[root@Nginx ~]# vim /etc/nginx/proxy_params
proxy_http_version 1.1;
peoxy_set_header Connection "";
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;

proxy_buffering on;
proxy_buffer_size 64k;
proxy_buffers 4 64k;
1
2
3
4
5
6
7
8
9
10
11
12
13

# 浏览器访问测试负载效果

使用浏览器访问web.birenchong.cn ,然后进行刷新测试。

# Nginx负载均衡调度算法

调度算法 概述
轮询 按时间顺序逐一分配到不同的后端服务器(默认)
weight 加权轮询, weight值越大,分配到的访问几率越高
ip_hash 每个请求按访问IP的hash结果分配,这样来自同一IP的固定访问一个后端服务器
least_conn 将请求传递到活动连接数最少的服务器。

# 轮询调度算法

轮询调度算法的原理是将每一次用户的请求,轮流分配给内部中的服务器。

轮询算法的优点是其简洁性,它无需记录当前所有连接的状态,所以它是一种无状态调度。

upstream load_pass {
	server 172.16.1.7:80;
	server 172.16.1.8:80;
}

server {
    listen 80;
    server_name web.birenchong.cn;

    location / {
    	proxy_pass http://load_pass;
    	include proxy_params;
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 加权轮询调度算法

轮询调度算法没有考虑每台服务器的处理能力,在实际情况中,由于每台服务器的配置、安装的业务应用等不同,其处理能力会不一样。所以,我们根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。

upstream load_pass {
	server 172.16.1.7:80 weight=5;
	server 172.16.1.8:80 weight=1;
}

server {
    listen 80;
    server_name web.birenchong.cn;

    location / {
        proxy_pass http://load_pass;
        include proxy_params;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# ip_hash调度算法

ip_hash是基于用户请求的IP,对该IP进行hash运算,根据hash运算的值,将请求分配到后端特定的一台节点进行处理。ip_hash算法实现公式:hash(ip) % node_counts = index

image-20210817150351653

如何配置ip_hash调度算法

upstream load_pass {
    ip_hash;
    server 172.16.1.7:80;
    server 172.16.1.8:80;
}

server {
    listen 80;
    server_name web.birenchong.cn;

    location / {
    	proxy_pass http://load_pass;
    	include proxy_params;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  • ip_hash调度算法会带来两个问题
    • 1.如果有大量来自于同一IP的请求会造成某个后端节点流量过大,而其他节点无流量
    • 2.如果临时下线一台节点,会出现重新计算hash值,官方建议将下线节点标记为down 状态,以保留客户端IP地址的当前哈希值。(如下图所示:)

image-20210817150657552

如果有大量的用户调度到某一节点,而该节点刚好故障,则该算法会重新计算结果,从而造成大量的用户被转移其他节点处理,而需要重新建立会话。

# 一致性hash调度算法

为了规避上述hash 情况,一致性hash算法就诞生,一致性Hash算法也是使用取模的方法,但不是对服务器节点数量进行取模,而是对2的32方取模。即,一致性Hash算法将整个Hash 空间组织成一个虚拟的圆环, Hash函数值的空间为0~2^32 - 1,整个哈希环如下:

  • —致性Hash参考地址 (opens new window)
    • Hash算法原理
    • Hash算法增加节点
    • Hash算法减少节点
    • Hash算法数据倾斜问题

# url_hash调度算法

根据用户请求的URL进行hash 取模,根据hash运算的值,将请求分配到后端特定的一台节点进行处理。URL算法使用场景如下: client-->nginx-->url_hash-->cache1-->app

  • 1.用户请求nginx负载均衡器,通过url调度算法,将请求调度至Cache1
  • 2.由于Cache1节点没有对应的缓存数据,则会请求后端获取,然后返回数据,并将数据缓存起来;
  • 3.当其他用户再次请求此前相同的URL 时,此时调度器依然会调度至Cache1节点处理;
  • 4.由于Cache1节点已存在该URL资源缓存,所以直接将缓存数据进行返回;能大幅提升网站的响应;

1.配置后端节点

# web1节点
[root@web01 ~]# echo "web1 Url1" >/web/url1.html
[root@web01 ~]# echo "web1 Url2" >/web/url2.html

# web2节点
[root@web02 ~]# echo "web2 Url1" >/web/url1.html
[root@web02 ~]# echo "web2 Url2" > /web/url2.html
1
2
3
4
5
6
7

2.负载均衡配置url_hash调度算法

upstream load_pass {
    # 请求同一个url,会始终定向到同一个服务器节点,consistent表示使用一致性hash算法
    hash $request_uri consistent;
    server 172.16.1.7:80;
    server 172.16.1.8:80;
}

server {
    listen 80;
    server_name web.birenchong.cn;

    location / {
    	proxy_pass http://load_pass;
    	include proxy_params;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

3.Client测试,会发现请求相同的 URL,始终会被定向至某特定后端节点。

[root@client ~]# curl -HHost:web.birenchong.cn http://10.0.0.5/url1.html
web2 Url1
[root@client ~]# curl -HHost:web.birenchong.cn http://10.0.0.5/url1.html
web2 Url1
[root@client ~]# curl -HHost:web.birenchong.cn http://10.0.0.5/url1.html
web2 Url1
1
2
3
4
5
6

# least_conn调度算法

least_conn调度算法实现原理,哪台节点连接数少,则将请求调度至哪台节点。

假设∶A节点有1000个连接、b节点有500连接,如果此时新的连接进入会分发给b节点

upstream load_pass {
    least_conn;
    server 172.16.1.7:80;
    server 172.16.1.8:80;
}

server {
    listen 80;
    server_name web.birenchong.cn;

    location / {
    	proxy_pass http://load_pass;
    	include proxy_params;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# Nginx负载均衡后端状态

后端 Web节点在前端Nginx负载均衡调度中的状态

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

# max_conns限制连接数

max_conns用来限制每个后端节点能够接收的最大TCP连接数,如果超过此连接则会抛出错误。

[root@proxy01 ~]# cat proxy_web.birenchong.cn.conf
upstream load_pass {
	server 172.16.1.7:80 max_conns=2;
	server 172.16.1.8:80 max_conns=2;
}

server {
    listen 80;
    server_name web.birenchong.cn;

    location / {
    	proxy_pass http://load_pass;
    	include proxy_params;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

通过jmter压力测试发现,当后端节点处理的连接数非常多的时候,当大于4个连接,其余的连接则会抛出异常,也就是每次仅能满足4个连接。

# down标识关闭状态

down将服务器标记为不可用状态。

[root@proxy01 ~]# cat proxy_web.birenchong.cn.conf
upstream load_pass {
	server 172.16.1.7:80 down; # —般用于停机维护
	server 172.16.1.8:80;
}

server {
    listen 80;
    server_name web.birenchong.cn;

    location / {
    	proxy_pass http://load_pass;
    	include proxy_params;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# backup标识备份状态

backup将服务器标记为备份服务器。当主服务器全部不可用时,将请求传递至备份服务器处理。

[root@proxy01 ~]# cat proxy_web.birenchong.cn.conf
upstream load_pass {
    server 172.16.1.7:80 backup;
    server 172.16.1.8:80;
    server 172.16.1.9:80;
}

server {
    listen 80;
    server_name web.birenchong.cn;

    location / {
    	proxy_pass http://load_pass;
    	include proxy_params;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# max_fails与fail_timeout

max_fails=2服务器通信失败尝试2次,仍然失败,认为服务器不可用;

fail_timeout=5s服务器通信失败后,每5s探测一次节点是否恢复可用;

在fail_timeout设定的时间内,与服务器连接失败达到max_fails则认为服务器不可用;

[root@proxy01 ~]# cat proxy_web.birenchong.cn.conf
upstream load_pass {
    server 172.16.1.7:80 max_fails=2 fail_timeout=5s;
    server 172.16.1.8:80 max_fails=2 fail_timeout=5s;
}

server {
    listen 80;
    server_name web.birenchong.cn;

    location / {
    	proxy_pass http://load_pass;
    	include proxy_params;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# Nginx负载均衡会话共享

# 什么是会话保持

当用户登陆一个网站服务器,网站服务器会将用户的登陆信息存储下来(存储下来的内容叫Session ) ,以保证我们能够一直处于”登陆在线“状态。

# 为什么需要会话保持

由于我们使用的是负载均衡轮询机制,会导致用户请求分散在不同的节点,从而造成会话无法保持。

假设用户A,通过负载均衡登陆了网站,此时会话信息存储在A节点,那么当它一刷新,负载均衡会将请求分发给B节点,那么B节点没有用户A的登陆信息,就会提示用户A登陆,当A用户点击登陆时又会将请求分发给C节点,从而造成用户A无法实现会话保持。

# 如何实现会话保持

  • 1.粘性session:指Ngnix每次都将同一用户的所有请求转发至同一台服务器上,既Nginx的IP_hash;
  • 2.session复制:每次session发生变化,就广播给集群中的服务器,使所有的服务器上的session相同;
  • 3.session共享:缓存session至内存数据库中,使用redis,memcached实现;
  • 4.session持久化:将session存储至数据库中,像操作数据一样操作session;

# 会话保持场景演示

# 配置web节点

1.首先安装并配置phpmyadmin

[root@web01 ~]# cd /code
[root@web01 code]# wget https://files.phpmyadmin.net/phpMyAdmin/5.1.1/phpMyAdmin-5.1.1-all-languages.zip
[root@web01 code]# unzip phpMyAdmin-5.1.1-all-languages.zip
1
2
3

2.修改phpmyadmin连接远程的数据库

[root@web01 code]# cd phpMyAdmin-5.1.1-all-languages/
[root@web01 phpMyAdmin-5.1.1-all-languages]# cp config.sample.inc.php config.inc.php
[root@web01 phpMyAdmin-5.1.1-all-languages]# vim config.inc.php
/*Server parameters*/
$cfg['Servers'][$i]['host'] = '172.16.1.51';
1
2
3
4
5

3.在多台web上准备phpmyadmin 的nginx配置文件

[root@web01 ~]# cat /etc/nginx/conf.d/php.conf
server {
    listen 80;
    server_name php.birenchong.cn;
    root /code/phpMyAdmin-5.1.1-all-languages;

    location / {
    	index index.php index.html;
    }

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

#重启Nginx服务
[root@web01 ~]# systemctl restart nginx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 配置负载均衡

1.编写一份proxy负载均衡的配置文件,将请求调度到后端web节点

[root@proxy01 ~]# cat /etc/nginx/conf.d/proxy_php.com.conf
upstream php {
	server 172.16.1.7:80;
	server 172.16.1.8:80;
}

server {
    listen 80;
    server_name php.birenchong.cn;

    location /{
        proxy_pass http://php;
        include proxy_params;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

2检查语法并重载nginx

[root@proxy01 ~]# nginx -t
[root@proxy01 ~]# systemctl restart nginx
1
2

# 配置Redis服务

1.安装redis内存数据库

[root@db01 ~]# yum install redis -y
1

2.配置redis 监听在本地的内网网卡上

[root@db01 ~]# sed -i '/^bind/c bind 127.0.0.1 172.16.1.51' /etc/redis.conf
1

3.启动redis

[root@db01 ~]# systemctl start redis
[root@db01 ~]# systemctl enable redis
1
2

# 配置php连接Redis

1.修改/etc/php.ini文件。[所有节点都需要操作]

[root@web ~]# vim /etc/php.ini
session.save_handler = redis
session.save_path = "tcp://172.16.1.51:6379"
;session.save_path = "tcp://172.16.1.51:6379?auth=123”#如果redis存在密码,则使用该方式
1
2
3
4

2.注释php-fpm.d/www.conf里面的两条内容,否则session内容会一直写入/var/lib/php/session目录中,从而造成会话共享失败。[所有节点都需要操作]

[root@web ~]# vim /etc/php-fpm.d/www.conf
;php_value[session.save_handler] = files
;php_value[session.save_path]= /var/lib/php/session
1
2
3

3.重启php-fpm服务。[所有节点都需要操作]

[root@web ~]# php-fpm -t
[root@web ~]# systemctl restart php-fpm
1
2

# 测试集群会话共享

1.使用浏览器登陆网站,获取对应的cookie信息

2.检查redis中是否存在cookie对应的session信息

[root@db01 ~]# redis-cli
172.16.1.51:6379> keys*
1)"PHPREDIS_sESSION:393ff522ed2a7e26ba44f6d925f991f2"
172.16.1.51:6379>
1
2
3
4

3.此时用户的 cookie始终都不会发生任何变化,无论请求被负载调度到那一台后端web节点服务器都不会出现没有登陆情况。

#nginx
Last Updated: 2022/03/30, 11:09:09
Nginx反向代理
Rewrite重写

← Nginx反向代理 Rewrite重写→

最近更新
01
谷歌云创建GKE集群
07-26
02
ElastiCacheForRedis启用密码
07-26
03
upload-to-gcs
06-29
更多文章>
Theme by Vdoing | Copyright © 2021-2024 Brc | MIT License | 浙ICP备19031881号-4
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式