# 1.新版安管

### 架构图

![image-20230709220942835](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230709220942835.png)

![image-20230721145522200](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230721145522200.png)

# 2.运行环境

## 服务器端

### 硬件环境

**最低配置：**

|       CPU       |  内存   |       硬盘        |
| :-------------: | :-----: | :---------------: |
| 双核CPU2.0 以上 | 2G 以上 | 至少100G 可用空间 |

**建议配置：**

|       CPU       |  内存   |       硬盘        |
| :-------------: | :-----: | :---------------: |
| 酷睿双核2G 以上 | 4G 以上 | 100G 可用空间以上 |

### 软件环境

centos 7、pgsql、redis、pulsar、nginx

## 用户端

### 硬件环境

**最低配置：**

|     CPU      |  内存   |
| :----------: | :-----: |
| PentiumⅣ以上 | 4G 以上 |

**建议配置：**

|       CPU       |  内存   |
| :-------------: | :-----: |
| 酷睿双核1G 以上 | 4G 以上 |

### 软件环境

centos 操作系统



| 主机名 |      IP       |
| :----: | :-----------: |
| node-1 | 192.168.30.10 |
| node-2 | 192.168.30.11 |
| node-3 | 192.168.30.12 |



# 3.安装环境准备

### 防火墙

测试环境：

```
关闭防火墙
[root@node-02 ~]# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:firewalld(1)

```

生产环境：

```
根据需求开放所需端口
firewall-cmd --zone=internal --add-port=3888/tcp --permanent
firewall-cmd --zone=internal --add-port=2888/tcp --permanent
firewall-cmd --zone=internal --add-port=2181/tcp --permanent
firewall-cmd --zone=internal --add-port=8080/tcp --permanent
firewall-cmd --zone=internal --add-port=8443/tcp --permanent
firewall-cmd --zone=internal --add-port=6650/tcp --permanent
firewall-cmd --zone=internal --add-port=6651/tcp --permanent
firewall-cmd --zone=internal --add-port=9990/tcp --permanent
firewall-cmd --zone=internal --add-port=3181/tcp --permanent
firewall-cmd --zone=internal --add-port=8000/tcp --permanent
firewall-cmd --zone=internal --add-port=8001/tcp --permanent
firewall-cmd --zone=internal --add-port=8002/tcp --permanent
..................................
firewall-cmd --reload
```

|    组件     |             端口              |
| :---------: | :---------------------------: |
|  Zookeeper  | 3888、2888、8443、6650、6651  |
| Bookkeeper  | 2181、8000、8001、8002、3181  |
|   Broker    |          8080、9990           |
| postgresql  |             5432              |
|   pgpool    |             5444              |
|  consumer   |             7009              |
|  agentapi   |             7003              |
|    auth     |             7001              |
|   gateway   |             9999              |
|   xxljob    |             9080              |
|  producer   |             7006              |
|   tenant    |             8088              |
|   manage    |             7002              |
|    nacos    |             8848              |
| Prometheus  |            未定义             |
|    redis    | 6371,6372,6373,6374,6375,6376 |
|   granfan   |            未定义             |
|     w5      |            未定义             |
| nginx中间件 |       19090、18090、80        |



### hosts文件

```
[root@node-02 ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.55.12 node-01 zookeeper01 bookkeeper01 broker01   pg-0
192.168.55.16 node-02 zookeeper02 bookkeeper02 broker02   pg-1
192.168.55.20 node-03 zookeeper03 bookkeeper03 broker03   pg-2
```

### docker部署

<font color='red'>docker版本24.0</font>

<font color='red'>docker-compose版本v2.19.0</font>

```
#docker安装
tar -zxvf /root/docker-*.tgz>/dev/null 2>&1
mv /root/docker/* /usr/bin/ 
echo '[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target

[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s

[Install]
WantedBy=multi-user.target'>/usr/lib/systemd/system/docker.service
systemctl daemon-reload >/dev/null 2>&1
systemctl enable docker>/dev/null 2>&1
systemctl start docker>/dev/null 2>&1
docker info>/dev/null 2>&1
#docker-compose安装
cp -r /root/docker-compose-linux-x86_64 /usr/local/bin/docker-compose 
chmod +x /usr/local/bin/docker-compose 
docker-compose -v>/dev/null 2>&1

开机自运行docker
systemctl enable docker
启动docker服务
systemctl start docker
```

```
方法二：
运行安装脚本
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
```

```
docker版本
[root@node-02 ~]# docker --version
Docker version 20.10.19, build d85ef84
```

# 4  数据库

采用的是postgresql+pgpool集群架构

注意：14和latest版本配置文件不一样，环境变量也不一样

## postgresql数据库

### 环境变量参数

```
-dit                                           以交互模式、分离模式以及为容器分配一个伪终端的方式运行容器。 
--restart always                               设置容器在退出后自动重启。
--name pg-0                                    为容器指定名称为 pg-0。
-p 5432:5432                                   将宿主机的5432端口映射到容器内的5432端口，用于访问PostgreSQL数据库
--env REPMGR_PARTNER_NODES=pg-0,pg-1,pg-2      设置 Replication Manager的partner 节点列表。
--env REPMGR_NODE_NAME=pg-0                    设置节点名称为 pg-0。
--env REPMGR_NODE_NETWORK_NAME=pg-0            设置节点网络名称为 pg-0。
--env REPMGR_PRIMARY_HOST=pg-0                 设置主节点的主机名为 pg-0。
--env REPMGR_PASSWORD=repmgrpass               设置 Replication Manager 的密码。
--env POSTGRESQL_POSTGRES_PASSWORD=qwert123    设置 PostgreSQL 数据库的 postgres 用户密码。
--env POSTGRESQL_USERNAME=test                 设置 PostgreSQL 数据库的自定义用户名。
--env POSTGRESQL_PASSWORD=qwert123             设置 PostgreSQL 数据库的自定义用户密码。
--env POSTGRESQL_DATABASE=postgre              设置 PostgreSQL 数据库的数据库名。
-v /etc/hosts:/etc/hosts                       映射hosts文件
-v /root/postgresql:/bitnami/postgresq         将宿主机的/root/postgresql目录挂载到容器内的/bitnami/postgresql目                                                录，用于持久化存储PostgreSQL数据。
bitnami/postgresql-repmgr:14                   所用镜像名
```

### 环境准备

```
创建映射目录
mkdir -p /data/postgres
赋予组写权限
chmod g+w   postgres

！！！必须要以下权限才能正确映射：
drwxrwxr-x. 5 root root   42 Jul  5 09:33 postgres
```

```
可以通过以下过滤方式查看配置文件的配置项
 cat postgres.conf | grep -vE "^\s*$|^#|^\s"
```

### 部署

```yml
version: '3'

services:
  pg-0:
    image: bitnami/postgresql-repmgr:14
    ports:
      - 5432
    volumes:
      - /data/postgres:/bitnami/postgresql
    environment:
      - REPMGR_PARTNER_NODES=pg-0,pg-1,pg-2
      - REPMGR_NODE_NAME=pg-0
      - REPMGR_NODE_NETWORK_NAME=pg-0
      - REPMGR_PRIMARY_HOST=pg-0
      - REPMGR_PASSWORD=qwert123
      - POSTGRESQL_PASSWORD=qwert123
      - POSTGRESQL_SYNCHRONOUS_COMMIT_MODE=on
      - POSTGRESQL_NUM_SYNCHRONOUS_REPLICAS=3
      - POSTGRESQL_REPLICATION_MODE=master
      - POSTGRESQL_REPLICATION_USER=repl
      - POSTGRESQL_REPLICATION_PASSWORD=qwert123
    hostname: pg-0
    deploy:
      placement:
        constraints: [ node.hostname == node-01 ]


  pg-1:
    image: bitnami/postgresql-repmgr:14
    ports:
      - 5432
    volumes:
      - /data/postgres:/bitnami/postgresql
    environment:
      - REPMGR_PARTNER_NODES=pg-0,pg-1,pg-2
      - REPMGR_NODE_NAME=pg-1
      - REPMGR_NODE_NETWORK_NAME=pg-1
      - REPMGR_PRIMARY_HOST=pg-0
      - REPMGR_PASSWORD=qwert123
      - POSTGRESQL_PASSWORD=qwert123
      - POSTGRESQL_SYNCHRONOUS_COMMIT_MODE=on
      - POSTGRESQL_NUM_SYNCHRONOUS_REPLICAS=3
      - POSTGRESQL_REPLICATION_MODE=master
      - POSTGRESQL_REPLICATION_USER=repl
      - POSTGRESQL_REPLICATION_PASSWORD=qwert123
    hostname: pg-1
    deploy:
      placement:
        constraints: [ node.hostname == node-02 ]

  pg-2:
    image: bitnami/postgresql-repmgr:14
    ports:
      - 5432
    volumes:
      - /data/postgres:/bitnami/postgresql
    environment:
      - REPMGR_PARTNER_NODES=pg-0,pg-1,pg-2
      - REPMGR_NODE_NAME=pg-2
      - REPMGR_NODE_NETWORK_NAME=pg-2
      - REPMGR_PRIMARY_HOST=pg-0
      - REPMGR_PASSWORD=qwert123
      - POSTGRESQL_PASSWORD=qwert123
      - POSTGRESQL_SYNCHRONOUS_COMMIT_MODE=on
      - POSTGRESQL_NUM_SYNCHRONOUS_REPLICAS=3
      - POSTGRESQL_REPLICATION_MODE=master
      - POSTGRESQL_REPLICATION_USER=repl
      - POSTGRESQL_REPLICATION_PASSWORD=qwert123
    hostname: pg-2
    deploy:
      placement:
        constraints: [ node.hostname == node-03 ]
```



