七层负载均衡和四层负载均衡

nginx七层负载均衡

【1】、为什么要使用负载均衡

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

image-20241212194051834

往往我们接触的最多的是 SLB(Server Load Balance) 负载均衡,实现最多的也是 SLB 、那么 SLB 它的调度节点和服务节点通常是在一个地域里面。那么它在这个小的逻辑地域里面决定了他对部分服务的实时性、响应性是非常好的。

所以说当海量用户请求过来以后,它同样是请求调度节点,调度节点将用户的请求转发给后端对应的服务节点,服务节点处理完请求后在转发给调度节点,调度节点最后响应给用户节点。这样也能实现一个均衡的作用,那么Nginx则是一个典型的 SLB

image-20241212194158222

四层负载均衡

所谓四层负载均衡指的是 OSI 七层模型中的传输层,那么传输层Nginx已经能支持TCP/IP的控制,所以只需要对客户端的请求进行TCP/IP协议的包转发就可以实现负载均衡,那么它的好处是性能非常快、只需要底层进行应用处理,而不需要进行一些复杂的逻辑。

七层负载均衡

七层负载均衡它是在应用层,那么它可以完成很多应用方面的协议请求,比如我们说的http应用的负载均衡,它可以实现http信息的改写、头信息的改写、安全应用规则控制、URL匹配规则控制、以及转发、rewrite等等的规则,所以在应用层的服务里面,我们可以做的内容就更多,那么Nginx则是一个典型的七层负载均衡 SLB

四层负载均衡与七层负载均衡区别

四层负载均衡数据包在底层就进行了分发,而七层负载均衡数据包则是在最顶层进行分发、由此可以看出,七层负载均衡效率没有四负载均衡高。

但七层负载均衡更贴近于服务,如:http协议就是七层协议,我们可以用Nginx可以作会话保持,URL路径规则匹配、head头改写等等,这些是四层负载均衡无法实现的。

注意:四层负载均衡不识别域名,七层负载均衡识别域名

【2】、nginx配置负载均衡场景

Nginx要实现负载均衡需要用到 proxy_pass 代理模块配置。

Nginx负载均衡与Nginx代理不同地方在于,Nginx的一个 location 仅能代理一台服务器,而Nginx负载均衡则是将客户端请求代理转发至一组upstream虚拟服务池。

image-20241212201039289

upstream web_ips {
    server 192.168.121.7;
    server 192.168.121.8;
}
server {
    listen 80;
    server_name www.test.com;
    location / {
        proxy_pass http://web_ips;
    }
}

【3】、nginx负载均衡典型故障

如果后台服务连接超时,Nginx是本身是有机制的,如果出现一个节点down掉的时候,Nginx会更据你具体负载均衡的设置,将请求转移到其他的节点上。

但是,如果后台服务连接没有down掉,但是返回错误异常码了如:504、502、500,这个时候你需要加一个负载均衡的设置,

如下:proxy_next_upstream http_500 http_502 http_503 http_504 http_404;意思是,当其中一台返回错误码404,500…等错误时,可以分配到下一台服务器程序继续处理,提高平台访问成功率。

upstream web_ips {
    server 192.168.121.7;
    server 192.168.121.8;
}
server {
    listen 80;
    server_name www.test.com;
    location / {
        proxy_pass http://web_ips;
        proxy_next_upstream http_500  http_502  http_503  http_504 http_404;
    }
}

【4】、负载均衡调度算法

面试题

调度算法 概述
rr(轮询) 按时间顺序逐一分配到不同的后端服务器(默认)
weight 加权轮询,weight值越大,分配到的访问几率越高
ip_hash 每个请求按访问IP的hash结果分配,这样来自同一IP的固定访问一个后端服务器
url_hash 按照访问URL的hash结果来分配请求,是每个URL定向到同一个后端服务器
least_conn 最少链接数,那个机器链接数少就分发
-- 轮询算法配置
upstream web_ips {
    server 192.168.121.7;
    server 192.168.121.8;
}
server {
    listen 80;
    server_name www.test.com;
    location / {
        proxy_pass http://web_ips;
        proxy_next_upstream http_500  http_502  http_503  http_504 http_404;
    }
}

