一、负载均衡
早期的网站流量和业务功能都比较简单,单台服务器足以满足基本的需求,但是随着互联网的发展,业务流量越来越大并且业务逻辑也跟着越来越复杂,单台服务器的性能及单点故障问题就凸显出来了,因此需要多台服务器进行性能的水平扩展及避免单点故障出现。负载均衡是将负载分摊到不同的服务单元,既保证服务的可用性,又保证响应足够快,给用户很好的体验,快速增长的访问量和数据流量催生了各式各样的负载均衡的产品,很多专业的的负载均衡硬件提供了很好的功能,但价格不菲,这使得负载均衡软件大受欢迎,nginx
就是其中一个,在
linux
下有nginx、
Ivs
、
haproxy
等服务,可以提供复杂均衡服务。
二、负载均衡原理
负载均衡
NAT
(
Network Address Translation
网络地址转换)简单地说就是将一个IP
地址转换为另一个
IP
地址,一般用于未经注册的内部地址与合法的、已获注册的Internet IP
地址间进行转换。适用于解决
Internet IP
地址紧张、不想让网络外部知道内部网络结构等的场合下。系统的扩展可以分为纵向扩展和横向扩展。
纵向扩展:从单机的角度出发,通过增加系统的硬件处理能力来提升服务器的处理能力;
横向扩展:通过添加机器来满足大型网站服务的处理能力。
![](https://i-blog.csdnimg.cn/direct/c21cd47cf83c4ee5ac87865bb925d003.png)
这里面涉及到两个重要的角色分别是
“
应用集群
”
和
“
负载均衡器
应用集群:将同一应用部署到多台机器上,组成处理集群,接收负载均衡设备分发的请求,进行处理并返回响应的数据。
负载均衡器:将用户访问的请求根据对应的负载均衡算法,分发到集群中的一台服务器进行处理。
三、负载均衡的作用
解决服务器的高并发压力,提高应用程序的处理性能;
提供故障转移,实现高可用;
通过添加或减少服务器数量,增强网站的可扩展性;
在负载均衡器上进行过滤,可以提高系统的安全性;
1
、提高系统性能
负载均衡可以扩展网络设备和服务器的带宽,优化访问请求在服务器组之间 的分配,提高系统的反应速度和总体性能。
2
、监控服务器的运行状态
负载均衡能够监控服务器的运行状态,提高整个服务器组的可靠性。
3
、提供服务一致性
负载均衡器具有提供服务一致性的功能,负载均衡器通过读取客户端所发出请求内的信息,进行重写报头程序然后将请求发送至合适的服务器上,该服务器会维护着该客户端信息。在http
通信当中,负载均衡器提供服务一致性的功能就得到了很好的发挥,但提供该服务的途径并不是非常安全。但若将消息加密后,负载均衡器就无法读取隐藏其中的信息了。
4
、摆脱停机时间
服务器托管公司可能会在维护期间将服务器关闭一段时间,这可能发生在业务的高峰期。在基于云服务器中,可以在将流量引导到另一台服务器的资源之后进行维护,前提是它们不在维护中,从而可以消除网站的停机时间。
5
、管理服务器故障
由于它具有根据需要添加或删除实例的功能,因此可以跨云平台拥有多个数据中心。如果其中一台服务器发生故障,则可以快速移动流量,将故障服务器的流量流入到另一台服务器中。
6
、转发功能
按照一定的算法,将客户端请求转发到不同应用服务器上,减轻单个服务器压力,提高系统并发量。
7
、恢复添加
如检测到发生故障的应用服务器恢复工作,自动将其添加到处理用户请求队伍中。
8
、分发流量
分发流量、请求到不同的服务器。使流量平均分配,提高整个集群的响应速度、服务的高可用性。四、负载均衡常用处理方式
负载均衡分为四层负载均衡和七层负载均衡。
1.
四层负载均衡是工作在
OSI
七层协议的第四层
——
传输层,基于IP+PORT的负载均衡,主要工作是转发。
2.
它在接收到客户端的流量以后通过修改数据包的地址信息(目标地址和端口和源地址)将流量转发到应用服务器。
3.
实现四层负载均衡的方式:
硬件:
F5
、
BIG-IP
、
Radware
等
;
软件:
LVS
、
Nginx
、
Haproxy
等。
1.
七层负载均衡是工作在七层协议的第七层
-
应用层,基于虚拟的
URL
或主机IP
的负载均衡,主要工作是代理。
2.
它首先会与客户端建立一条完整的连接并将应用层的请求流量解析出来,再按照调度算法选择一个应用服务器,并与应用服务器建立另外一条连接将请求发送过去。
3.
实现七层负载均衡的方式:
软件:
Nginx
、
Hayproxy
等。
五、四层和七层负载均衡的区别
1.
四层负载均衡数据包是在底层就进行了分发,而七层负载均衡数据包则最顶端进行分发,所以四层负载均衡的效率比七层负载均衡的效率要高;
2.
四层负载均衡不识别域名,而七层负载均衡识别域名。
3.
除了四层和七层负载均衡以外其实还有二层、三层负载均衡。二层负载均衡是在数据链路层基于MAC
地址来实现负载均衡,三层是在网络层一般采用虚拟IP
地址的方式实现负载均衡。
4.
实际环境采用的方式:四层负载
(LVS) +
七层负载
(Nginx)
六、
nginx
七层负载均衡
1
、七层负载均衡基础配置
[root@server]# vim /usr/local/nginx/conf/nginx.conf
worker_processes 1;
event {
worker_connections 1024;
}
http { # 七层负载均衡支持http、ftp协议
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream qicengzu { # 服务器组,组名qingcengzu
server 192.168.33.11:8080; # 组内服务器1
server 192.168.33.22:8080; # 组内服务器2
}
server { # 虚拟服务器
listen 80; # 虚拟服务器端口
server_name localhost; # 虚拟服务器名
location { # 虚拟服务器的url跳转
proxy_pass http://qicengzu;
# 当访问本机的80端口时,跳转到服务器组
}
}
}
2
、负载均衡状态
![](https://i-blog.csdnimg.cn/direct/9ad5787da6c74766af865a3d49daab66.png)
在服务器组的组内服务器后填写该服务器的状态,如
[root@server]# vim /usr/local/nginx/conf/nginx.conf
......省略部分内容......
upstream qicengzu { # 服务器组,组名qingcengzu
server 192.168.33.11:8080 down; # 停止
此服务器负载均衡
server 192.168.33.22:8080 backup; # 该服
务器作为其他组内服务器的备份服务器
server 192.168.....
}
......省略部分内容......
3
、负载均衡策略
![](https://i-blog.csdnimg.cn/direct/144efe42ff5e4d32831cd55a96784226.png)
(
1
)轮询
upstream backend {
server 192.168.33.11:8080;
server 192.168.33.22:8080;
}
(
2
)
weight
加权
upstream backend {
server 192.168.33.11:8080 weight=5;
server 192.168.33.22:8080 weight=2; # 权重默认为
1,谁权重大,谁优先处理请求
}
(
3
)
ip_hash
当对后端的多台动态应用服务器做负载均衡时,
ip_hash
指令能够将某个客户端IP
的请求通过哈希算法定位到同一台后端服务器上。
这样,当来自某一个
IP
的用户在后端
Web
服务器
A
上登录后,再访问该站点的其他URL
,能保证其访问的还是后端
web
服务器
A
。
注意
:
使用
ip_hash
指令无法保证后端服务器的负载均衡,可能导致有些后端服务器接收到的请求多,有些后端服务器接受的请求少,而且设置后端服务器权重等方法将不起作用
upstream backend {
ip_hash; # ip_hash算法
server 192.168.33.11:8080;
server 192.168.33.22:8080;
}
(
4
)
least_conn
least_conn
:最少连接,把请求转发给连接数较少的后端服务器。轮询算法是把请求平均地转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况
下,
leastconn
这种方式就可以达到更好的负载均衡效果。
upstream backend {
least_conn; # 将请求转发给连接数较少的后端服务器
server 192.168.33.11:8080;
server 192.168.33.22:8080;
}
(
5
)
url_hash
按访问
url
的
hash
结果来分配请求,使每个
url
定向到同一个后端服务器,要配合缓存命中来使用。同一个资源多次请求,可能会到达不同的服务器上,导致不必要的多次下载,缓存命中率不高,以及一些资源时间的浪费。而使用ur_hash
,可以使得同一个
url (
也就是同一个资源请求)
会到达同一台服务器,一旦缓存住了资源,再次收到请求,就可以
缓存中读取。
upstream backend {
hash $request_uri;
server 192.168.33.11:8080;
server 192.168.33.22:8080;
}
七、
nginx
四层负载均衡
四层使用
stream
模块,与七层的
http
模块同级。
[root@localhost ~]# nginx -V # 查看版本及安装模块
nginx version: nginx/1.22.1
built by gcc 8.5.0 20210514 (Red Hat 8.5.0-16) (GCC)
built with OpenSSL 1.1.1k FIPS 25 Mar 2021TLS SNI support
enabled
configure arguments: --prefix=/usr/local/nginx --
user=nginx --group=nginx--with-httpssl module --withhttp_stub status_module --with-http_realip module
[root@localhost ~]# cp /usr/local/nginx/sbin/nginx
/usr/local/nginx/sbin/nginxbak #将原
有/usr/local/nginx/sbin/nginx进行备份
[root@localhost ~]# cd /usr/src/nginx-1.22.1/
[root@localhost nginx-1.22.1]# Is
auto CHANGES CHANGES.ru configure html Makefile objs
conf contrib LICENSE man README src
[root@localhost nginx-1.22.1]# ./configure --
prefix=/usr/local/nginx --user=nginx --group=nginx --withhttp_ssl_module --with-http_stub_status_module --withhttp_realip_module --with-stream # 安装指定模块
[root@localhost nginx-1.22.1]# make # 进行编译
[root@localhost nginx-1.22.1]# cp ./objs/nginx
/usr/local/nginx/sbin/ # 将obis下面的nginx移动
到/usr/local/nginx/sbin下
[root@localhost nginx-1.22.1]# nginx -V # 模块添加成功
nginx version: nginx/1.22.1
built by gcc 8.5.0 20210514 (Red Hat 8.5.0-16) (GCC)
built with OpenSSL 1.1.1k FIPS 25 Mar 2021TLS SNI support
enabled
configure arguments: --prefix=/usr/local/nginx --
user=nginx --group=nginx--with-httpssl module --withhttp_stub status_module --with-http_realip module --withstream
[root@server ~]# vim /usr/local/nginx/conf/nginx.conf
events {
worker_connections 1024;
}
stream {
upstream dongtai { # 配置dongtai服务器组
server 192.168.33.11:8080; # 动态资源走tomcat的
8080端口
server 192.168.33.22:8080;
}
server {
listen 81; # 设置监听端口
proxy_pass dongtai; # 当请求访问到本机的81端口时,
将请求转发到dongtai组
}
upstream jingtai { # 配置jingtai服务器组
server 192.168.33.33:80; # 静态资源走nginx或
tomcat的80端口
server 192.168.33.44:80;
}
server {
listen 82;
proxy_pass jingtai;
}
}
:wq
八、nginx软件平滑升级
不停用业务,使用平滑升级
需要有
kill
命令的支持
kill不仅仅用于杀死进程,还可以向软件进程发送信号
![](https://i-blog.csdnimg.cn/direct/d20c84e05622487f917f02d758c716a7.png)
常用的
-9
和
-15
一个是强杀,一个是正常杀
kill
信号 进程编号
-USR2
平滑启动一个进程,平滑升级
-WINCH
优雅关闭子进程
-QUIT
优雅关闭主进程
步骤
1.
不停止原有服务,但是必须使用原生方式启动或者更改
nginx
脚本(会创
建一个新的进程)
2.
重新编译
nginx
新版本
3.
使用
kill -USR@
启动新版本
4.
把旧的
Nginx
子进程全部退出
5.
优雅的退出
Nginx
的老进程 系统就只剩下新的
nginx
了
使用原生方式启动
nginx
# 重新加载nginx配置文件
sbin/nginx -c /usr/local/nginx/conf/nginx.conf
查看进程,分主进程和
work
进程
# 查看进程
[root@front logs]# ps -aux|grep nginx
root 1277 0.0 0.1 46128 1156 ? Ss 7月29
0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 1278 0.0 0.2 46584 2148 ? S 7月29
0:00 nginx: worker process
root 1405 0.0 0.0 112828 988 pts/1 R+ 00:10
0:00 grep --color=auto nginx
上传新的版本并且解压
root@front logs]# cd
[root@front ~]# ls
anaconda-ks.cfg initserver.sh nginx-1.26.1 nginx-
1.26.1.tar.gz
[root@front ~]# wget https://nginx.org/download/nginx-
1.27.0.tar.gz
--2024-07-30 00:16:33-- https://nginx.org/download/nginx-
1.27.0.tar.gz
正在解析主机 nginx.org (nginx.org)... 52.58.199.22,
3.125.197.172, 2a05:d014:5c0:2601::6, ...
正在连接 nginx.org (nginx.org)|52.58.199.22|:443... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:1244887 (1.2M) [application/octet-stream]
正在保存至: “nginx-1.27.0.tar.gz”
100%
[=========================================================
=============>] 1,244,887 115KB/s 用时 7.6s
2024-07-30 00:16:42 (160 KB/s) - 已保存 “nginx-
1.27.0.tar.gz” [1244887/1244887])
[root@front ~]# ls
anaconda-ks.cfg initserver.sh nginx-1.26.1 nginx-
1.26.1.tar.gz nginx-1.27.0.tar.gz
[root@front ~]# tar -zxvf nginx-1.27.0.tar.gz
nginx-1.27.0/
...省略
nginx-1.27.0/man/nginx.8
[root@front ~]# ls
anaconda-ks.cfg initserver.sh nginx-1.26.1 nginx-
1.26.1.tar.gz nginx-1.27.0 nginx-1.27.0.tar.gz
对新版本进行编译安装,安装目录必须和旧版本一致
[root@front ~]# cd nginx-1.27.0/
[root@front nginx-1.27.0]# ./configure --
prefix=/usr/local/nginx --user=nginx --group=nginx --withhttp_ssl_module --with-http_stub_status_module --withhttp_realip_module --with-stream
[root@front nginx-1.27.0]# make && make install
使用
kill -USR2
启用新版本的
Nginx
的软件
kill -USR2 老版本的pid编号
主要功能会根据上一次的启动方式再重新运行一次之前的启动命令
![](https://i-blog.csdnimg.cn/direct/339755d3ce2b44908265b9263a9445c1.png)
重装新的版本以后,会出现新的启动工具
[root@front nginx-1.27.0]# /usr/local/nginx/sbin/nginx -v
nginx version: nginx/1.27.0
[root@front nginx-1.27.0]# /usr/local/nginx/sbin/nginx.old
-v
nginx version: nginx/1.26.1
再次查看进程,找到老版本的
pid
[root@front nginx-1.27.0]# ps -ef|grep nginx
root 1277 1 0 7月29 ? 00:00:00 nginx:
master process /usr/local/nginx/sbin/nginx
nginx 1278 1277 0 7月29 ? 00:00:00 nginx:
worker process
root 4412 1281 0 00:33 pts/1 00:00:00 grep --
color=auto nginx
# 使用老的nginx进程创建新的进程
[root@front nginx-1.27.0]# kill -USR2 1277
[root@front nginx-1.27.0]# ps -ef|grep nginx
root 1277 1 0 7月29 ? 00:00:00 nginx:
master process /usr/local/nginx/sbin/nginx
nginx 1278 1277 0 7月29 ? 00:00:00 nginx:
worker process
root 4413 1277 0 00:34 ? 00:00:00 nginx:
master process /usr/local/nginx/sbin/nginx
nginx 4414 4413 0 00:34 ? 00:00:00 nginx:
worker process
root 4418 1281 0 00:34 pts/1 00:00:00 grep --
color=auto nginx
此时会出现两套
master
进程,这个时候处理客户请求的就是新的
nginx
服务
了
关闭老版本的所有子进程
关闭老版本的主进程
[root@front nginx-1.27.0]# kill -WINCH 1278
[root@front nginx-1.27.0]# kill -QUIT 1277
[root@front nginx-1.27.0]# ps -ef|grep nginx
root 4413 1 0 00:34 ? 00:00:00 nginx:
master process /usr/local/nginx/sbin/nginx
nginx 4414 4413 0 00:34 ? 00:00:00 nginx:
worker process
root 4424 1281 0 00:40 pts/1 00:00:00 grep --
color=auto nginx
使用
curl
查看当前服务器的版本
[root@front nginx-1.27.0]# curl -I localhost
HTTP/1.1 403 Forbidden
Server: nginx/1.27.0
Date: Mon, 29 Jul 2024 16:42:32 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 153
Connection: keep-alive