Docker环境下的前后端分离项目部署与运维

第1章 RR开源前后端分离项目

image-20201216112911694

第2章 RR开源前后端分离项目下载与配置

2.1 项目描述

image-20201216113924705

项目地址: https://gitee.com/renrenio

image-20201216113812021

2.2 后端项目下载与配置

image-20201216114052154

下载后台源码,

后端:https://gitee.com/renrenio/renren-fast.git

前端:https://gitee.com/renrenio/renren-fast-vue.git

使用IDEA打开后端,Webstrom或者VScode打开前端

新建数据库renren_fast后端项目打开之后将mysql.sql导入数据库

image-20201216115210314

导入数据库后运行该项目,访问 http://localhost:8080/renren-fast/swagger/index.html

image-20201216141111818

image-20201216141224365

2.3 前台项目的下载与配置

image-20201216141441877

1
2
3
4
5
6
安装node.js 
安装依赖&运行项目

cd 工程目录
npm install
npm run dev

image-20201216153346586

image-20201216153455101

1
2
3
4
5
6
7
8
9
10
11
firewall-cmd --permanent --add-port=8080-8085/tcp

firewall-cmd --reload

firewadd-cmd --permanent --remove-port=8080=8085/tcp

#查看防火墙开启的端口号是
firewall-cmd --permanent --list-ports

#查看有哪些服务通过防火墙连接了互联网
firewall-cmd --permanent --list-services

image-20201216143249424

1
2
3
4
# 导入导出镜像 
docker save java > /home/java.tar.gz

docker load < /home/java.tar.gz

第3章 搭建MySQL集群

单节点数据库的弊端

大型互联网程序用户群体庞大,所以架构必须要特殊设计

单节点的数据库无法满足性能上的要求

单节点的数据库没有冗余设计,无法满足高可用

3.1 常见MySQl集群方案

image-20201216153555482

mysql 集群方案介绍,建议使用pxc,因为弱一致性会有问题,比如说a节点数据库显示我购买成功,b 节点数据库显示没有成功,这就麻烦了,pxc 方案是在全部节点都写入成功之后才会告诉你成功,是可读可写双向同步的,但是replication是单向的,不同节点的数据库之间都会开放端口进行通讯,如果从防火墙的这个端口关闭,pxc就不会同步成功,也不会返给你成功了。

PXC集群示意图

image-20201216154015548

PXC集群同步是双向的在任何一个节点写入数据,都会同步到其他节点中。在一个节点写入数据会同步到第二个,第三个,第四个节点中去。在任何一个节点上都是可以同时读写数据的,Replication同步数据时单向的,无法做到任何一个节点同时读写数据

Replication集群示意图

image-20201216154411929

负责写入数据的节点叫做master,我们在master上写入数据,因为同步是单向的,数据会同步到另外一个节点上。这个节点比如说叫做slave节点,那么这个节点是可以读取到数据的。因为数据同步是单向的,那么这个数据不会同步到Master节点中。Replication同步数据时单向的,导致不是每一个节点都是可以同时读写的

PXC数据的强一致性

同步复制,事务在所有节点要么同时提交,要么不提交

Replication采用异步复制,无法保证数据的一致性

3.2 创建MySQL集群

安装PXC镜像

1
2
3
4
5
6
7
8
#安装PXC镜像
docker pull percona/percona-xtradb-cluster

#为PXC镜像改名(因为原来的名字有点长)
docker tag percona/percona-xtradb-cluster pxc

#删除原来的镜像
docker rmi percona/percona-xtradb-cluster

image-20201216161024659

创建内部网络

出于安全考虑,需要给PXC集群实例创建Docker内部网络

1
2
3
4
5
6
7
docker network create net1

# 这个网段相关的信息
docker network inspect net1

# 删除网段
docker network rm net1

Docker 内置的网段 172.17.0.XX

自己创建的网段 172.18.0.XX 、172.19.0.XX 以此类推

也可以自定义网段

1
docker network create --subnet=172.18.0.0/24 net1

image-20201216161537775

创建Docker卷

容器中的PXC节点映射数据目录的解决办法

