定义

负载均衡

将最前端的访问负载分摊到多个后端服务器中,具有高并发、伸缩性、高可用和安全防护的特性

集群

相互独立的节点组成的一个较大的计算机服务系统,每个集群节点都是运行各自服务的独立服务器,可以彼此通信,共享数据

联系

用keepalived来保证集群高可用,通常结合负载均衡来实现,比如Nginx+keepalived,LVS-DR+keepalived,MySQL+keepalived

包含内容

常见负载均衡:Nginx负载均衡、LVS负载均衡、Tomcat负载均衡

常见集群:Mysql、Redis、Rabbitmq的集群模式

Nginx

Nginx作为反向代理服务器,隐藏了真实的服务器,把请求分转发到真实提供服务的各台服务器。负载均衡就是用代理的方法去实现的,分摊流量到多台内容一致的服务器

LVS

Linux virtual server,由ipvsadm(用户空间)和ipvs(内核空间)组成,ipvs工作于INPUT链上,若有请求报文被ipvs事先定义,则根据其特定的模型进行修改,再转发到POSTROUTING链上送出TCP/IP协议栈。

Tomcat

作为Java容器,也叫web中间件,Nginx处理静态,Tomcat处理动态程序,结合Nginx做单机多实例的负载均衡

MySQL

用多台机器向外提供同一个服务,共享数据,mysql第三方集群:galera

Redis

Redis集群是一个由多个主从节点群组成的分布式服务集群,无中心,具有复制、高可用和分片特性,不需要sentinel哨兵也能完成节点移除和故障转移的功能。

Rabbitmq

生产者发送的消息被缓存到RabbitMQ中,生产者不需要等待消息被消费就可以继续执行,提高生产者的效率。RabbitMQ可以在多个消费者之间分配消息,实现负载均衡。他的镜像集群模式属于高可用模式,每次写消息到 queue 的时候,都会自动把消息到多个实例的 queue 里进行消息同步。

修改配置

Nginx

#反向代理(一个)
#Nginx1.24的配置文件位置:/etc/nginx/conf.d/default.conf
#Nginx1.20在主配置文件修改:/etc/nginx/nginx.conf