```shell
可能用到的命令
docker stop pg-0
docker rm pg-0
rm -rf /data/postgres/*
docker stop pg-1
docker rm pg-1
rm -rf /data/postgres/*
docker stop pg-2
docker rm pg-2
rm -rf /data/postgres/*

docker stack deploy -c docker-compose.yml pg
docker stack ps pg
docker stack ls
docker stack rm pg

```



pg-0数据库

```shell
docker run -dit --restart always --name pg-0 \
  -p 5432:5432 \
  --env REPMGR_PARTNER_NODES=pg-0,pg-1,pg-2 \
  --env REPMGR_NODE_NAME=pg-0 \
  --env REPMGR_NODE_NETWORK_NAME=pg-0 \
  --env REPMGR_PRIMARY_HOST=pg-0 \
  --env REPMGR_PASSWORD=qwert123 \
  --env POSTGRESQL_POSTGRES_PASSWORD=qwert123 \
  --env POSTGRESQL_USERNAME=manage \
  --env POSTGRESQL_PASSWORD=qwert123 \
  --env POSTGRESQL_SYNCHRONOUS_COMMIT_MODE=on \
  --env POSTGRESQL_NUM_SYNCHRONOUS_REPLICAS=3 \
  --env POSTGRESQL_REPLICATION_MODE=master \
  --env POSTGRESQL_REPLICATION_USER=repl \
  --env POSTGRESQL_REPLICATION_PASSWORD=qwert123 \
  --env POSTGRESQL_MASTER_HOST=pg-0 \
  --env POSTGRESQL_MASTER_PORT_NUMBER=5432 \
  -v /etc/hosts:/etc/hosts \
  -v /data/postgres:/bitnami/postgresql \
  bitnami/postgresql-repmgr:14
```

pg-1数据库

```
docker run -dit --restart always --name pg-1 \
  -p 5432:5432 \
  --env REPMGR_PARTNER_NODES=pg-0,pg-1,pg-2 \
  --env REPMGR_NODE_NAME=pg-1 \
  --env REPMGR_NODE_NETWORK_NAME=pg-1 \
  --env REPMGR_PRIMARY_HOST=pg-0 \
  --env REPMGR_PASSWORD=qwert123 \
  --env POSTGRESQL_POSTGRES_PASSWORD=qwert123 \
  --env POSTGRESQL_USERNAME=manage \
  --env POSTGRESQL_PASSWORD=qwert123 \
  --env POSTGRESQL_SYNCHRONOUS_COMMIT_MODE=on \
  --env POSTGRESQL_NUM_SYNCHRONOUS_REPLICAS=3 \
  --env POSTGRESQL_REPLICATION_MODE=master \
  --env POSTGRESQL_REPLICATION_USER=repl \
  --env POSTGRESQL_REPLICATION_PASSWORD=qwert123 \
  --env POSTGRESQL_MASTER_HOST=pg-0 \
  --env POSTGRESQL_MASTER_PORT_NUMBER=5432 \
  -v /etc/hosts:/etc/hosts \
  -v /data/postgres:/bitnami/postgresql \
  bitnami/postgresql-repmgr:14
```

pg-2数据库

```
docker run -dit --restart always --name pg-2 \
  -p 5432:5432 \
  --env REPMGR_PARTNER_NODES=pg-0,pg-1,pg-2 \
  --env REPMGR_NODE_NAME=pg-2 \
  --env REPMGR_NODE_NETWORK_NAME=pg-2 \
  --env REPMGR_PRIMARY_HOST=pg-0 \
  --env REPMGR_PASSWORD=qwert123 \
  --env POSTGRESQL_POSTGRES_PASSWORD=qwert123 \
  --env POSTGRESQL_USERNAME=manage \
  --env POSTGRESQL_PASSWORD=qwert123 \
  --env POSTGRESQL_SYNCHRONOUS_COMMIT_MODE=on \
  --env POSTGRESQL_NUM_SYNCHRONOUS_REPLICAS=3 \
  --env POSTGRESQL_REPLICATION_MODE=master \
  --env POSTGRESQL_REPLICATION_USER=repl \
  --env POSTGRESQL_REPLICATION_PASSWORD=qwert123 \
  --env POSTGRESQL_MASTER_HOST=pg-0 \
  --env POSTGRESQL_MASTER_PORT_NUMBER=5432 \
  -v /etc/hosts:/etc/hosts \
  -v /data/postgres:/bitnami/postgresql \
  bitnami/postgresql-repmgr:14
```

也可以将配置文件，数据目录，索引目录根据需求选择性映射出来

```
  -v /root/postgresql/data:/bitnami/postgresql/data \
  -v /root/postgresql/lock:/bitnami/postgresql/lock \
  -v /root/postgresql/conf:/bitnami/postgresql/conf \
```

### 验证

进入数据库检查配置

```
docker exec -it pg-0 bash
docker exec -it pg-1 bash
docker exec -it pg-2 bash

登录数据库
psql -U postgres -p 5432
-U    用户名
-p    端口

```

检查run后所创建的用户信息

```
SELECT * FROM pg_user;
```

```
postgres=# SELECT * FROM pg_user;
 usename  | usesysid | usecreatedb | usesuper | userepl | usebypassrls |  passwd  | valuntil |  useconfig                 
----------+----------+-------------+----------+---------+--------------+----------+----------+-------------
 postgres |       10 | t           | t        | t       | t            | ******** |          | 
 manage   |    16384 | t           | f        | f       | f            | ******** |          | 
 repmgr   |    16385 | f           | t        | t       | f            | ******** |          |  'a'
 
 'a'={"search_path=repmgr, \"$user\", public"}

usename                    用户名。
usesysid                 用户 ID，是一个唯一的系统标识符。
usecreatedb              指示用户是否具有创建数据库的权限。如果为t，表示用户可以创建数据库；如果为f，表示不能创建数据库。
usesuper                 指示用户是否是超级用户（superuser）。如果为t，表示用户是超级用户；如果为f，表示用户不是超级用户。
userepl                  指示用户是否具有复制权限。如果为t，表示用户具有复制权限；如果为f，表示用户没有复制权限。
usebypassrls             指示用户是否绕过行级安全（row-level security）。如果为t，表示用户可以绕过行级安全；如果为f，表                          示用户不能绕过行级安全。
passwd                   密码哈希值（已加密）。
valuntil                 密码有效期截止日期。
useconfig                用户的配置选项。
{"search_path=repmgr, \"$user\", public"}     用户可以控制 PostgreSQL 在搜索对象时的优先级和范围，使其能够更方便地访                                               问和操作数据库中的对象,同步复制
```

查看集群，同步复制状态（主库看才有，备库无）

```
SELECT * FROM pg_stat_replication;
```

```
-[ RECORD 1 ]----+------------------------------
pid              | 1339                                      连接的进程 ID
usesysid         | 16385                                     连接用户的系统标识符
usename          | repmgr                                    连接用户名，复制流用户repmgr
application_name | pg-1                                      节点连接的名称
client_addr      | 192.168.54.133                            连接的客户端 IP 地址
client_hostname  |                                           连接的客户端主机名
client_port      | 46930                                     连接的客户端端口号
backend_start    | 2023-07-07 09:55:36.03718+00              后端进程的启动时间
backend_xmin     |                                           后端正在执行的事务的最早活动事务ID
state            | streaming                                 连接状态，“streaming”，表示正在进行流复制。
sent_lsn         | 0/C0015D0                                 已经发送到流复制客户端的日志序列号
write_lsn        | 0/C0015D0                                 已经写入到磁盘上的日志序列号
flush_lsn        | 0/C0015D0                                 已经刷写到磁盘上的日志序列号
replay_lsn       | 0/C0015D0                                 当前正在重放的日志序列号
write_lag        |                                           写入延迟时间
flush_lag        |                                           刷写延迟时间
replay_lag       |                                           重放延迟时间
sync_priority    | 2                                         流复制同步优先级
sync_state       | sync                                      流复制同步状态，同步
reply_time       | 2023-07-07 09:59:23.630003+00             最后一次从流复制客户端收到响应的时间
-[ RECORD 2 ]----+------------------------------
pid              | 1425
usesysid         | 16385
usename          | repmgr
application_name | pg-2
client_addr      | 192.168.54.137
client_hostname  | 
client_port      | 46930                                     连接的客户端端口号
backend_start    | 2023-07-07 09:55:56.587942+00
backend_xmin     | 
state            | streaming
sent_lsn         | 0/C0015D0
write_lsn        | 0/C0015D0
flush_lsn        | 0/C0015D0
replay_lsn       | 0/C0015D0
write_lag        | 
flush_lag        | 
replay_lag       | 
sync_priority    | 3
sync_state       | sync
reply_time       | 2023-07-07 09:59:23.633182+00
```

