七层负载均衡和四层负载均衡
nginx七层负载均衡
【1】、为什么要使用负载均衡
当我们的Web服务器直接面向用户,往往要承载大量并发请求,单台服务器难以负荷,我使用多台Web服务器组成集群,前端使用 Nginx 负载均衡,将请求分散的打到我们的后端服务器集群中,实现负载的分发。那么会大大提升系统的吞吐率、请求性能、高容灾
往往我们接触的最多的是 SLB(Server Load Balance) 负载均衡,实现最多的也是 SLB 、那么 SLB 它的调度节点和服务节点通常是在一个地域里面。那么它在这个小的逻辑地域里面决定了他对部分服务的实时性、响应性是非常好的。
所以说当海量用户请求过来以后,它同样是请求调度节点,调度节点将用户的请求转发给后端对应的服务节点,服务节点处理完请求后在转发给调度节点,调度节点最后响应给用户节点。这样也能实现一个均衡的作用,那么Nginx则是一个典型的 SLB
四层负载均衡
所谓四层负载均衡指的是 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虚拟服务池。
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 超时时间,单位为毫秒
【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';
# 修改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共享和持久化,所以会一直卡在登录界面上
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
# 查看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
配置之后,就会显示客户端的IP了
nginx四层负载均衡
四层负载均衡是基于传输层协议包来封装的(如:TCP/IP),那我们前面使用到的七层是指的应用层,他的组装在四层的基础之上,无论四层还是七层都是指的OSI网络模型。
1、四层+七层来做负载均衡,四层可以保证七层的负载均衡的高可用性;如:nginx就无法保证自己的服务高可用,需要依赖LVS或者keepalive。
2、如:tcp协议的负载均衡,有些请求是TCP协议的(mysql、ssh),或者说这些请求只需要使用四层进行端口的转发就可以了,所以使用四层负载均衡。
四层负载总结
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
测试
【3】、动静分离
动静分离,通过中间件将动静分离和静态请求进行分离;
通过中间件将动态请求和静态请求分离,可以减少不必要的请求消耗,同时能减少请求的延时。
通过中间件将动态请求和静态请求分离,逻辑图如下
动静分离只有好处:动静分离后,即使动态服务不可用,但静态资源不会受到影响。
我们这里使用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
# 配置反向代理
# 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
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>
# 配置负载均衡
[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;
}
}
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
停掉nignx后不影响动态资源
[root@web02 conf.d]# systemctl stop nginx
停止tomcat后不影响静态资源访问
[root@web01 ~]# /usr/local/apache-tomcat-10.1.34/bin/shutdown.sh
本文来自博客园,作者:Linux小菜鸟,转载请注明原文链接:https://www.cnblogs.com/xuruizhao/p/18617971