vim /etc/nginx/conf.d/default.conf
server {
    server {
    listen       80;
    server_name  localhost;

    location / {
    proxy_pass http://IP; #真实后端服务器地址,可以是ip或域名
    proxy_redirect default;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_connect_timeout 30;
    proxy_send_timeout 60;
    proxy_read_timeout 60;
    }
}


#负载均衡(多个)
#位置跟上面一样

vim /etc/nginx/conf.d/default.conf
upstream testapp { 
      server IP:port   weight=1;       # IP为真实服务器地址,testapp可以是任意名字
      server IP:port   weight=2;
      
    }
server {
        ....
        location / {         
           proxy_pass  http://testapp;  #请求转向 testapp 定义的服务器列表         
        }

LVS(DR模式)

#分发器上操作
yum install -y ipvsadm          #先安装ipvsadm
service ipvsadm start
ip a a dev ens33 VIP/32    #设置VIP,访问的虚拟IP
ipvsadm -C                      #清除内核虚拟服务器表中的所有记录。
ipvsadm -A -t VIP:port -s rr 	#指定轮询转发
ipvsadm -a -t VIP:port -r RIP1 -g   #指定转发的RIP1
ipvsadm -a -t VIP:port -r RIP2 -g   #指定转发的RIP2
ipvsadm -S > /etc/sysconfig/ipvsadm  #保存方式,保存到一个文件中
ipvsadm -ln                #查看IP转发和轮询

-A:添加VIP
-t:用的是tcp协议
-a:添加的是lo网卡的vip地址
-r:转发到realserverip
-s:算法
-L|-l –list #显示内核虚拟服务器表
--numeric, -n:#以数字形式输出地址和端口号
-g --gatewaying #指定LVS工作模式为直接路由器模式(也是LVS默认的模式)
-S -save #保存虚拟服务器规则到标准输出,输出为-R 选项可读的格式
rr:轮循
#如果添加ip错了,删除命令如下:
ip a del IP dev ens33


#rs上操作
ip a a dev lo VIP/32                #在lo网卡接口上绑定VIP
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore     #忽略arp广播
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce   #匹配精确ip地址回包

Tomcat

#tomcat单机多实例负载均衡配置
#先安装单实例Tomcat
tar -xzvf apache-tomcat-8.5.88.tar.gz -C /usr/local/
ln -s /usr/local/apache-tomcat-8.5.88/ /usr/local/tomcat
或者:# mv  /usr/local/apache-tomcat-8.5.88/ /usr/local/tomcat

#定义Tomcat所需环境变量
vim /etc/profile
CATALINA_HOME=/usr/local/tomcat	      #Tomcat安装目录(基准、工作)
export CATALINA_HOME

source /etc/profile

/usr/local/tomcat/bin/version.sh      #查看tomcat版本
/usr/local/tomcat/bin/startup.sh      #启动Tomcat
/usr/local/tomcat/bin/shutdown.sh	  #关闭tomcat


#再此基础上部署多实例,对应的实例生成的目录和端口如下
instance1: /usr/local/tomcat/instance1/{conf,logs,temp,work}       8081     8091
instance2: /usr/local/tomcat/instance2/{conf,logs,temp,work}       8082     8092
instance3: /usr/local/tomcat/instance3/{conf,logs,temp,work}       8083     8093


/usr/local/tomcat/bin/shutdown.sh        #先关闭原来的Tomcat实例
mkdir /usr/local/tomcat/instance{1..3}   #创建多实例的目录并拷贝配置、日志、temp和work目录
cp -r /usr/local/tomcat/{conf,logs,temp,work}   /usr/local/tomcat/instance1/
cp -r /usr/local/tomcat/{conf,logs,temp,work}   /usr/local/tomcat/instance2/
cp -r /usr/local/tomcat/{conf,logs,temp,work}   /usr/local/tomcat/instance3/

#配置每个实例的server.xml,把端口和基准目录修改为对应的
#实例1配置修改为:
vim /usr/local/tomcat/instance1/conf/server.xml

<Server port="8091" shutdown="SHUTDOWN">
<Connector port="8081" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    
<!--  <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> --> 
#直接将8009端口这一行注释掉	tomcat8.5.88这个是注释的,可以不动他  
    
    
<Host name="localhost"  appBase="/usr/local/tomcat/webapps"   //修改网站基准目录
            unpackWARs="true" autoDeploy="true">
   

#实例2配置修改为:
vim /usr/local/tomcat/instance2/conf/server.xml    
<Server port="8092" shutdown="SHUTDOWN">
<Connector port="8082" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    
<!--  <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> --> 
    
<Host name="localhost"  appBase="/usr/local/tomcat//webapps"
            unpackWARs="true" autoDeploy="true">    
    
    
#实例3配置修改:
vim /usr/local/tomcat/instance3/conf/server.xml    
<Server port="8093" shutdown="SHUTDOWN">
<Connector port="8083" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    
<!--  <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> --> 

<Host name="localhost"  appBase="/usr/local/tomcat//webapps"
            unpackWARs="true" autoDeploy="true">

#利用原来的Tomcat编写启动脚本
#vim /usr/local/tomcat/instance1/ins1.sh
#!/bin/bash
. /etc/init.d/functions
export CATALINA_BASE="/usr/local/tomcat/instance1"
case "$1" in
start)
        $CATALINA_HOME/bin/startup.sh;;
stop)
        $CATALINA_HOME/bin/shutdown.sh;;
restart)
        $CATALINA_HOME/bin/shutdown.sh
        sleep 5
        $CATALINA_HOME/bin/startup.sh;;
esac
export JAVA_OPTS='-Xms64m -Xmx128m'
# chmod a+x   /usr/local/tomcat/instance1/ins1.sh