查看run后有什么库被创建

```
\l
```

```
postgres=# \l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-----------+----------+----------+-------------+-------------+-----------------------
 postgres  | manage   | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =Tc/manage           +
           |          |          |             |             | manage=CTc/manage
 repmgr    | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
(4 rows)

Name（名称）                    这是数据库的名称，用于唯一地标识该数据库。
Owner（所有者）                  这是拥有该数据库的用户或角色。
Encoding（编码）                这是数据库中存储数据所使用的字符编码方式。编码决定了如何将文本转换为字节序列进行存储和检索。
Collate（排序规则）              排序规则定义了如何对文本进行排序。它决定了在字符串比较时应该考虑哪些因素，如大小写敏感性和重                                音符号等。
Ctype（字符分类）                字符分类定义了如何对字符进行分类和比较。它与排序规则密切相关，用于确定如何对字符进行等效性                                  比较。
postgres                   普通用户的库
repmgr                     同步复制的库
template1                  系统默认的模板数据库
template0                  系统默认的模板数据库，提供了一个干净的模板，没有任何用户自定义的结构和数据
```

数据库基础命令

```
1、列举数据库：\l
2、选择数据库：\c 数据库名
3、查看该某个库中的所有表：\dt
4、切换数据库：\c interface
5、查看某个库中的某个表结构：\d 表名
6、查看某个库中某个表的记录：select * from apps limit 1;
7、显示字符集：\encoding
8、退出psgl：\q
postgres=# \help         // 获取SQL命令的帮助,同 \h
postgres=# \quit         // 退出,同 \q
postgres=# \password dlf // 重新设置用户dlf的密码,然后需要 \q退出后才生效
c:\>psql exampledb < user.sql  // 将user.sql文件导入到exampled数据库中
postgres=# \h select   // 精细显示SQL命令中的select命令的使用方法
postgres=# \l          // 显示所有数据库
postgres=# \dt         // 显示当前数据库中的所有表
postgres=# \d [table_name]  // 显示当前数据库的指定表的表结构
postgres=# \c [database_name]  // 切换到指定数据库,相当于use
postgres=# \du                 // 显示所有用户
postgres=# \conninfo           // 显示当前数据库和连接信息
postgres=# \e   // 进入记事本sql脚本编辑状态(输入批命令后关闭将自动在命令行中执行)
postgres=# \di  // 查看索引(要建立关联)
postgres=# \prompt [文本] 名称    // 提示用户设定内部变数
postgres=# \encoding [字元编码名称]  // 显示或设定用户端字元编码
*可以将存储过程写在文本文件中aaa.sql,然后在psql状态下:
postgres=# \i aaa.sql    // 将aaa.sql导入(到当前数据库)
postgres=# \df           // 查看所有存储过程（函数）
postgres=# \df+ name     // 查看某一存储过程
postgres=# select version();            // 获取版本信息
postgres=# select usename from pg_user; // 获取系统用户信息
postgres=# drop User 用户名             // 删除用户
create database [数据库名];

*删除数据库：
drop database [数据库名]; 

*创建表：
create table ([字段名1] [类型1] ;,[字段名2] [类型2],......<,primary key (字段名m,字段名n,...)>;);

*在表中插入数据：
insert into 表名 ([字段名m],[字段名n],......) values ([列m的值],[列n的值],......);

*显示表内容:
select * from student;

*重命名一个表：
alter table [表名A] rename to [表名B];

*删除一个表：
drop table [表名]; 

*在已有的表里添加字段：
alter table [表名] add column [字段名] [类型];

*删除表中的字段：
alter table [表名] drop column [字段名];

*重命名一个字段： 
alter table [表名] rename column [字段名A] to [字段名B];

*给一个字段设置缺省值： 
alter table [表名] alter column [字段名] set default [新的默认值];

*去除缺省值： 
alter table [表名] alter column [字段名] drop default;
 
*修改表中的某行某列的数据：
update [表名] set [目标字段名]=[目标值] where [该行特征];

*删除表中某行数据：
delete from [表名] where [该行特征];
delete from [表名];    // 删空整个表

*可以使用pg_dump和pg_dumpall来完成。比如备份sales数据库：
pg_dump drupal>/opt/Postgresql/backup/1.bak
```

### 数据库初始化

```
首先创建nacos库，导入pqsql-nacos.sql

创建auth库，导入auth.sql

创建management库,导入pqsql-manage.sql、dict_data.sql、dict.sql

创建xxl_job库,导入pgsql-xxl_job.sql

创建agent库,导入agent.sql       
```

![image-20230726222227115](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230726222227115.png)

## pgpool

### 部署

```
version: '3'
services:
  pgpool:
    image: bitnami/pgpool:latest
    ports:
      - 9999:5432
    volumes:
      - /etc/hosts:/etc/hosts
    environment:
      - PGPOOL_BACKEND_NODES=0:pg-0:5432,1:pg-1:5432,2:pg-2:5432
      - PGPOOL_SR_CHECK_USER=repmgr
      - PGPOOL_SR_CHECK_PASSWORD=qwert123
      - PGPOOL_ENABLE_LDAP=no
      - PGPOOL_ADMIN_USERNAME=admin
      - PGPOOL_ADMIN_PASSWORD=qwert123
      - PGPOOL_POSTGRES_USERNAME=postgres
      - PGPOOL_POSTGRES_PASSWORD=qwert123
      - PGPOOL_ENABLE_LOAD_BALANCING=yes
    extra_hosts:
      - "pg-0:192.168.55.12"
      - "pg-1:192.168.55.16"
      - "pg-2:192.168.55.20"
    healthcheck:
      test: ["CMD", "/opt/bitnami/scripts/pgpool/healthcheck.sh"]
      interval: 10s
      timeout: 5s
      retries: 5
    deploy:
      replicas: 3
```

### 验证

```
启动
docker-compose -f docker-compose.yml up -d
查看是否正常启动
docker ps
```

```
登录pgpool
 psql -h pg-0  -p 9999 -U postgres 
 
 
 使用show命令检查pgpool信息

show pool_status; : 查看配置信息
show pool_nodes; : 查看后端数据库节点信息
show pool_processes; : 查看进程信息
show pool_pools; : 显示连接池的各个连接信息
show pool_version; : 显示版本
```

![image-20230725163856015](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230725163856015.png)

```

-dit                                                  这些选项分别表示在后台运行容器、分配一个伪终端和打开标准输入流。
--restart always                                           指示容器在退出时总是重新启动。
--name pgpool                                                    指定容器的名称为 pgpool。
--env                                                     用于设置容器的环境变量。该命令中有多个环境变量设置，包括：

PGPOOL_BACKEND_NODES                                         指定 Pgpool 的后端节点（数据库节点）的信息。这里配置了三个节点，分别为 pg-                                                                0:5432、 pg-1:5432 和 pg-2:5432。
PGPOOL_SR_CHECK_USER 和 PGPOOL_SR_CHECK_PASSWORD             用于设置 Pgpool 检查后端节点状态的用户凭证。
PGPOOL_ENABLE_LDAP                                            用于启用或禁用 LDAP 认证，这里设置为禁用（no）。
PGPOOL_POSTGRES_USERNAME 和 PGPOOL_POSTGRES_PASSWORD             设置用于管理 PostgreSQL 数据库的用户名和密码。
PGPOOL_ADMIN_USERNAME 和 PGPOOL_ADMIN_PASSWORD                       设置用于访问 Pgpool 管理界面的管理员用户名和密码。
--add-host                                                       用于将容器内的节点名称映射到主机的 IP 地址。在这里添加了三个节点，分别为                                                                    node-01、 node-02 和 node-03，对应的 IP 地址分别为                                                                                  192.168.54.130、192.168.54.133 和 192.168.54.137。
-p 5444:5432                                                       将主机端口 5444 映射到容器内的 PostgreSQL 默认端口 5432。

PGPOOL_BACKEND_NODES                                         指定 Pgpool 的后端节点（数据库节点）信息。
PGPOOL_SR_CHECK_USER 和 PGPOOL_SR_CHECK_PASSWORD            用于设置 Pgpool 检查后端节点状态的用户凭证。
PGPOOL_ENABLE_LDAP                                             用于启用或禁用 LDAP 认证。
PGPOOL_POSTGRES_USERNAME 和 PGPOOL_POSTGRES_PASSWORD               设置用于管理 PostgreSQL 数据库的用户名和密码。
PGPOOL_ADMIN_USERNAME 和 PGPOOL_ADMIN_PASSWORD                     设置用于访问 Pgpool 管理界面的管理员用户名和密码。
--add-host                                                       用于将容器内的节点名称映射到主机的 IP 地址。
-p 5444:5432                                                          将主机端口 5444 映射到容器内的 PostgreSQL 默认端口 5432。
bitnami/pgpool:latest                                                      指定要使用的 Pgpool 镜像。
```