-- 加权轮询算法配置
upstream web_ips {
    server 192.168.121.7  weight=3;
    server 192.168.121.8;
}
server {
    listen 80;
    server_name www.test.com;
    location / {
        proxy_pass http://web_ips;
        proxy_next_upstream http_500  http_502  http_503  http_504 http_404;
    }
}

-- ip_hash算法配置
-- 具体配置不能和weight一起使用。
upstream web_ips {
    ip_hash
    server 192.168.121.7;
    server 192.168.121.8;
}
server {
    listen 80;
    server_name www.test.com;
    location / {
        proxy_pass http://web_ips;
        proxy_next_upstream http_500  http_502  http_503  http_504 http_404;
    }
}

【5】、ngixn负载均衡后端服务器状态

状态 概述
down 当前的server暂时不参与负载均衡
backup 预留的备份服务器
max_fails 允许请求失败的次数
max_conns 限制最大的接收连接数
fail_timeout 经过max_fails失败后,服务暂停时间
upstream load_pass { 
    -- 不参与任何调度, 一般用于停机维护 
    server 10.0.0.7:80 down; 
}

【6】、nginx负载均衡健康检查

upstream web { 
    server 172.16.1.7:80 max_fails=2 fail_timeout=10s; 
    server 172.16.1.8:80 max_fails=2 fail_timeout=10s; 
    check interval=3000 rise=2 fall=3 timeout=1000 type=tcp;
}
server { 
    listen 80;
    server_name web.test.com; 
    location / { 
        proxy_pass http://web; 
        include proxy_params; 
    }
    location /upstream_check {
        check_status; 
    } 
}
#interval 检测间隔时间,单位为毫秒
#rise 表示请求2次正常,标记此后端的状态为up
#fall 表示请求3次失败,标记此后端的状态为down
#type 类型为tcp
#timeout 超时时间,单位为毫秒

image-20241212210330644

【6】、nginx负载均衡会话保持

在使用负载均衡的时候会遇到会话保持的问题,可通过如下方式进行解决。

1.使用nginx的 ip_hash ,根据客户端的IP,将请求分配到对应的IP上

2.基于服务端的 session 会话共享(NFS,MySQL,memcache,redis,file)

在解决负载均衡会话问题,我们需要了解 session 和 cookie 的区别。

浏览器端存的是 cookie 每次浏览器发请求到服务端时,报文头是会自动添加 cookie 信息的。

服务端会查询用户的 cookie 作为key去存储里找对应的value(session)

同意域名下的网站的 cookie 都是一样的,所以无论几台服务器,无论请求分配到哪一台服务器上同一用户的 cookie 是不变的。也就是说 cookie 对应的 session 也是唯一的。所以,这里只要保证多台业务服务器访问同一个共享存储服务器(NFS,MySQL,memcache,redis,file)就行了。

1、部署phpmyadmin

1.web01部署
[root@web01 conf.d]# cat admin.conf 
server {
        listen 80;
        server_name www.admin.com;
        root /code/admin;

        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;
        }
}

[root@web01 conf.d]# systemctl restart nginx
[root@web01 conf.d]# mkdir /code/admin
[root@web01 conf.d]# cd /code/admin

下载代码
[root@web01 admin]# wget https://files.phpmyadmin.net/phpMyAdmin/5.2.1/phpMyAdmin-5.2.1-all-languages.zip
解压代码
[root@web01 admin]# unzip phpMyAdmin-5.2.1-all-languages.zip

手动配置代码指向数据库
[root@web01 admin]# mv phpMyAdmin-5.2.1-all-languages/* .
[root@web01 admin]# mv config.sample.inc.php config.inc.php
[root@web01 admin]# grep 172.16.1.51 config.inc.php -n
30:$cfg['Servers'][$i]['host'] = '172.16.1.51';

image-20241212213936647

# 修改session会话目录的权限
[root@web01 admin]# chown www.www /var/lib/php/session
[root@web01 admin]# ll -d /var/lib/php/session
drwxrwx--- 2 www www 6 Dec  2 16:44 /var/lib/php/session
web02部署phpmyadmi
[root@web02 conf.d]# cat admin.conf
server {
        listen 80;
        server_name www.admin.com;
        root /code/admin;

        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;
        }
}
[root@web02 conf.d]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@web02 conf.d]# systemctl restart nginx

将web01的代码拷贝到web02
[root@web02 conf.d]# scp -r 10.0.0.7:/code/admin /code