#vim /usr/local/tomcat/instance2/ins2.sh
#!/bin/bash
. /etc/init.d/functions
export CATALINA_BASE="/usr/local/tomcat/instance2"
case "$1" in
start)
        $CATALINA_HOME/bin/startup.sh;;
stop)
        $CATALINA_HOME/bin/shutdown.sh;;
restart)
        $CATALINA_HOME/bin/shutdown.sh
        sleep 5
        $CATALINA_HOME/bin/startup.sh;;
esac
export JAVA_OPTS='-Xms64m -Xmx128m'
# chmod a+x   /usr/local/tomcat/instance2/ins2.sh


# vim /usr/local/tomcat/instance3/ins3.sh
#!/bin/bash
. /etc/init.d/functions
export CATALINA_BASE="/usr/local/tomcat/instance3"
case "$1" in
start)
        $CATALINA_HOME/bin/startup.sh;;
stop)
        $CATALINA_HOME/bin/shutdown.sh;;
restart)
        $CATALINA_HOME/bin/shutdown.sh
        sleep 5
        $CATALINA_HOME/bin/startup.sh;;
esac
export JAVA_OPTS='-Xms64m -Xmx128m'

#添加执行权限
# chmod a+x   /usr/local/tomcat/instance3/ins1.sh
# chmod a+x   /usr/local/tomcat/instance3/ins2.sh
# chmod a+x   /usr/local/tomcat/instance3/ins3.sh

#陆续启动
/usr/local/tomcat/instance1/ins1.sh start
/usr/local/tomcat/instance2/ins2.sh start
/usr/local/tomcat/instance3/ins3.sh start

MySQL

#准备环境
#主机解析
cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
IP1 galera1
IP2 galera2
IP3 galera3
IP4 galera4

#关闭防火墙和selinux

#下载和安装Galera(每台都需要安装)
配置yum源
vim /etc/yum.repos.d/galera.repo 
[galera]
name=galera
baseurl=http://releases.galeracluster.com/mysql-wsrep-5.7/centos/7/x86_64/
enabled=1
gpgcheck=0
    
yum -y install epel*  #需要epel源提供galera包
yum install mysql-wsrep-5.7.x86_64 galera  rsync -y
systemctl start mysqld
mysqladmin -u root -p'2rttwxb?3_oP' password '新密码'   #修改密码
mysql -u root -p'新密码'
mysql> grant all on *.* to 'syncuser'@'%' identified by '设置密码';

#修改每台机器的配置文件,逐一启动
#galera1
vim /etc/my.cnf   #追加以下内容
server-id=1
binlog_format=row
innodb_file_per_table=1
innodb_autoinc_lock_mode=2
wsrep_on=ON
wsrep_provider=/usr/lib64/galera/libgalera_smm.so
wsrep_cluster_name='galera'
wsrep_cluster_address='gcomm://'
wsrep_node_name='galera1'
wsrep_node_address='IP1'
wsrep_sst_auth=syncuser:'mysql同步账户的密码'
wsrep_sst_method=rsync

systemctl  restart mysqld         #重启服务

#galera2
vim /etc/my.cnf   #追加以下内容
server-id=2
binlog_format=row
innodb_file_per_table=1
innodb_autoinc_lock_mode=2
wsrep_on=ON
wsrep_provider=/usr/lib64/galera/libgalera_smm.so
wsrep_cluster_name='galera'
wsrep_cluster_address='gcomm://galera1'
wsrep_node_name='galera2'
wsrep_node_address='IP2'
wsrep_sst_auth=syncuser:'mysql同步账户的密码'
wsrep_sst_method=rsync

systemctl  restart mysqld         #重启服务

#galera3
vim /etc/my.cnf   #追加以下内容
server-id=3
binlog_format=row
innodb_file_per_table=1
innodb_autoinc_lock_mode=2
wsrep_on=ON
wsrep_provider=/usr/lib64/galera/libgalera_smm.so
wsrep_cluster_name='galera'
wsrep_cluster_address='gcomm://galera1,galera2'
wsrep_node_name='galera3'
wsrep_node_address='IP3'
wsrep_sst_auth=syncuser:'mysql同步账户的密码'
wsrep_sst_method=rsync