1
2
3
4
# --name 可以省略
docker volume create --name v1

docker volume rm v1

image-20201216161909334

3.3 创建PXC容器

创建5个数据卷

1
2
3
4
5
docker volume create --name v1
docker volume create --name v2
docker volume create --name v3
docker volume create --name v4
docker volume create --name v5

只要向PXC镜像传入运行参数就能创建出PXC容器

容器的创建非常快,但是容器中mysql的初始话不是一瞬间就完成的,MySQL数据库的初始话至少要2分钟以上,如果第一个PXC容器里的MySQL没有初始话成功,就创建第二个PXC容器,第二个PXC容器会闪退,因为第二个里面的mysql和第一个里面的mysql做同步的时候,他发现第一个容器里得MySQL没有启动,他就会出现一些故障,导致第二个PXC容器闪退,所以必须第1个MySQL节点启动成功,用MySQL客户端能连接上之后,再去创建其他MySQL节点。

1
2
3
4
5
6
7
8
9
10
#创建第1个MySQL节点
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -v v1:/var/lib/mysql --privileged --name=node1 --net=net1 --ip 172.18.0.2 pxc
#创建第2个MySQL节点
docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v2:/var/lib/mysql --privileged --name=node2 --net=net1 --ip 172.18.0.3 pxc
#创建第3个MySQL节点
docker run -d -p 3308:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v3:/var/lib/mysql --privileged --name=node3 --net=net1 --ip 172.18.0.4 pxc
#创建第4个MySQL节点
docker run -d -p 3309:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v4:/var/lib/mysql --privileged --name=node4 --net=net1 --ip 172.18.0.5 pxc
#创建第5个MySQL节点
docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v5:/var/lib/mysql --privileged --name=node5 --net=net1 --ip 172.18.0.6 pxc

node1节点成功启动,node2节点启动时报错:New joining cluster node didn‘t find all needed SSL artifacts

image-20201216173118094

解决方案:https://www.cnblogs.com/nhdlb/p/14046323.html

PXC8.0官方说明:https://www.percona.com/doc/percona-xtradb-cluster/8.0/howtos/upgrade_guide.html

官网描述:https://www.percona.com/doc/percona-xtradb-cluster/8.0/security/encrypt-traffic.html#ssl-auto-conf

  • 解决方案属实有点小麻烦,我选择放弃采用5.7版本….
1
2
3
4
5
6
7
8
// 拉取PXC
docker pull percona/percona-xtradb-cluster:5.7.21

// 修改镜像名称为PXC
docker tag percona/percona-xtradb-cluster:5.7.21 pxc

// 删除原来的percona/percona-xtradb-cluster镜像
docker rmi percona/percona-xtradb-cluster:5.7.21

全部启动后

image-20201216175831263

在其中一个节点中新建数据库,新建表,然后增加一条字段会同步到所有节点中

image-20201216180020467

image-20201216180154608

3.4 数据库负载均衡

数据库负载均衡的必要性

负载均衡首先是数据库的集群,加入5个集群,每次请求都是第一个的话,有可能第一个数据库就挂掉了,所以更优的方案是对不同的节点都进行请求,这就需要有中间件进行转发,比较好的中间件有nginx,haproxy等,因nginx 支持插件,但是刚刚支持了tcp/ip 协议,haproxy 是一个老牌的中间转发件。如果要用haproxy的话,可以从官方下载镜像,然后呢对镜像进行配置(自己写好配置文件,因为这个镜像是没有配置文件的,配置好之后再运行镜像的时候进行文件夹的映射,配置文件开放3306(数据库请求,然后根据check心跳检测访问不同的数据库,8888 对数据库集群进行监控))。配置文件里面设置用户(用户在数据库进行心跳检测,判断哪个数据库节点是空闲的,然后对空闲的进行访问),还有各种算法(比如轮训),最大连接数,时间等,还有对集群的监控。配置文件写好以后运行这个镜像,镜像运行成功后进入容器启动配置文件 。其实haprocy返回的也是一个数据库实例(但是并不存储任何的数据,只是转发请求),这个实例用来check其他节点。最好生成至少两个这样的实例。当一个挂掉的时候,另外 一个可以顶上(这就是双机热备见下一节)。