```
show pool_nodes; : 查看后端数据库节点信息
node_id：Pgpool节点的编号。
hostname：Pgpool节点的主机名或 IP 地址。
port：Pgpool节点的监听端口号。
status：Pgpool节点的状态。在此结果中为waiting，表示该节点当前处于等待状态，可用于连接请求。
pg_status：Pgpool节点连接到的PostgreSQL节点的状态。
lb_weight：负载均衡节点的权重。该值表示在负载均衡操作中该节点的相对权重。在此结果中值为0.333333。
role：该Pgpool节点的角色。在此结果中为standby，表示该节点是一个备用节点。
pg_role：该Pgpool节点连接到的PostgreSQL节点的角色。
select_cnt：在负载均衡操作中该节点的选择计数器。
load_balance_node：表示该节点是否用于负载均衡。
replication_state：复制状态，显示节点的当前复制状态。
replication_sync_state：复制同步状态，显示节点的当前复制同步状态。
last_status_change：最后状态更改时间，表示节点状态最后一次变更的时间。
在你提供的示例中，具体的字段信息包括节点编号为1，主机名为pg-1，端口为5432，状态为waiting，连接的PostgreSQL节点状态为down。该节点的负载均衡权重为0.333333，角色为standby，连接的PostgreSQL节点的角色为unknown。选择计数器为0，不参与负载均衡操作。该节点不用于负载均衡(load_balance_node为false)，复制状态和复制同步状态为空。最后状态更改时间为2023-07-06 07:13:08。


-[ RECORD 2 ]----------+-------------------- 
node_id                | 1                                        Pgpool节点的编号
hostname               | pg-1                                     Pgpool节点的主机名或 IP 地址。
port                   | 5432                                     Pgpool节点的监听端口号
status                 | waiting                          Pgpool节点的状态。在此结果中为waiting，表示该节点当前处于                                                          等待状态，可用于连接请求
pg_status              | down                                   Pgpool节点连接到的PostgreSQL节点的状态
lb_weight              | 0.333333                      负载均衡节点的权重。该值表示在负载均衡操作中该节点的相对权重。                                                        在此结果中值为0.333333。
role                   | standby                         该Pgpool节点的角色。在此结果中为standby，表示该节点是一个                                                           备用节点
pg_role                | unknown                         该Pgpool节点连接到的PostgreSQL节点的角色
select_cnt             | 0                                  在负载均衡操作中该节点的选择计数器
load_balance_node      | false                             表示该节点是否用于负载均衡

...skipping 1 line
replication_state      |                                         复制状态，显示节点的当前复制状态
replication_sync_state |                                         复制同步状态，显示节点的当前复制同步状态
last_status_change     | 2023-07-06 07:13:08                        最后状态更改时间，表示节点状态最后一次变更的时间
```

# 5 消息队列

## 环境准备

#### 跨主机基于Docker Swarm 集群

- 采用三台或以上服务器实现整个 Docker Swarm 集群。

- Pulsar 使用 Docker 接入 Swarm 网络部署，不使用 Swarm 进行服务编排。

- APP 服务使用 Swarm 进行编排。

  #### 角色分配

  - node-01:`192.168.30.10`
  - node-02:`192.168.30.11`
  - node-03:`192.168.30.12`

#### 软件及版本

```
docker     24.0.4
镜像        apachepulsar/pulsar-all:latest或apachepulsar/pulsar:latest
```

#### 部署Swarm集群

在 `node-01` 执行命令：

```
docker swarm init --advertise-addr 192.168.30.10 --listen-addr 192.168.30.10
```

可看到返回加入 Swarm 集群的命令：

```
Swarm initialized: current node (dic2wg88o13jbjxod6oh0qxdy) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-655ujo9pb22s0u329itecjf8u8lzmenadsuqlluu9xeqabdnwe-0t2yh3v86h2gdght3r4gtvamp 192.168.30.10:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
```

> ​	注意，此时的 token 是用于加入 `worker` 节点，并非我们需要加入 `manager` 节点的 token。

在 `node-01` 获取加入管理节点命令：

```
docker swarm join-token manager
```

> ​	如果想要获取加入 `worker` 节点的 token，将命令改成 `docker swarm join-token worker` 即可。

可看到返回加入管理节点的命令：

```
To add a manager to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-655ujo9pb22s0u329itecjf8u8lzmenadsuqlluu9xeqabdnwe-f5dlwk5ohwdj16rckokrzdumq 192.168.30.10:2377
```

分别在 `node-02` 和 `node-03` 执行加入管理节点的命令：

```
docker swarm join --token SWMTKN-1-655ujo9pb22s0u329itecjf8u8lzmenadsuqlluu9xeqabdnwe-f5dlwk5ohwdj16rckokrzdumq 192.168.30.10:2377
```

如无意外，可看到添加成功的信息：

```
This node joined a swarm as a manager.
```

回到 `node-01` 执行 `docker node ls` 命令查看节点情况：

```
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
dic2wg88o13jbjxod6oh0qxdy *   node-01    Ready     Active         Leader           20.10.16
jcs2sl9qigmliojpt437hssdm     node-02    Ready     Active         Reachable        20.10.16
un7e0bfo5i22uc0xss2apqtcx     node-03    Ready     Active         Reachable        20.10.16
```

可看到 `node-01` 在 `MANAGER` 标注了 `*` 和 `Leader`，说明此时的管理和领导节点均是 `node-01`。

> - `ID`：节点 ID，节点的唯一标识符。
> - `HOSTNAME`：节点的主机名。
> - `STATUS`：节点状态。
> - `AVAILABILITY`：表示调度程序是否可以将任务分配给节点。
>   - `Active`：可以将任务分配给该节点。
>   - `Pause`：调度程序不向该节点分配新任务，但现有任务仍然运行。
>   - `Drain`：调度程序不向该节点分配新任务，已经存在的任务也将被调用到 `Active` 节点上。
> - `MANAGER STATUS`：表示是否参与集群的管理（没有值则代表不参与）。
>   - `Leader`：代表为集群做出所有的集群管理和编排决策。
>   - `Reachable`：表示该节点为参与 `Raft` 仲裁的 `manager` 节点。如果 `Leader` 节点不可用，则该节点有资格成为新的 `Leader` 节点。
>   - `Unavailable`：表示该节点是一个无法与其他 `manager` 通信的节点。如果 `manager` 节点变为此状态，则应该添加一个新的 `manager` 节点到集群中，或者将一个工作节点提升为一个 `manager`。

 



## 方法一：

### 创建Overlay网络

在任一管理节点执行如下命令创建名为 `myapp` 的 overlay 网络：

```
docker network create -d overlay  --attachable  myapp
```

> ​	`--attachable` 声明当前创建的网络为：其他节点可以访问的网络。

网络创建完成后，在任一管理节点执行 `docker network ls` 可以看到创建完成的 `myapp` 网络：

```
NETWORK ID     NAME              DRIVER    SCOPE
4a72bbeffbb8   bridge            bridge    local
4745b6b1d9f9   docker_gwbridge   bridge    local
477401a250c1   host              host      local
tgureb3sg8oz   ingress           overlay   swarm
2kekj9ksfrnx   myapp             overlay   swarm
```

#### 创建目录 

为便于数据管理，切换到 pulsar 用户创建数据目录

```
mkdir -p /home/pulsar/zookeeper/{data,log} /home/pulsar/bookkeeper/{journal,ledgers}
```

环境清理可能用到的命令

```
docker stop zookeeper
docker rm zookeeper
docker stop bookkeeper
docker rm bookkeeper
docker stop broker
docker rm  broker
rm -rf /home/pulsar/bookkeeper/*
rm -rf /root/zookeeper
rm -rf /root/broker
rm -rf /root/bookkeeper
```

### Zookeeper集群(调度)

#### 启动容器

分别在三台节点启动 zookeeper 容器：

node-01