修改存放会话的目录权限
[root@web02 conf.d]# chown www.www /var/lib/php/session
[root@web02 conf.d]# ll -d /var/lib/php/session
drwxrwx--- 2 www www 6 Dec  2 16:44 /var/lib/php/session

加入到负载均衡

[root@lb01 conf.d]# vim admin.conf
upstream admin {
upstream admin {
     server 172.16.1.7:80;
     server 172.16.1.8:80;
}
server {
        listen 80;
        server_name www.admin.com;

        location / {
        proxy_pass http://admin;
        include proxy_params;
        }
}                                                                                                   
"admin.conf" 13L, 191C written
[root@lb01 conf.d]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@lb01 conf.d]# systemctl restart nginx

由于没有做session共享和持久化,所以会一直卡在登录界面上

image-20241212215102825

2、配置redis

51服务器上部署redis服务
[root@db01 ~]# yum -y install redis

配置redis监听端口 默认127.0.0.1
[root@db01 ~]# vim /etc/redis/redis.conf
[root@db01 ~]# grep -n 172.16.1.51 /etc/redis/redis.conf
75:bind 127.0.0.1 172.16.1.51

启动redis
[root@db01 ~]# systemctl start redis
[root@db01 ~]# systemctl enable redis

登录查看
[root@db01 ~]# redis-cli 
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> quit

3、修改两台web会话写入到redis

web01配置
安装编译命令
yum install -y gcc glibc gcc-c++ pcre-devel openssl-devel patch
PHP安装redis插件  # 注意两台web都需要安装
第一步: 下载redis源码包
[root@web01:~]# wget http://pecl.php.net/get/redis-4.0.1.tgz
第二步: 解压代码
[root@web01:~]# tar xf redis-4.0.1.tgz 
第三步: 配置
[root@web01:~]#cd redis-4.0.1/
[root@web01 redis-4.0.1]# phpize   # 初始化
[root@web01:redis-4.0.1]#./configure
第四步: 编译安装
[root@web01:redis-4.0.1]# make && make install
第五步: 开启redis插件功能,配置文件增加以下一行内容
[root@web01:~]#grep redis.so /etc/php.ini  -n
1357:extension=redis.so
第六步: 重启服务
[root@web01:~]#systemctl restart php-fpm



[root@web01 ~]# awk 'NR==1222||NR==1255' /etc/php.ini
session.save_handler = redis
session.save_path = "tcp://172.16.1.51:6379"

注释files和 session的行
[root@web01 ~]# tail -4 /etc/php-fpm.d/www.conf
;php_value[session.save_handler] = files
;php_value[session.save_path]    = /var/lib/php/session
php_value[soap.wsdl_cache_dir]  = /var/lib/php/wsdlcache
;php_value[opcache.file_cache]  = /var/lib/php/opcache
重启生效

[root@web01 ~]# systemctl restart php-fpm


将web01配置好的文件同步给web02
[root@web01 ~]# rsync -avz /etc/php.ini 10.0.0.8:/etc/
[root@web01 ~]# rsync -avz /etc/php-fpm.d/www.conf  10.0.0.8:/etc/php-fpm.d/
[root@web02 ~]# systemctl restart php-fpm

image-20241213100546047

image-20241213100556814

# 查看redis中存储的session
127.0.0.1:6379> keys *
1) "PHPREDIS_SESSION:6ogr9kachp9uvu34e5r28mcltc"

4、获取客户端真实的IP地址

set_real_ip_from: 真实服务器上一级代理的IP地址或者IP地址段,可以写多行

real_ip_header: 从那个heare头检索出需要的IP地址

real_ip_recursive: 递归排除set_real_ip_from里出现的IP,没有出现的则为remote用户来源IP

配置代理服务器携带客户端真实的IP
[root@lb01 conf.d]# cat ../proxy_params 
proxy_set_header Host $http_host;
proxy_http_version 1.1;
proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;	# 携带客户端信息

配置之前,不会显示来源IP

image-20241213100944151

配置之后,就会显示客户端的IP了

image-20241213101053424

nginx四层负载均衡

四层负载均衡是基于传输层协议包来封装的(如:TCP/IP),那我们前面使用到的七层是指的应用层,他的组装在四层的基础之上,无论四层还是七层都是指的OSI网络模型。

1、四层+七层来做负载均衡,四层可以保证七层的负载均衡的高可用性;如:nginx就无法保证自己的服务高可用,需要依赖LVS或者keepalive。