image-20201216180553418

image-20201216180717239

安装Haproxy

1
docker pull haproxy

创建Haproxy的配置文件

1
touch /home/soft/haproxy/haproxy.cfg

配置文件详情可以参考 https://zhangge.net/5125.html

配置文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
global
#工作目录
chroot /usr/local/etc/haproxy
#日志文件,使用rsyslog服务中local5日志设备(/var/log/local5),等级info
log 127.0.0.1 local5 info
#守护进程运行
daemon

defaults
log global
mode http
#日志格式
option httplog
#日志中不记录负载均衡的心跳检测记录
option dontlognull
#连接超时(毫秒)
timeout connect 5000
#客户端超时(毫秒)
timeout client 50000
#服务器超时(毫秒)
timeout server 50000

#监控界面
listen admin_stats
#监控界面的访问的IP和端口
bind 0.0.0.0:8888
#访问协议
mode http
#URI相对地址
stats uri /dbs
#统计报告格式
stats realm Global\ statistics
#登陆帐户信息
stats auth admin:abc123456
#数据库负载均衡
listen proxy-mysql
#访问的IP和端口
bind 0.0.0.0:3306
#网络协议
mode tcp
#负载均衡算法(轮询算法)
#轮询算法:roundrobin
#权重算法:static-rr
#最少连接算法:leastconn
#请求源IP算法:source
balance roundrobin
#日志格式
option tcplog
#在MySQL中创建一个没有权限的haproxy用户,密码为空。Haproxy使用这个账户对MySQL数据库心跳检测
option mysql-check user haproxy
server MySQL_1 172.18.0.2:3306 check weight 1 maxconn 2000
server MySQL_2 172.18.0.3:3306 check weight 1 maxconn 2000
server MySQL_3 172.18.0.4:3306 check weight 1 maxconn 2000
server MySQL_4 172.18.0.5:3306 check weight 1 maxconn 2000
server MySQL_5 172.18.0.6:3306 check weight 1 maxconn 2000
#使用keepalive检测死链
option tcpka

创建Haproxy容器

1
2
3
4
5
6
7
#创建第1个Haproxy负载均衡服务器
docker run -it -d -p 4001:8888 -p 4002:3306 -v /home/soft/haproxy:/usr/local/etc/haproxy --name h1 --privileged --net=net1 --ip 172.18.0.7 haproxy

# 进入h1容器
docker exec -it h1 bash
# 启动Haproxy
haproxy -f /usr/local/etc/haproxy/haproxy.cfg

image-20201216184722575

在数据库节点中新增haproxy用户,Haproxy使用这个账户对MySQL数据库心跳检测

1
create user 'haproxy'@'%' identified by ''

image-20201216183218006

测试

直接访问ip:4001/dbs 账号:admin 密码: abc123456

image-20201216183433535

节点状态都正常

image-20201216184612254

1
2
# 将一个节点挂掉之后
docker stop node1

image-20201216185252792

使用客户端连接Haproxy 端口号为之前映射的4002

image-20201216185042768

新增一条数据会同步到所有节点

image-20201216185123703

3.5 负载均衡的高可用方案

为什么要采用双机热备

双机就是两个请求处理程序,比如两个haproxy,当一个挂掉的时候,另外 一个可以顶上。热备我理解就是keepalive。在haproxy 容器中安装keepalive。

关键就是虚拟ip,定义一个虚拟ip,然后比如两个haproxy分别安装keepalive镜像,因为haproxy是ubuntu系统的,所以安装用apt-get,keepalive是作用是抢占虚拟ip,抢到的就是主服务器,没有抢到的就是备用服务器,然后两个keepalive进行心跳检测(就是创建一个用户到对方那里试探,看是否还活着,mysql的集群之间也是心跳检测),如果 挂掉抢占ip。所以在启动keepalive 之前首先要编辑好他的配置文件,怎么抢占,权重是什么,虚拟ip是什么,创建的用户交什么。配置完启动完以后可以ping一下看是否正确.