```
docker run -itd --user=root --net=myapp -p 2181:2181 -p 28000:8000  \
-e metadataStoreUrl=zk:zookeeper01:2181,zookeeper02:2181,zookeeper03:2181 \
-e cluster-name=pulsar-cluster \
-v /home/pulsar/zookeeper/data:/pulsar/data/zookeeper \
--restart=always \
--name zookeeper --hostname zookeeper01 \
apachepulsar/pulsar-all:latest \
bash -c "echo 1 > data/zookeeper/myid && \
echo 'client.sasl=false' >> conf/zookeeper.conf && \
echo 'server.1=zookeeper01:2888:3888' >> conf/zookeeper.conf && \
echo 'server.2=zookeeper02:2888:3888' >> conf/zookeeper.conf && \
echo 'server.3=zookeeper03:2888:3888' >> conf/zookeeper.conf && \
bin/apply-config-from-env.py conf/zookeeper.conf && bin/generate-zookeeper-config.sh conf/zookeeper.conf && exec bin/pulsar zookeeper"
```

node-02

```
docker run -itd --user=root --net=myapp  -p 2181:2181 -p 28000:8000  \
-e metadataStoreUrl=zk:zookeeper01:2181,zookeeper02:2181,zookeeper03:2181 \
-e cluster-name=pulsar-cluster \
-v /home/pulsar/zookeeper/data:/pulsar/data/zookeeper \
--restart=always \
--name zookeeper --hostname zookeeper02 \
apachepulsar/pulsar-all:latest \
bash -c "echo 2 > data/zookeeper/myid && \
echo 'client.sasl=false' >> conf/zookeeper.conf && \
echo 'server.1=zookeeper01:2888:3888' >> conf/zookeeper.conf && \
echo 'server.2=zookeeper02:2888:3888' >> conf/zookeeper.conf && \
echo 'server.3=zookeeper03:2888:3888' >> conf/zookeeper.conf && \
bin/apply-config-from-env.py conf/zookeeper.conf && bin/generate-zookeeper-config.sh conf/zookeeper.conf && exec bin/pulsar zookeeper"
```

node-03

```
docker run -itd --user=root --net=myapp -p 2181:2181  -p 28000:8000 \
-e metadataStoreUrl=zk:zookeeper01:2181,zookeeper02:2181,zookeeper03:2181 \
-e cluster-name=pulsar-cluster \
-v /home/pulsar/zookeeper/data:/pulsar/data/zookeeper \
--restart=always \
--name zookeeper --hostname zookeeper03 \
apachepulsar/pulsar-all:latest \
bash -c "echo 3 > data/zookeeper/myid && \
echo 'client.sasl=false' >> conf/zookeeper.conf && \
echo 'server.1=zookeeper01:2888:3888' >> conf/zookeeper.conf && \
echo 'server.2=zookeeper02:2888:3888' >> conf/zookeeper.conf && \
echo 'server.3=zookeeper03:2888:3888' >> conf/zookeeper.conf && \
bin/apply-config-from-env.py conf/zookeeper.conf && bin/generate-zookeeper-config.sh conf/zookeeper.conf && exec bin/pulsar zookeeper"
```

注意：3 个 zookeeper 启动命令，`--hostname` 和 `myid` 是根据节点来对应角色规划来设置的，并非是一致的。

如果将容器日志输出到文件，在启动命令前加上 `export PULSAR_LOG_APPENDER=RollingFile` 即可

#### 初始化集群元数据

在任一节点执行初始化元数据操作：

```
docker run --user=root --net=myapp \
--name initialize-pulsar-cluster-metadata \
apachepulsar/pulsar-all:latest \
bash -c "bin/pulsar initialize-cluster-metadata \
--cluster pulsar-cluster \
--zookeeper zookeeper01:2181,zookeeper02:2181,zookeeper03:2181 \
--configuration-store zookeeper01:2181,zookeeper02:2181,zookeeper03:2181 \
--web-service-url broker01:8080,broker02:8080,broker03:8080 \
--broker-service-url pulsar://broker01:6650,broker02:6650,broker03:6650"
```

等待一会可看到如下信息输出，说明初始化完毕：

```
INFO  org.apache.bookkeeper.stream.storage.impl.cluster.ZkClusterInitializer - Successfully initialized the stream cluster :
num_storage_containers: 16

INFO  org.apache.pulsar.PulsarClusterMetadataSetup - Cluster metadata for 'pulsar-cluster' setup correctly
```

### Bookkeeper集群(存储)

BookKeeper 是一种优化实时工作负载的存储服务，具有可扩展、高容错、低延迟的特点。

- 以极低的延迟（小于 5 毫秒）读写 entry 流
- 能够持久、一致、容错地存储数据
- 在写数据时，能够进行流式传输或追尾传输
- 有效地存储、访问历史数据与实时数据
- ![image-20230720174922014](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230720174922014.png)

#### 启动容器

在三台节点上启动 bookkeeper 容器：

- node-01

```
docker run -itd --user=root --net=myapp \
-v /home/pulsar/bookkeeper/journal:/pulsar/data/bookkeeper/journal \
-v /home/pulsar/bookkeeper/ledgers:/pulsar/data/bookkeeper/ledgers \
-e zkServers=zookeeper01:2181,zookeeper02:2181,zookeeper03:2181 \
-e metadataStoreUrl=zk:zookeeper01:2181,zookeeper02:2181,zookeeper03:2181  \
--restart=always \
--name bookkeeper \
--hostname bookkeeper01 \
apachepulsar/pulsar-all:latest \
bash -c "sed -i 's/# extraServerComponents=/extraServerComponents=org.apache.bookkeeper.stream.server.StreamStorageLifecycleComponent/g' conf/bookkeeper.conf && \
sed -i 's/prometheusStatsHttpPort=8000/prometheusStatsHttpPort=8001/g' conf/bookkeeper.conf && \
sed -i "s/advertisedAddress=/advertisedAddress=bookkeeper01/g" conf/bookkeeper.conf && \
sed -i 's/httpServerPort=8000/httpServerPort=8002/g' conf/bookkeeper.conf && \
bin/apply-config-from-env.py conf/bookkeeper.conf && exec bin/pulsar bookie"
```

- node-02

  ```
  docker run -itd --user=root --net=myapp \
  -v /home/pulsar/bookkeeper/journal:/pulsar/data/bookkeeper/journal \
  -v /home/pulsar/bookkeeper/ledgers:/pulsar/data/bookkeeper/ledgers \
  -e zkServers=zookeeper01:2181,zookeeper02:2181,zookeeper03:2181 \
  -e metadataStoreUrl=zk:zookeeper01:2181,zookeeper02:2181,zookeeper03:2181  \
  --restart=always \
  --name bookkeeper \
  --hostname bookkeeper02 \
  apachepulsar/pulsar-all:latest \
  bash -c "sed -i 's/# extraServerComponents=/extraServerComponents=org.apache.bookkeeper.stream.server.StreamStorageLifecycleComponent/g' conf/bookkeeper.conf && \
  sed -i 's/prometheusStatsHttpPort=8000/prometheusStatsHttpPort=8001/g' conf/bookkeeper.conf && \
  sed -i "s/advertisedAddress=/advertisedAddress=bookkeeper02/g" conf/bookkeeper.conf && \
  sed -i 's/httpServerPort=8000/httpServerPort=8002/g' conf/bookkeeper.conf && \
  bin/apply-config-from-env.py conf/bookkeeper.conf && exec bin/pulsar bookie"
  ```

- node-03

```
docker run -itd --user=root --net=myapp \
-v /home/pulsar/bookkeeper/journal:/pulsar/data/bookkeeper/journal \
-v /home/pulsar/bookkeeper/ledgers:/pulsar/data/bookkeeper/ledgers \
-e zkServers=zookeeper01:2181,zookeeper02:2181,zookeeper03:2181 \
-e metadataStoreUrl=zk:zookeeper01:2181,zookeeper02:2181,zookeeper03:2181  \
--restart=always \
--name bookkeeper \
--hostname bookkeeper03 \
apachepulsar/pulsar-all:latest \
bash -c "sed -i 's/# extraServerComponents=/extraServerComponents=org.apache.bookkeeper.stream.server.StreamStorageLifecycleComponent/g' conf/bookkeeper.conf && \
sed -i 's/prometheusStatsHttpPort=8000/prometheusStatsHttpPort=8001/g' conf/bookkeeper.conf && \
sed -i "s/advertisedAddress=/advertisedAddress=bookkeeper03/g" conf/bookkeeper.conf && \
sed -i 's/httpServerPort=8000/httpServerPort=8002/g' conf/bookkeeper.conf && \
bin/apply-config-from-env.py conf/bookkeeper.conf && exec bin/pulsar bookie"
```

在三台节点都启动后，在任一节点执行 `docker logs -f bookkeeper` 可看到类似如下关键日志输出：