systemctl  restart mysqld         #重启服务

#galera4
vim /etc/my.cnf   #追加以下内容
server-id=4
binlog_format=row
innodb_file_per_table=1
innodb_autoinc_lock_mode=2
wsrep_on=ON
wsrep_provider=/usr/lib64/galera/libgalera_smm.so
wsrep_cluster_name='galera'
wsrep_cluster_address='gcomm://galera1,galera2,galera3'
wsrep_node_name='galera4'
wsrep_node_address='IP4'
wsrep_sst_auth=syncuser:'mysql同步账户的密码'
wsrep_sst_method=rsync

systemctl  restart mysqld         #重启服务

Redis

#环境准备
#所有机器关闭防火墙和selinux,修改一下主机名
hostnamectl set-hostname redis-cluster1	
hostnamectl set-hostname redis-cluster2
hostnamectl set-hostname redis-cluster3

vim /etc/hosts      #所有机器做好hosts解析,添加以下内容
IP1 redis-cluster1
IP2 redis-cluster2
IP3 redis-cluster3

#安装redis
yum update -y                          #更新源
yum install -y centos-release-scl      #安装scl源
yum install -y devtoolset-9-toolchain  #安装gcc工具链
scl enable devtoolset-9 bash           #临时覆盖旧版本gcc引用,针对本次会话有效
echo "source /opt/rh/devtoolset-9/enable"  >>/etc/profile
source  /etc/profile                   #为了避免需要再次激活devtoolset-9使其长期有效
gcc -v                                 #查看gcc版本

#下载redis压缩包
wget http://download.redis.io/releases/redis-7.0.11.tar.gz
tar -xzvf redis-7.0.11.tar.gz  -C /usr/local/
mv  /usr/local/redis-7.0.11   /usr/local/redis
cd /usr/local/redis/
make && make install

mkdir /data/redis/data -p    #创建存放数据的目录
#创建节点目录:按照规划在每台redis节点的安装目录中创建对应的目录,以端口号命名
cd /data/redis
mkdir cluster             #创建集群目录
mkdir cluster/{7000,7001} #机器1创建节点目录,机器2和3类似,文件名字陆续为7002-7005

#拷贝配置文件到节点目录中,三台机器相同操作,机器2和3类似,文件名字陆续为7002-7005
cp /usr/local/redis/redis.conf 7000/
cp /usr/local/redis/redis.conf 7001/

#修改集群每个redis配置文件。(主要是端口、ip、pid文件,三台机器相同操作),机器1为例,修改如下:
cd 7000/
cp redis.conf{,.bak}
vim redis.conf      #修改如下
bind IP1            #每个实例的配置文件修改为对应节点的ip地址
port 7000           #监听端口,运行多个实例时,需要指定规划的每个实例不同的端口号
daemonize yes       #redis后台运行
pidfile /var/run/redis_7000.pid   #pid文件,运行多个实例时,需要指定不同的pid文件
logfile /var/log/redis_7000.log   #日志文件位置,运行多实例时,需要将文件修改的不同。
dir /data/redis/data              #存放数据的目录
appendonly yes                    #开启AOF持久化
appendfilename "appendonly.aof"   #AOF文件名称
appendfsync everysec              #表示对写操作进行累积,每秒同步一次
protected-mode no	              #受保护模式,默认是yes开启的,将它修改成no

#以下为打开注释并修改:
cluster-enabled yes                 #启用集群
cluster-config-file nodes-7000.conf #运行多实例时请注修改为对应端口
cluster-node-timeout 5000           #单位毫秒。集群节点超时时间
cluster-replica-validity-factor 10 	#默认就是10,单位是秒
cluster-migration-barrier 1         #默认配置是一个迁移临界值。
cluster-require-full-coverage yes   #集群中的所有slot(16384个)全部覆盖,把注释打开就好了