然后将虚拟ip映射到局域网的ip

image-20201216185435192

实现Haproxy双机热备离不开虚拟Ip的技术

image-20201216185553175

利用Keepalived实现双机热备

image-20201216193803132

Haproxy双机热备方案

image-20201216194213851

安装Keepalived

Keepalived必须安装在Haproxy所在的容器之内

1
2
apt-get update
apt-get install keepalived

Keepalived配置文件

Keepalived的配置文件时/etc/keepalived/keepalived.conf

1
2
3
4
5
6
7
8
9
10
11
interface 网卡设备

virtual_router_id 虚拟路径标识 MASTER和BACKUP的虚拟路由标识必须一致。标识可以是0-255
priority MASTER权重要搞域BACKUP 数字越大优先级越高


advert_int MASTER与BACKUP节点间同步检查的时间间隔,单位为秒,主备之间必须一致

authentication 心跳检测需要登录到Keepalived节点,主从服务器验证方式,主备必须使用相同的密码才能正常通信

virtual_ipaddress xuniIP地址,而可以设置多个虚拟IP地址,每行一个

advert

image-20201216195908084

搭建双击热备

  1. 安装Haproxy镜像

    1
    docker pull haproxy
  2. 宿主机上编写Haproxy配置文件

    1
    vi /home/soft/haproxy.cfg

    配置文件如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    global
    #工作目录
    chroot /usr/local/etc/haproxy
    #日志文件,使用rsyslog服务中local5日志设备(/var/log/local5),等级info
    log 127.0.0.1 local5 info
    #守护进程运行
    daemon

    defaults
    log global
    mode http
    #日志格式
    option httplog
    #日志中不记录负载均衡的心跳检测记录
    option dontlognull
    #连接超时(毫秒)
    timeout connect 5000
    #客户端超时(毫秒)
    timeout client 50000
    #服务器超时(毫秒)
    timeout server 50000

    #监控界面
    listen admin_stats
    #监控界面的访问的IP和端口
    bind 0.0.0.0:8888
    #访问协议
    mode http
    #URI相对地址
    stats uri /dbs
    #统计报告格式
    stats realm Global\ statistics
    #登陆帐户信息
    stats auth admin:abc123456
    #数据库负载均衡
    listen proxy-mysql
    #访问的IP和端口
    bind 0.0.0.0:3306
    #网络协议
    mode tcp
    #负载均衡算法(轮询算法)
    #轮询算法:roundrobin
    #权重算法:static-rr
    #最少连接算法:leastconn
    #请求源IP算法:source
    balance roundrobin
    #日志格式
    option tcplog
    #在MySQL中创建一个没有权限的haproxy用户,密码为空。Haproxy使用这个账户对MySQL数据库心跳检测
    option mysql-check user haproxy
    server MySQL_1 172.18.0.2:3306 check weight 1 maxconn 2000
    server MySQL_2 172.18.0.3:3306 check weight 1 maxconn 2000
    server MySQL_3 172.18.0.4:3306 check weight 1 maxconn 2000
    server MySQL_4 172.18.0.5:3306 check weight 1 maxconn 2000
    server MySQL_5 172.18.0.6:3306 check weight 1 maxconn 2000
    #使用keepalive检测死链
    option tcpka
  3. 创建两个Haproxy容器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #创建第1个Haproxy负载均衡服务器
    docker run -it -d -p 4001:8888 -p 4002:3306 -v /home/soft/haproxy:/usr/local/etc/haproxy --name h1 --privileged --net=net1 --ip 172.18.0.7 haproxy

    #进入h1容器,启动Haproxy
    docker exec -it h1 bash
    haproxy -f /usr/local/etc/haproxy/haproxy.cfg

    #创建第2个Haproxy负载均衡服务器
    docker run -it -d -p 4003:8888 -p 4004:3306 -v /home/soft/haproxy:/usr/local/etc/haproxy --name h2 --privileged --net=net1 --ip 172.18.0.8 haproxy

    #进入h2容器,启动Haproxy
    docker exec -it h2 bash
    haproxy -f /usr/local/etc/haproxy/haproxy.cfg
  4. Haproxy容器内安装Keepalived,设置虚拟IP

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #进入h1容器
    docker exec -it h1 bash
    #更新软件包
    apt-get update
    #安装VIM
    apt-get install vim
    #安装Keepalived
    apt-get install keepalived
    #编辑Keepalived配置文件(参考下方配置文件)
    vim /etc/keepalived/keepalived.conf
    #启动Keepalived
    service keepalived start
    #宿主机执行ping命令
    ping 172.18.0.201

    配置文件内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    vrrp_instance  VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
    auth_type PASS
    auth_pass 123456
    }
    virtual_ipaddress {
    172.18.0.201
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #进入h2容器
    docker exec -it h2 bash
    #更新软件包
    apt-get update
    #安装VIMshell
    apt-get install vim
    #安装Keepalived
    apt-get install keepalived
    #编辑Keepalived配置文件
    vim /etc/keepalived/keepalived.conf
    #启动Keepalived
    service keepalived start
    #宿主机执行ping命令
    ping 172.18.0.201

    配置文件内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    vrrp_instance  VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
    auth_type PASS
    auth_pass 123456
    }
    virtual_ipaddress {
    172.18.0.201
    }
    }
  5. 宿主机安装Keepalived,实现双机热备

    1
    2
    3
    4
    5
    6
    #宿主机执行安装Keepalived
    yum -y install keepalived
    #修改Keepalived配置文件
    vi /etc/keepalived/keepalived.conf
    #启动Keepalived
    service keepalived start

    Keepalived配置文件如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
    auth_type PASS
    auth_pass 1111
    }
    virtual_ipaddress {
    192.168.99.150
    }
    }

    virtual_server 192.168.99.150 8888 {
    delay_loop 3
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP

    real_server 172.18.0.201 8888 {
    weight 1
    }
    }

    virtual_server 192.168.99.150 3306 {
    delay_loop 3
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP

    real_server 172.18.0.201 3306 {
    weight 1
    }
    }