```
INFO  org.apache.bookkeeper.proto.PerChannelBookieClient - Successfully connected to bookie: bookkeeper01:3181 [id: 0x2d587be5, L:/10.0.1.9:41048 - R:bookkeeper01/10.0.1.9:3181]
INFO  org.apache.bookkeeper.proto.PerChannelBookieClient - Successfully connected to bookie: bookkeeper02:3181 [id: 0xb4980f09, L:/10.0.1.9:32810 - R:bookkeeper02/10.0.1.10:3181]
INFO  org.apache.bookkeeper.proto.PerChannelBookieClient - Successfully connected to bookie: bookkeeper03:3181 [id: 0x0d814823, L:/10.0.1.9:53252 - R:bookkeeper03/10.0.1.11:3181]
```

#### 初始化元数据

在任一节点执行初始化元数据操作：

```
docker exec -i --user=root \
bookkeeper \
bash -c "bin/bookkeeper shell metaformat"
```

等待执行过程中，根据提示输入 `Y` 即可看到如下 `Successfully formatted BookKeeper metadata` 日志信息：

```
2023-07-01T23:57:45,753+0000 [main-EventThread] INFO  org.apache.bookkeeper.zookeeper.ZooKeeperWatcherBase - ZooKeeper client is connected now.
Ledger root already exists. Are you sure to format bookkeeper metadata? This may cause data loss. (Y or N) Y
2023-07-01T23:58:16,037+0000 [main] INFO  org.apache.bookkeeper.discover.ZKRegistrationManager - Successfully formatted BookKeeper metadata
2023-07-01T23:58:16,176+0000 [main] INFO  org.apache.zookeeper.ZooKeeper - Session: 0x200013ad91a0006 closed
2023-07-01T23:58:16,176+0000 [main-EventThread] INFO  org.apache.zookeeper.ClientCnxn - EventThread shut down for session: 0x200013ad91a0006
```

### Broker集群(计算)

Broker是Pulsar的核心组件，负责接收、存储和传递消息。它是一个高性能的消息传递引擎，支持多租户、持久化存储、消息复制和负载均衡等功能。Broker负责接收来自生产者的消息，将其持久化存储，并将消息传递给相应的消费者

#### 启动容器

在三台节点上启动 broker 容器：

- node-01

  ```
  docker run -itd --user=root --net=myapp -p 6650:6650 -p 8080:8080 \
  -e metadataStoreUrl=zk:zookeeper01:2181,zookeeper02:2181,zookeeper03:2181 \
  --restart=always \
  --name broker \
  --hostname broker01 \
  apachepulsar/pulsar-all:latest \
  bash -c "sed -i 's/clusterName=/clusterName=pulsar-cluster/g' conf/broker.conf && \
  sed -i 's/bindAddress=0.0.0.0/bindAddress=broker01/g' conf/broker.conf && \
  bin/apply-config-from-env.py conf/broker.conf && exec bin/pulsar broker"
  ```

- node-02

  ```
  docker run -itd --user=root --net=myapp -p 6650:6650 -p 8080:8080 \
  -e metadataStoreUrl=zk:zookeeper01:2181,zookeeper02:2181,zookeeper03:2181 \
  --restart=always \
  --name broker \
  --hostname broker02 \
  apachepulsar/pulsar-all:latest \
  bash -c "sed -i 's/clusterName=/clusterName=pulsar-cluster/g' conf/broker.conf && \
  sed -i 's/bindAddress=0.0.0.0/bindAddress=broker02/g' conf/broker.conf && \
  bin/apply-config-from-env.py conf/broker.conf && exec bin/pulsar broker"
  ```
  
- node-03

```
docker run -itd --user=root --net=myapp -p 6650:6650 -p 8080:8080 \
-e metadataStoreUrl=zk:zookeeper01:2181,zookeeper02:2181,zookeeper03:2181 \
--restart=always \
--name broker \
--hostname broker03 \
apachepulsar/pulsar-all:latest \
bash -c "sed -i 's/clusterName=/clusterName=pulsar-cluster/g' conf/broker.conf && \
sed -i 's/bindAddress=0.0.0.0/bindAddress=broker03/g' conf/broker.conf && \
bin/apply-config-from-env.py conf/broker.conf && exec bin/pulsar broker"
```

等待启动完成后，可看到 pulsar 服务已启动完成的日志输出：

```
INFO  org.apache.pulsar.PulsarBrokerStarter - PulsarService started.
```

## 方法二：

可以通过docker stack deploy -c 来搭建消息队列集群