2、如:tcp协议的负载均衡,有些请求是TCP协议的(mysql、ssh),或者说这些请求只需要使用四层进行端口的转发就可以了,所以使用四层负载均衡。

image-20241213202934077

四层负载总结

1、四层负载均衡仅能转发TCP/IP协议、UDP协议、通常用来转发端口,如:tcp/22、udp/53;

2、四层负载均衡可以用来解决七层负载均衡端口限制问题;(七层负载均衡最大使用65535个端口号)

3、四层负载均衡可以解决七层负载均衡高可用问题;(多台后端七层负载均衡能同事的使用)

4、四层的转发效率比七层的高得多,但仅支持tcp/ip协议,不支持http和https协议;

5、通常大并发场景通常会选择使用在七层负载前面增加四层负载均衡。

【1】、配置四层负载

搭建lb02

1.配置nginx仓库
[root@lb02 ~]# scp 192.168.121.5:/etc/yum.repos.d/nginx.repo /etc/yum.repos.d/
2.安装nginx服务
[root@lb02 ~]# yum -y install nginx
3.同步lb01的配置
[root@lb02 ~]# rsync -avz --delete 192.168.121.5:/etc/nginx/ /etc/nginx/

4.启动nginx
[root@lb02 conf.d]# systemctl start nginx
[root@lb02 conf.d]# systemctl enable nginx

配置四层负载

1.配置官网仓库
[root@lb ~]# scp 192.168.121.5:/etc/yum.repos.d/nginx.repo /etc/yum.repos.d/
2.安装nginx服务
[root@lb ~]# yum -y install nginx
3.配置四层负载
[root@lb ~]# cd /etc/nginx/
[root@lb conf.d]# rm -rf default.conf	# 删除应用层配置
配置四层需要再http区块外配置
[root@lb nginx]# cat nginx.conf 

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}

### 四层配置,不需要写http协议和location了
stream {
upstream web {
        server 192.168.121.5:80;
		server 192.168.121.6:80;
}
     server {
     listen 80;
     proxy_pass web;
     }

}
###########
http {
...

启动nginx服务
[root@lb nginx]# systemctl start nginx

# 注意浏览器缓存

【2】、配置路由转发

配置访问10.0.0.4的2222端口则转发给后端web01的22端口
vim nginx.conf
..
upstream web01 {
        server 172.16.1.7:22;
        }

     server {
     listen 2222;
     proxy_pass web01;
        }
...

[root@lb nginx]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@lb nginx]# systemctl restart nginx

测试

image-20241213223734156

【3】、动静分离

动静分离,通过中间件将动静分离和静态请求进行分离;

通过中间件将动态请求和静态请求分离,可以减少不必要的请求消耗,同时能减少请求的延时。

通过中间件将动态请求和静态请求分离,逻辑图如下

image-20241214101031912

动静分离只有好处:动静分离后,即使动态服务不可用,但静态资源不会受到影响。

我们这里使用tomcat配合nginx实现动静分离的配置

nginx解析静态图片,tomcat解析动态资源

1、单台实现动静分离

由于tomcat使用的是8080端口,nginx使用的是80端口,因此不存在端口冲突的问题

在web01上实现动静分离
1.安装java运行环境
[root@web01 ~]#  yum -y install java

2.安装tomcat web服务
https://tomcat.apache.org/  # tomcat的官网
[root@web01 ~]# wget https://dlcdn.apache.org/tomcat/tomcat-10/v10.1.34/bin/apache-tomcat-10.1.34.tar.gz

[root@web01 ~]# tar xf apache-tomcat-10.1.34.tar.gz -C /usr/local/

3.启动tomcat服务
[root@web01 ~]# /usr/local/apache-tomcat-10.1.34/bin/startup.sh

image-20241214102429926

# 配置反向代理
# tomcat 网站的根目录 /usr/local/apache-tomcat-10.1.34/webapps/ROOT/
# 我们配置反向代理,将tomcat的图片代理到本机的/images目录下面
[root@web01 conf.d]# vim tom.conf 
server {
        listen 80;
        server_name www.tom.com;
        location / {
        proxy_pass http://10.0.0.7:8080;
        }

        location ~ \.(svg|jpg|jpeg)$ {
        root /images;
        }
}
                                                                                            