3.6 热备份数据

1.冷备份 导出数据库进行备份,但是数据库需要停机,影响业务

2.热备份

​ 全量备份:整个都备份 增量备份:对变化的数据进行备份 。

​ 方案:lvm 和xtrabackup lvm 需要对数据库进行加锁(锁表),只能读取数据不能写入数据。

​ 具体方法:利用mysql集群的技术,暂停删除一个节点镜像,新建一个节点进行备份(先要创造一个数据卷用来映射容器中备份的数据),然后下载xtrabackup 进行备份。

​ 备份数据进行恢复

冷备份

image-20201216210156525

热备份

image-20201216210359262

XtraBackup介绍

image-20201216210415689

XtraBackup优势

image-20201216210507241

全量备份和增量备份

1
2
3
4
5
6
7
8
# 必须挂载备份数据目录
docker volume create backup

docker stop node1

docker rm node1

docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -v v1:/var/lib/mysql -v backup1:/data --privileged -e CLUSTER_JOIN=node2 --name=node1 --net=net1 --ip 172.18.0.2 pxc

热备份数据

1
2
3
4
5
6
7
8
#进入node1容器
docker exec -it node1 bash
#更新软件包
apt-get update
#安装热备工具
apt-get install percona-xtrabackup-24
#全量热备
innobackupex --user=root --password=abc123456 /data/backup/full

冷还原数据

停止其余4个节点,并删除节点

1
2
3
4
5
6
7
8
docker stop node2
docker stop node3
docker stop node4
docker stop node5
docker rm node2
docker rm node3
docker rm node4
docker rm node5

node1容器中删除MySQL的数据