#7001操作:
[root@redis-cluster1 7001]# mv redis.conf redis.conf.bak
[root@redis-cluster1 7001]# cp ../7000/redis.conf ./
[root@redis-cluster1 7001]# vim redis.conf   #把7000修改成7001:%s/7000/7001/g
#以此类推,把修改好的配置文件发给每个机器,再把bind和4个端口号修改

#启动各个实例,以此类推
/usr/local/redis/src/redis-server /data/redis/cluster/7000/redis.conf
#创建集群:在其中一个节点操作就可以
cd /usr/local/redis/src/
./redis-cli --cluster create --cluster-replicas 1 IP1:7000 IP2:7001 IP3:7002 IP4:7003 IP5:7004 IP6:7005

Rabbitmq

#修改主机名字,添加解析,关闭防火墙
vim /etc/hosts
IP1 rabbitmq-1
IP2 rabbitmq-2
IP3 rabbitmq-3

#三个节点配置安装rabbitmq软件
yum install -y *epel* gcc-c++ unixODBC unixODBC-devel openssl-devel ncurses-devel   #安装依赖
curl -s https://packagecloud.io/install/repositories/rabbitmq/erlang/script.rpm.sh | sudo bash
yum install erlang-21.3.8.21-1.el7.x86_64 -y   #安装erlang

erl   #测试是否有erl环境
Erlang/OTP 21 [erts-10.3.5.16] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1] [hipe]
Eshell V10.3.5.16  (abort with ^G)
1>	#crtl g
User switch command
 -->	q	    #退出;h列出功能

yum install -y socat   #安装 socat
yum install -y rabbitmq-server-3.7.10-1.el7.noarch.rpm   #安装rabbitmq
systemctl daemon-reload    #启动rabbitmq
systemctl enable  --now  rabbitmq-server.service  #启动并加入开机自启

#任意一个节点创建用户并修改权限
rabbitmqctl add_user admin admin   #添加一个admin的用户
rabbitmqctl set_user_tags admin administrator  #设置角色为管理员
rabbitmqctl list_users             #查看用户
rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"  #对admin这个用户设置所有资源可读可写

#3台机器都开启用户远程登录
cd /etc/rabbitmq/   
cp /usr/share/doc/rabbitmq-server-3.7.10/rabbitmq.config.example /etc/rabbitmq/rabbitmq.config
cp rabbitmq.config{,.bak}
vim rabbitmq.config        #修改如下:
%% {loopback_users, []},   #改成: {loopback_users, []}
systemctl restart rabbitmq-server   #三台机器都操作重启服务

#部署集群,所有机器都要操作
mkdir -p /data/rabbitmq/{data,logs}
chmod 777 -R /data/rabbitmq
chown rabbitmq.rabbitmq /data/ -R
vim /etc/rabbitmq/rabbitmq-env.conf         #创建配置文件
RABBITMQ_MNESIA_BASE=/data/rabbitmq/data
RABBITMQ_LOG_BASE=/data/rabbitmq/logs
systemctl restart rabbitmq-server           #重启服务

#将rabbitmq-1节点的.erlang.cookie的值复制到其他两个节点中
cat /var/lib/rabbitmq/.erlang.cookie 
TLRCSBNSYLEYNYUALPRM   
scp /var/lib/rabbitmq/.erlang.cookie root@IP2:/var/lib/rabbitmq/
scp /var/lib/rabbitmq/.erlang.cookie root@IP3:/var/lib/rabbitmq/

#在rabbitmq-2、rabbitmq-3执行如下命令
systemctl restart rabbitmq-server.service  #先重启一下rabbitmq
rabbitmqctl stop_app                       #停止节点,切记不是停止服务

#将两个节点加入集群,指定角色,执行相同操作
rabbitmqctl join_cluster --ram rabbit@rabbitmq-1  #添加到内存节点 --ram
rabbitmqctl start_app                             #启动节点
rabbitmqctl cluster_status                        #任意节点上查看是否集群配置成功