[Docker](https://www.xinbaoku.com/docker/) Stack 为解决该问题而生，Docker Stack 通过提供期望状态、滚动升级、简单易用、扩缩容、健康检查等特性简化了应用的管理，这些功能都封装在一个完美的声明式模型当中

如果了解Docker Compose，就会发现Docker Stack非常简单。事实上在许多方面，Stack一直是期望的Compose——完全集成到Docker中，并能够管理应用的整个生命周期

从体系结构上来讲，Stack位于Docker应用层级的最顶端。Stack基于服务进行构建，而服务又基于容器

[Docker Stack命令 (xinbaoku.com)](https://www.xinbaoku.com/archive/Bea4Fqc6.html)

![image-20230725164830072](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230725164830072.png)

```
常用命令：
docker stsack deploy
用于根据 Stack 文件（通常是 docker-stack.yml）部署和更新 Stack 服务的命令。
docker stack ls
会列出 Swarm 集群中的全部 Stack，包括每个 Stack 拥有多少服务。
docker stack ps
列出某个已经部署的 Stack 相关详情。该命令支持 Stack 名称作为其主要参数，列举了服务副本在节点的分布情况，以及期望状态和当前状态。
docker stack rm
命令用于从 Swarm 集群中移除 Stack。移除操作执行前并不会进行二次确认。
docker stack services <stack_name>
查看<service_id>
docker service logs <service_id>
查看日志
```

#### 部署准备

以下操作都在主节点运行

将pulsar-docker.tar包放到虚拟机上，并解压

```
[root@node-01 pulsar]# ll
total 28
drwxr-xr-x. 2 root root     6 Jul 20 02:47 admin
drwxr-xr-x. 2 root root    32 Jul 25 03:50 bookkeeper
drwxr-xr-x. 2 root root    32 Jul 25 03:52 broker
-rw-r--r--. 1 root root 12737 Jul 19 04:14 docker-compose.tmp
-rw-r--r--. 1 root root  4769 Jul 19 22:32 docker-compose.yml
drwxr-xr-x. 2 root root    32 Jul 20 06:28 proxy
-rw-r--r--. 1 root root  2033 Jul 20 21:32 pulsar.tar.gz
drwxr-xr-x. 2 root root    32 Jul 25 02:48 zookeeper
```

#### 部署zookeeper

进入解压后的zookeeper目录

![image-20230725165401658](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230725165401658.png)

编辑docker-compose.yml

```
将constraints: [ node.hostname == node1 ]/constraints: [ node.hostname == node2 ]/constraints: [ node.hostname == node3 ]改为相对应的主机名（所部署的虚拟机主机名）

执行命令
docker stack deploy -c docker-compose.yml pulsar
开始部署（一定要创建好swarm环境，不然会报错）

检查是否成功
docker stack ps pulsar
[root@node-01 zookeeper]# docker stack ps pulsar
ID             NAME                   IMAGE                        NODE      DESIRED STATE   CURRENT STATE               ERROR     PORTS              
b1i4sa8xg9ai   pulsar_zookeeper01.1   apachepulsar/pulsar:latest   node-01   Running         Running 2 hours ago                   
oplsd40z6y1i   pulsar_zookeeper02.1   apachepulsar/pulsar:latest   node-02   Running         Running 2 hours ago                   
03683o820ll2   pulsar_zookeeper03.1   apachepulsar/pulsar:latest   node-03   Running         Running 2 hours ago 
如上所示即成功，并且在其他节点docker ps也有输出
[root@node-02 ~]# docker ps
c369cde09f6f   apachepulsar/pulsar:latest     "bash -c 'bin/apply-…"   2 hours ago         Up 2 hours (healthy)                                               pulsar_zookeeper02.1.oplsd40z6y1izsqm276vptgt9

```

#### 部署Bookkeeper

进入解压后的Bookkeeper目录

![image-20230725170016624](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230725170016624.png)

编辑docker-compose.yml

```
将constraints: [ node.hostname == node1 ]/constraints: [ node.hostname == node2 ]/constraints: [ node.hostname == node3 ]改为相对应的主机名（所部署的虚拟机主机名）

执行命令
docker stack deploy -c docker-compose.yml pulsar
开始部署（一定要创建好swarm环境，不然会报错）

检查是否成功
docker stack ps pulsar
[root@node-01 zookeeper]# docker stack ps pulsar
ID             NAME                   IMAGE                        NODE      DESIRED STATE   CURRENT STATE               ERROR     PORTS              
11pjjir2h5oz   pulsar_bookie01.1      apachepulsar/pulsar:latest   node-01   Running         Running about an hour ago             
8b286cpdzren   pulsar_bookie02.1      apachepulsar/pulsar:latest   node-02   Running         Running about an hour ago             
wso2xbqzuwv3   pulsar_bookie03.1      apachepulsar/pulsar:latest   node-03   Running         Running about an hour ago  
如上所示即成功，并且在其他节点docker ps也有输出
[root@node-02 ~]# docker ps
3645e070ea8c   apachepulsar/pulsar:latest     "bash -c 'bin/apply-…"   About an hour ago   Up About an hour                                                   pulsar_bookie02.1.8b286cpdzrenrducbfd847ujj
```

#### 部署broker

进入解压后的broker目录

![image-20230725170207275](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230725170207275.png)

编辑docker-compose.yml

```
将constraints: [ node.hostname == node1 ]/constraints: [ node.hostname == node2 ]/constraints: [ node.hostname == node3 ]改为相对应的主机名（所部署的虚拟机主机名）

执行命令
docker stack deploy -c docker-compose.yml pulsar
开始部署（一定要创建好swarm环境，不然会报错）

检查是否成功
docker stack ps pulsar
[root@node-01 zookeeper]# docker stack ps pulsar
ID             NAME                   IMAGE                        NODE      DESIRED STATE   CURRENT STATE               ERROR     PORTS              
rp62f74nwqjg   pulsar_broker01.1      apachepulsar/pulsar:latest   node-01   Running         Running about an hour ago             
xej0hy7j1dip   pulsar_broker02.1      apachepulsar/pulsar:latest   node-02   Running         Running about an hour ago             
ip2muwdwzafl   pulsar_broker03.1      apachepulsar/pulsar:latest   node-03   Running         Running about an hour ago   
如上所示即成功，并且在其他节点docker ps也有输出
[root@node-02 ~]# docker ps
0c3fbaee0e42   apachepulsar/pulsar:latest     "bash -c 'bin/apply-…"   About an hour ago   Up About an hour                                                   pulsar_broker02.1.xej0hy7j1dipuq8d34z3ihg1i
```

## 验证消息队列

#### 查看Bookkeeper集群

可执行命令验证是否启动集群：

```
docker exec -i --user=root bookkeeper \
bash -c "bin/bookkeeper shell bookiesanity"
```

如果不出意外，会看到成功的提示：

```
INFO  org.apache.bookkeeper.tools.cli.commands.bookie.SanityTestCommand - Bookie sanity test succeeded
```

#### 查看Broker节点

完成启动后，即可通过 `pulsar-admin` 命令查看集群的节点情况：

```
docker exec -i --user=root broker \
bash -c "bin/pulsar-admin --admin-url http://broker01:8080 brokers list pulsar-cluster"
```

如不出意外，可看到终端显示的 broker 节点：

```
"broker01:8080"
"broker02:8080"
"broker03:8080"
```

#### 查看Cluster

**获取 Pulsar Cluster 的部署信息：**

```
docker exec -i --user=root broker \
bash -c "bin/pulsar-admin --admin-url http://broker01:8080 clusters get pulsar-cluster"
```

等待返回结果：

```
{
  "serviceUrl" : "broker01:8080,broker02:8080,broker03:8080",
  "brokerServiceUrl" : "pulsar://broker01:6650,broker02:6650,broker03:6650",
  "brokerClientTlsEnabled" : false,
  "tlsAllowInsecureConnection" : false,
  "brokerClientTlsEnabledWithKeyStore" : false,
  "brokerClientTlsTrustStoreType" : "JKS",
  "brokerClientTlsKeyStoreType" : "JKS"
}
```

**查看 Cluster 列表：**

```
docker exec -i --user=root broker \
bash -c "bin/pulsar-admin --admin-url http://broker01:8080 clusters list"
```

等待返回结果，可看到刚刚创建的集群：

```
pulsar-cluster
```

#### Hello Pulsar

到此，Pulsar 集群已搭建完成，可以进行测试了，使用 `pulsar-client` 命令生产并消费消息。

首先开启一个终端，执行消费监听，这样就可以实时查看到生产的消息，例如计划消费 100 条消息，可在 node-01 上面执行如下命令：

```
docker exec -i --user=root  broker \
bash -c "bin/pulsar-client --url pulsar://broker01:6650 consume persistent://public/default/test   -s 'first-subscription' -n 100"
```

再开一个终端，执行生产消息，例如在 node-02 上面执行如下命令：

```
docker exec -i --user=root broker \
bash -c "bin/pulsar-client --url pulsar://broker01:6650 produce \
  persistent://public/default/test \
  -n 10 \
  -m 'Hello Pulsar'"
```

此时可看到在生产端看到如下输出信息，表示已生产了一条消息：

```
INFO  org.apache.pulsar.client.cli.PulsarClientTool - 1 messages successfully produced
```

回到消费监听端，可看到已经消费了一条消息：

```
----- got message -----
key:[null], properties:[], content:Hello Pulsar
```

![image-20230719111923482](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230719111923482.png)

至此，已完成 Pulsar 集群的搭建及测试。



# 6 redis集群安装

| 密码 | r@WPbVETNb4o5 |
| :--: | :-----------: |

**创建redis目录**

```
mkdir -p /data/redis
```

**在redis目录下创建redis-cluster.tmpl模板文件**

```
vi /data/redis/redis-cluster.tmpl
三个节点都要
```

**注意cluster-announce-ip要根据本机的ip修改，内容如下：**

**节点1：**

```
port ${PORT}
masterauth tte@C3uTpYmV
requirepass tte@C3uTpYmV
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
cluster-announce-ip 192.168.30.10
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
```

节点2：

```
port ${PORT}
masterauth r@WPbVETNb4o5
requirepass r@WPbVETNb4o5
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
cluster-announce-ip 192.168.30.11
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
```

节点3：

```
port ${PORT}
masterauth r@WPbVETNb4o5
requirepass r@WPbVETNb4o5
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
cluster-announce-ip 192.168.30.12
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
```

**在每个主机节点分配端口创建配置文件及数据目录，seq 的端口为redis两个节点的端口**

节点1运行：

```
for port in `seq 6371 6372`; do mkdir -p ${port}/conf && PORT=${port} envsubst < redis-cluster.tmpl > ${port}/conf/redis.conf && mkdir -p ${port}/data;done
```

节点2运行：

```
for port in `seq 6373 6374`; do mkdir -p ${port}/conf && PORT=${port} envsubst < redis-cluster.tmpl > ${port}/conf/redis.conf && mkdir -p ${port}/data;done
```

节点3运行：

```
for port in `seq 6375 6376`; do mkdir -p ${port}/conf && PORT=${port} envsubst < redis-cluster.tmpl > ${port}/conf/redis.conf && mkdir -p ${port}/data;done
```

  **Docker**拉取redis镜像

```
docker pull redis
```

  **批量运行redis**

主机节点1运行：

```
for port in `seq 6371 6372`; do \
docker run -di --restart always --name redis-${port} --net host \
-v /data/redis/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \
-v /data/redis/${port}/data:/data \
redis redis-server /usr/local/etc/redis/redis.conf; \
done;
```

主机节点2运行：

```
for port in `seq 6373 6374`; do docker run -di --restart always --name redis-${port} --net host -v /data/redis/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf -v /data/redis/${port}/data:/data redis redis-server /usr/local/etc/redis/redis.conf; done;
```

主机节点3运行：

```
for port in `seq 6375 6376`; do docker run -di --restart always --name redis-${port} --net host -v /data/redis/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf  -v /data/redis/${port}/data:/data redis redis-server /usr/local/etc/redis/redis.conf; done
```

 **选第一台主机节点进入容器创建集群，集群地址端口要填写实际6节点的ip端口**

```
docker exec -it redis-6371 bash
```

```
\#redis-cli -a r@WPbVETNb4o5 --cluster create 192.168.30.10:6371 192.168.30.10:6372 192.168.30.11:6373 192.168.30.11:6374 192.168.30.12:6375 192.168.30.12:6376 --cluster-replicas 1
```

**询问是否设置集群**

```
Can I set the above configuration? (type 'yes' to accept): yes
输入yes
```

  **成功添加后登录redis查看**

```
\#redis-cli -c -a r@WPbVETNb4o5 -h 192.168.30.12 -p 6376
```

**查看集群信息**

```
\> cluster info
```

**显示cluster_state:ok就是创建成功：如下图所示**

![image-20230712161126034](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230712161126034.png)

# 7.应用服务环境

```
nacos变量
POSTGRESQL_IP  pg连接IP          192.168.0.24
POSTGRESQL_PORT pg连接端口        5432
POSTGRESQL_USER pg 账号          root 
POSTGRESQL_PAS SWORD pg密码      AqglZx910a!@#A

其他服务全局变量
SERVER_PORT   启动端口
SERVER_ADDR  连接nacos服务地址

镜像版本
nacos:1.0.6
consumer:1.0
agentapi:1.0
auth:1.0
gateway:1.0
xxljob:1.0.1
producer:1.0
manage:1.0
tenant:1.0
nginx:latest

docker load <agentapi-2.0.2.tar
docker load <auth.2.0.1.tar
docker load <backstage-1.0.tar
docker load <kg_nacos107.tar
docker load <managefront1.0.3.tar
docker load <tenant.2.0.1.tar
docker load <consumer2.0.1.1.tar
docker load <gateway1.0.1.tar
docker load <manage_2.0.1.1.tar
docker load <producer_2.0.1.1.tar
docker load <tenantfront.2.0.3.tar

```

## 7.1  nacos注册中心

![image-20230724230031022](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230724230031022.png)

```
docker run -itd --restart=always --name nacos  --net=myapp -p 8848:8848 -e POSTGRESQL_IP=192.168.0.24 -e POSTGRESQL_PORT=5432 -e POSTGRESQL_USER=root -e 'POSTGRESQL_PASSWORD=AqglZx910a!@#A' nacos:1.0.7
```

然后通过打隧道

![image-20230719150621618](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230719150621618.png)



然后到浏览器输入http://127.0.0.1:8848/nacos/

![image-20230719150717774](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230719150717774.png)

```
输入初始化账号密码   
nacos
nacos
```

![image-20230719150751351](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230719150751351.png)



修改数据库配置

![image-20230719151708502](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230719151708502.png)

```
url: jdbc:postgresql://192.168.0.24:5432/management
          username: root
          password: AqglZx910a!@#A
```

redis配置

![image-20230719151947620](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230719151947620.png)



```
redis:
    cluster:
      nodes:
        - 192.168.30.10:6371
        - 192.168.30.10:6372
        - 192.168.30.11:6373
        - 192.168.30.11:6374
        - 192.168.30.12:6375
        - 192.168.30.12:6376
    database: 0
    password: r@WPbVETNb4o5
```

消息队列配置

![image-20230719163149864](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230719163149864.png)



```
pulsar://192.168.30.10:6650,192.168.30.11:6650,192.168.30.12:6650
```

![image-20230719163049382](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230719163049382.png)



```
 /data/tcyunsc2023.jks  改成 /data/package/tcyunsc2023.jks
```

## 7.2  consumer 数据处理模块

```
docker run -itd --restart=always --name consumer  --net=myapp -p 7009:7009 -e SERVER_ADDR=192.168.30.10:8848 -e SERVER_PORT=7009  consumer:2.0.2.2
```

修改jeecg-consumer.yaml文件和 jeecg-consumer-dev.yaml文件（数据库、消息队列、redis配置如上）

```
数据库
jdbc:postgresql://192.168.0.24:5432/management
```

## 7.3  xxljob 定时任务模块

```
docker run -itd --restart=always --name xxljob --net=myapp -p 9080:9080 -e SERVER_ADDR=192.168.30.10:8848 -e SERVER_PORT=9080 -e POSTGRESQL_IP=192.168.0.24 -e POSTGRESQL_PORT=5432 -e POSTGRESQL_USER=root -e 'POSTGRESQL_PASSWORD=AqglZx910a!@#A'   xxljob:1.0.1
```

修改jeecg-data-dev.yaml、  jeecg-data.yaml文件

```
数据库
jdbc:postgresql://192.168.0.24:5432/xxl_job
```

![image-20230721093941692](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230721093941692.png)

```
[任务调度中心](http://127.0.0.1:9080/xxl-job-admin/toLogin)
```

![image-20230721110314739](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230721110314739.png)

默认的
admin
123456

## 7.4  agentapi 安全资源池

```
docker run -itd --restart=always --name agentapi  --net=myapp -p 7003:7003 -e SERVER_ADDR=192.168.30.10:8848 -e SERVER_PORT=7003  agentapi:2.0.2.2
```

修改jeecg-agentapi-dev.yaml、jeecg-agentapi.yaml文件

```
 数据库
 jdbc:postgresql://192.168.0.24:5432/agent
```

## 7.5  auth  认证中心

```
docker run -itd --restart=always --name auth --net=myapp  -p 7001:7001 -e SERVER_ADDR=192.168.30.10:8848 -e SERVER_PORT=7001  auth:2.0.1.5
```

修改 jeecg-auth-dev.yaml、 jeecg-auth.yaml文件

```
数据库
jdbc:postgresql://192.168.0.24:5432/auth
```

![image-20230719170606090](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230719170606090.png)

## 7.6  gateway 网关

```
docker run -itd --restart=always --name gateway  --net=myapp -p 9999:9999 -e SERVER_ADDR=192.168.30.10:8848 -e SERVER_PORT=9999  gateway:1.0.1
```

修改jeecg-gateway-router.json、jeecg-gateway-dev.yaml文件

<img src="https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230721111348347.png"/>

## 7.7  producer 消息接收模块

```
docker run -itd --restart=always --name producer --net=myapp -p 7006:7006 -e SERVER_ADDR=192.168.30.10:8848 -e SERVER_PORT=7006 producer:2.0.1.1
```

修改 jeecg-management.yaml

```
数据库
jdbc:postgresql://192.168.0.24:5432/management
```

<img src="https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230721111348347.png"/>

## 7.8  tenant 租户侧

```
docker run -itd --restart=always --name tenant --net=myapp -p 8088:8088 -e SERVER_ADDR=192.168.30.10:8848 -e SERVER_PORT=8088 tenant:2.0.2.1
```

```
容器内执行
sed -i '94s|addresses: ${XXL_JOB_ADDR:http://192.168.54.112:9080/xxl-job-admin}|addresses: ${XXL_JOB_ADDR:http://192.168.30.10:9080/xxl-job-admin}|' application.yml
```

修改tenant-service.yml、tenant-service35.yml、jeecg-tenant-dev.yaml、jeecg-tenant.yaml

```
数据库
jdbc:postgresql://192.168.0.24:5432/management
```

<img src="https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230721111348347.png"/>

## 7.9  manage 管理端

```
docker run -itd --restart=always --name manage  --net=myapp  -p 7002:7002 -e SERVER_ADDR=192.168.30.10:8848 -e SERVER_PORT=7002 -v /data/smc/server.json:/data/package/server.json manage:2.0.1.5
```

修改jeecg-management-dev.yaml、jeecg-management.yaml

```
数据库
jdbc:postgresql://192.168.0.24:5432/management
```

![image-20230721111348347](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230721111348347.png)

## backstage外网访问代理

```
docker run -itd --restart=always --name backstage --net=myapp -v /data/hosts:/etc/hosts:rw  -p 17090:17090 backstage:1.0
```

# 8.部署前端（应用参考示例）

镜像

```
tenantfront:2.0.3    managefront:1.0.3
```

hosts文件

```
::1	localhost	localhost.localdomain	localhost6	localhost6.localdomain6

127.0.0.1	localhost	localhost.localdomain	localhost4	localhost4.localdomain4
127.0.0.1	localhost	localhost
192.168.30.10   backend
```

```
可能用到的命令
docker stop tenantfront
docker rm tenantfront
```

## 8.1  managefront管理端配置文件

```
docker run -d --name managefront --restart=always  -p 19090:19090 -v /data/hosts:/etc/hosts:rw  managefront:1.3
```

## 8.2  tenantfront租客端配置文件

```
docker run -d --name tenantfront --restart=always --net=myapp  -p 18090:18090 -v /data/hosts:/etc/hosts:rw  tenantfront:2.0.2.1
```

# 9.部署完成登录

```
docker stack deploy -c
应用服务重启命令
docker restart xxljob
docker restart tenant
docker restart manage
docker restart producer
docker restart auth
docker restart agentapi
docker restart consumer
docker restart gateway
docker restart managefront
docker restart tenantfront
```

```
监控机：140.246.10.2:10222
监控机密码：E$4p7%ur3dzh
ssh 140.246.10.2:10222
```

![image-20230722173723420](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230722173723420.png)

```
然后连接192.168.30.10
ssh 192.168.30.10
密码qwerT@123
```

然后做隧道

![image-20230722173630669](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230722173630669.png)



![image-20230722173648313](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230722173648313.png)

![image-20230722173559886](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230722173559886.png)

![image-20230722173551806](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230722173551806.png)

```
浏览器打开
https://127.0.0.1:19090/

https://127.0.0.1:18090/
```

```
更新配置
docker service update monitor_prometheus
设置副本数
docker service scale prometheus=0
docker service scale prometheus=1
```