1
2
3
4
5
6
#删除数据
rm -rf /var/lib/mysql/*
#清空事务
innobackupex --user=root --password=abc123456 --apply-back /data/backup/full/2020-04-15_05-09-07/
#还原数据
innobackupex --user=root --password=abc123456 --copy-back /data/backup/full/2020-04-15_05-09-07/

重新创建其余4个节点,组件PXC集群

第5章 搭建Redis集群

5.1 高速缓存的介绍

  • 高速缓存利用内存保存数据,读写速度远超硬盘

  • 高速缓存可以减少I/O操作,降低I/O压力

5.2 Redis 集群介绍

  1. RedisCluster:官方推荐,没有中心节点
  2. Codis:中间件产品,存在中心节点
  3. Twemproxy:中间件产品,存在中心节点

5.3 RedisCluster

  • 无中心节点,客户端与Redis节点直连,不需要中间代理层

  • 数据可以被分片存储

  • 管理方便,后续可自行增加或摘除节点

5.4 主从同步

  • Redis集群中的数据库复制是通过主从同步来实现的

  • 主节点把数据分发给从节点

  • 主从同步的好处在于高可用,Redis节点有冗余设计

5.5 Redis集群高可用

  • Redis集群中应该包含奇数个Master,至少应该有三个
  • Redis集群中每个Master都应该有Slave、

image-20201217152733125

1
2
3
#新建一个网段(用来存放Reids集群)
docker network create --subnet=172.19.0.0/16 net2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 创建配置文件

for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.19.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done


image-20201217160736510

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 启动Redis
docker run -p 5001:6379 -p 15001:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net net2 --ip 172.19.0.2 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 5002:6379 -p 15002:16379 --name redis-2 \
-v /mydata/redis/node-2/data:/data \
-v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net net2 --ip 172.19.0.3 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 5003:6379 -p 15003:16379 --name redis-3 \
-v /mydata/redis/node-3/data:/data \
-v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
-d --net net2 --ip 172.19.0.4 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 5004:6379 -p 15004:16379 --name redis-4 \
-v /mydata/redis/node-4/data:/data \
-v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
-d --net net2 --ip 172.19.0.5 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 5005:6379 -p 15005:16379 --name redis-5 \
-v /mydata/redis/node-5/data:/data \
-v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
-d --net net2 --ip 172.19.0.6 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 5006:6379 -p 15006:16379 --name redis-6 \
-v /mydata/redis/node-6/data:/data \
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net net2 --ip 172.19.0.7 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf



image-20201217161116049

1
2
3
4
5
6
7
8
#创建集群
进入一个Redis容器中执行
redis-cli --cluster create 172.19.0.2:6379 172.19.0.3:6379 172.19.0.4:6379 172.19.0.5:6379 172.19.0.6:6379 172.19.0.7:6379 --cluster-replicas 1

# 通过集群连接
redis-cli -c
cluster info
cluster nodes
1
2
docekr pause redis-3
docker unpause redis-3

第6章 部署前后端分离项目

6.1 打包部署后端项目

1
,Java程序假设分配到Net3网段上想访问宿主机上net1网段的mysql 以及net2网段上的Redis集群。Doker容器是禁止跨网段访问的,就需要把Java程序的网络对接到宿主机的网络上,不要给Java程序划分网段,直接使用宿主机的网络。这样可能存在一个问题就是端口号冲突问题,因此需要给Java程序设置不同的端口
  1. 进入人人开源后端项目,执行打包(修改配置文件,更改端口,打包三次生成三个JAR文件)

mvn clean install -Dmaven.test.skip=true

  1. 安装Java镜像

docker pull java

  1. 创建3节点Java容器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#创建数据卷,上传JAR文件
docker volume create j1
#将jar放到该数据卷中

#启动容器(需要和宿主机同一网络)
docker run -it -d --name j1 -v j1:/home/soft --net=host java
#进入j1容器
docker exec -it j1 bash
#启动Java项目
nohup java -jar /home/soft/renren-fast.jar

#创建数据卷,上传JAR文件
docker volume create j2
#启动容器
docker run -it -d --name j2 -v j2:/home/soft --net=host java
#进入j1容器
docker exec -it j2 bash
#启动Java项目
nohup java -jar /home/soft/renren-fast.jar --server.port=6002 &

#创建数据卷,上传JAR文件
docker volume create j3
#启动容器
docker run -it -d --name j3 -v j3:/home/soft --net=host java
#进入j1容器
docker exec -it j3 bash
#启动Java项目
nohup java -jar /home/soft/renren-fast.jar --server.port=6003 &

后程序负载均衡

Nginx是性能非常出色的反向代理服务器,最大可以支持8w/s的并发访问

安装Nginx

1
docker pull nginx

创建Nginx容器,配置负载均衡

宿主机上/home/n1/nginx.conf配置文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
user  nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
#tcp_nopush on;

keepalive_timeout 65;

#gzip on;

proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 5s;
proxy_send_timeout 5s;
proxy_read_timeout 5s;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;

upstream tomcat {
server 192.168.99.104:6001;
server 192.168.99.104:6002;
server 192.168.99.104:6003;
}
server {
listen 6101;
server_name 192.168.99.104;
location / {
proxy_pass http://tomcat;
index index.html index.htm;
}
}
}

创建第1个Nginx节点

1
docker run -it -d --name n1 -v /home/n1/nginx.conf:/etc/nginx/nginx.conf --net=host --privileged nginx
  1. 宿主机上/home/n2/nginx.conf配置文件内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    user  nginx;
    worker_processes 1;
    error_log /var/log/nginx/error.log warn;
    pid /var/run/nginx.pid;

    events {
    worker_connections 1024;
    }

    http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
    '$status $body_bytes_sent "$http_referer" '
    '"$http_user_agent" "$http_x_forwarded_for"';

    access_log /var/log/nginx/access.log main;

    sendfile on;
    #tcp_nopush on;

    keepalive_timeout 65;

    #gzip on;

    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    client_max_body_size 10m;
    client_body_buffer_size 128k;
    proxy_connect_timeout 5s;
    proxy_send_timeout 5s;
    proxy_read_timeout 5s;
    proxy_buffer_size 4k;
    proxy_buffers 4 32k;
    proxy_busy_buffers_size 64k;
    proxy_temp_file_write_size 64k;

    upstream tomcat {
    server 192.168.99.104:6001;
    server 192.168.99.104:6002;
    server 192.168.99.104:6003;
    }
    server {
    listen 6102;
    server_name 192.168.99.104;
    location / {
    proxy_pass http://tomcat;
    index index.html index.htm;
    }
    }
    }

    创建第2个Nginx节点

    1
    docker run -it -d --name n2 -v /home/n2/nginx.conf:/etc/nginx/nginx.conf --net=host --privileged nginx
  2. 在Nginx容器安装Keepalived

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #进入n1节点
    docker exec -it n1 bash
    #更新软件包
    apt-get update
    #安装VIM
    apt-get install vim
    #安装Keepalived
    apt-get install keepalived
    #编辑Keepalived配置文件(如下)
    vim /etc/keepalived/keepalived.conf
    #启动Keepalived
    service keepalived start
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
    auth_type PASS
    auth_pass 123456
    }
    virtual_ipaddress {
    192.168.99.151
    }
    }
    virtual_server 192.168.99.151 6201 {
    delay_loop 3
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP
    real_server 192.168.99.104 6101 {
    weight 1
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #进入n1节点
    docker exec -it n2 bash
    #更新软件包
    apt-get update
    #安装VIM
    apt-get install vim
    #安装Keepalived
    apt-get install keepalived
    #编辑Keepalived配置文件(如下)
    vim /etc/keepalived/keepalived.conf
    #启动Keepalived
    service keepalived start
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
    auth_type PASS
    auth_pass 123456
    }
    virtual_ipaddress {
    192.168.99.151
    }
    }
    virtual_server 192.168.99.151 6201 {
    delay_loop 3
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP
    real_server 192.168.99.104 6102 {
    weight 1
    }
    }

6.2 打包部署前端项目

在前端项目路径下执行打包指令

1
npm run build

文件拷贝到宿主机

  • build目录的文件拷贝到宿主机的/home/fn1/renren-vue、/home/fn2/renren-vue、/home/fn3/renren-vue的目录下面

创建3节点的Nginx,部署前端项目

  • 宿主机/home/fn1/nginx.conf的配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
user  nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
#tcp_nopush on;

keepalive_timeout 65;

#gzip on;

proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 5s;
proxy_send_timeout 5s;
proxy_read_timeout 5s;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;

server {
listen 6501;
server_name 192.168.99.104;
location / {
root /home/fn1/renren-vue;
index index.html;
}
}
}
1
2
#启动第fn1节点
docker run -it -d --name fn1 -v /home/fn1/nginx.conf:/etc/nginx/nginx.conf -v /home/fn1/renren-vue:/home/fn1/renren-vue --privileged --net=host nginx
  • 宿主机/home/fn2/nginx.conf的配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
user  nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
#tcp_nopush on;

keepalive_timeout 65;

#gzip on;

proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 5s;
proxy_send_timeout 5s;
proxy_read_timeout 5s;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;

server {
listen 6502;
server_name 192.168.99.104;
location / {
root /home/fn2/renren-vue;
index index.html;
}
}
}
1
2
#启动第fn2节点
docker run -it -d --name fn2 -v /home/fn2/nginx.conf:/etc/nginx/nginx.conf -v /home/fn2/renren-vue:/home/fn2/renren-vue --privileged --net=host nginx
  • 宿主机/home/fn3/nginx.conf的配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
user  nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
#tcp_nopush on;

keepalive_timeout 65;

#gzip on;

proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 5s;
proxy_send_timeout 5s;
proxy_read_timeout 5s;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;

server {
listen 6503;
server_name 192.168.99.104;
location / {
root /home/fn3/renren-vue;
index index.html;
}
}
}

启动fn3节点

1
2
#启动第fn3节点
docker run -it -d --name fn3 -v /home/fn3/nginx.conf:/etc/nginx/nginx.conf -v /home/fn3/renren-vue:/home/fn3/renren-vue --privileged --net=host nginx

配置负载均衡

  • 宿主机/home/ff1/nginx.conf配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
user  nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
#tcp_nopush on;

keepalive_timeout 65;

#gzip on;

proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 5s;
proxy_send_timeout 5s;
proxy_read_timeout 5s;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;

upstream fn {
server 192.168.99.104:6501;
server 192.168.99.104:6502;
server 192.168.99.104:6503;
}
server {
listen 6601;
server_name 192.168.99.104;
location / {
proxy_pass http://fn;
index index.html index.htm;
}
}
}
1
2
#启动ff1节点
docker run -it -d --name ff1 -v /home/ff1/nginx.conf:/etc/nginx/nginx.conf --net=host --privileged nginx
  • 宿主机/home/ff2/nginx.conf配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
user  nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
#tcp_nopush on;

keepalive_timeout 65;

#gzip on;

proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 5s;
proxy_send_timeout 5s;
proxy_read_timeout 5s;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;

upstream fn {
server 192.168.99.104:6501;
server 192.168.99.104:6502;
server 192.168.99.104:6503;
}
server {
listen 6602;
server_name 192.168.99.104;
location / {
proxy_pass http://fn;
index index.html index.htm;
}
}
}
1
2
#启动ff2节点
docker run -it -d --name ff2 -v /home/ff2/nginx.conf:/etc/nginx/nginx.conf --net=host --privileged nginx

配置双机热备

1
2
3
4
5
6
7
8
9
10
11
12
#进入ff1节点
docker exec -it ff1 bash
#更新软件包
apt-get update
#安装VIM
apt-get install vim
#安装Keepalived
apt-get install keepalived
#编辑Keepalived配置文件(如下)
vim /etc/keepalived/keepalived.conf
#启动Keepalived
service keepalived start
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 52
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.99.152
}
}
virtual_server 192.168.99.151 6701 {
delay_loop 3
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
real_server 192.168.99.104 6601 {
weight 1
}
}
1
2
3
4
5
6
7
8
9
10
11
12
#进入ff1节点
docker exec -it ff2 bash
#更新软件包
apt-get update
#安装VIM
apt-get install vim
#安装Keepalived
apt-get install keepalived
#编辑Keepalived配置文件(如下)
vim /etc/keepalived/keepalived.conf
#启动Keepalived
service keepalived start
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 52
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.99.152
}
}
virtual_server 192.168.99.151 6701 {
delay_loop 3
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
real_server 192.168.99.104 6602 {
weight 1
}
}