[root@web01 conf.d]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@web01 conf.d]# systemctl restart nginx
[root@web01 conf.d]# mkdir /images

将图片拷贝到/images目录
[root@web01 conf.d]# cp /usr/local/apache-tomcat-10.1.34/webapps/ROOT/tomcat.svg /images/
[root@web01 conf.d]# ll /images/
total 68
-rw-r----- 1 root root 67795 Dec 13 11:35 tomcat.svg
# 修改目录的权限
[root@web01 ~]# chown www:www /images/ -R

浏览器访问测试
www.tom.com/tomcat.svg 应该显示tom猫的图片

2、多台机器实现动静分离

web02上的nginx解析静态资源

动态资源交给web01上的tomcat解析

web02上配置静态资源
WEB02配置
1.配置Nginx的静态页面 可以直接访问的一张苍姐姐图片即可
[root@web02 conf.d]# vim s.conf
server {
        listen 80;
        server_name www.s.com;

        location / {
        root /code/s;
        index index.html;
        }
}       
                                                 
[root@web02 conf.d]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@web02 conf.d]# systemctl restart nginx

[root@web02 conf.d]# mkdir /code/s
[root@web02 conf.d]# echo web02... > /code/s/index.html
上传31.png图片到s目录
[root@web02 conf.d]# cd /code/s
[root@web02 s]# ll 
total 180
-rw-r--r-- 1 root root 178803 Dec 10 11:27 31.png
-rw-r--r-- 1 root root      9 Dec 13 11:49 index.html

访问图片测试
www.s.com/31.png

image-20241214103807855

web02 上配置动态资源
修改默认的首页
[root@web01 ~]# cat /usr/local/apache-tomcat-10.1.34/webapps/ROOT/index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<HTML>
<HEAD>
<TITLE> JSP Page</TITLE>
</HEAD>
<BODY>
<%
Random rand = new Random();
out.println("<h1>随机数:<h1>");
out.println(rand.nextInt(99)+100);
%>
</BODY>
</HTML>

image-20241214104812090

# 配置负载均衡
[root@lb01 ~]# cd /etc/nginx/conf.d/
[root@lb01 conf.d]# cat ds.conf 
upstream static {
        server 192.168.121.8:80;
}
upstream dong {
        server 192.168.121.7:8080;
}
server {
        listen 80;
        server_name www.ds.com;
        location ~ \.png$ {
                proxy_pass http://static;
        }
        location ~ \.jsp$ {
                proxy_pass http://dong;
        }
}

image-20241214105654285

image-20241214105710963

3、负载均衡上整合动态和静态的html文件

[root@lb01 conf.d]# cat ds.conf 
upstream static {
        server 172.16.1.8:80;
}
upstream dong {
        server 172.16.1.7:8080;
}
server {
	listen 80;
	server_name www.ds.com;
        root /code;
        index index.html;

       location ~* \.(jpg|png|gif)$ {
       proxy_pass http://static;
       proxy_set_header Host $http_host;
       } 

       location ~ \.jsp {
       proxy_pass http://dong;
       proxy_set_header Host $http_host;
      }
}
[root@lb01 conf.d]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

[root@lb01 conf.d]# systemctl restart nginx

创建代码目录
[root@lb01 conf.d]# mkdir /code
整合资源
[root@lb01 conf.d]# cat /code/index.html
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>测试ajax和跨域访问</title>
		<script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
	</head>
	<script type="text/javascript">
		$(document).ready(function(){
			$.ajax({
				type: "GET",
				url: "http://www.ds.com/index.jsp",
				success: function(data){
					$("#get_data").html(data)
				},
				error: function() {
					alert("哎呦喂,失败了,回去检查你服务去~");
				}
			});
		});
	</script>
	<body>
		<h1>测试动静分离</h1>
		<img src="http://www.ds.com/tupian.png">
		<div id="get_data"></div>
	</body>
</html>

访问测试
www.s.com

image-20241214111347318

停掉nignx后不影响动态资源

[root@web02 conf.d]# systemctl stop nginx

image-20241214111517040

停止tomcat后不影响静态资源访问

[root@web01 ~]# /usr/local/apache-tomcat-10.1.34/bin/shutdown.sh 

image-20241214111608937

posted @ 2024-12-19 21:34  Linux小菜鸟  阅读(56)  评论(0编辑  收藏  举报