# 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.组件安装指南

## 4.1  数据库

采用的是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"
```

pg-0数据库

```
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
```

### pgpool(未解决，待测试)

```
-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命令检查pgpool信息

show pool_status; : 查看配置信息
show pool_nodes; : 查看后端数据库节点信息
show pool_processes; : 查看进程信息
show pool_pools; : 显示连接池的各个连接信息
show pool_version; : 显示版本
```

```
登录pgpool
psql -h 192.168.55.12 -p 5444 -U  postgres
```

```
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                        最后状态更改时间，表示节点状态最后一次变更的时间
```

pgpool配置文件

```
backend_clustering_mode = 'streaming_replication'
listen_addresses = '*'
port = '5432'
unix_socket_directories = '/opt/bitnami/pgpool/tmp'
pcp_socket_dir = '/opt/bitnami/pgpool/tmp'
enable_pool_hba = 'on'
pool_passwd = 'pool_passwd'
authentication_timeout = '30'
allow_clear_text_frontend_auth = 'off'
max_pool = '15'
log_connections = 'off'
log_hostname = 'off'
log_per_node_statement = 'off'
pid_file_name = '/opt/bitnami/pgpool/tmp/pgpool.pid'
logdir = '/opt/bitnami/pgpool/logs'
load_balance_mode = 'on'
disable_load_balance_on_write = 'transaction'
statement_level_load_balance = 'off'
sr_check_period = '30'
sr_check_user = 'customuser'
sr_check_password = 'qwert123'
sr_check_database = 'postgres'
health_check_period = '30'
health_check_timeout = '10'
health_check_user = 'customuser'
health_check_password = 'qwert123'
health_check_max_retries = '5'
health_check_retry_delay = '5'
connect_timeout = '10000'
failover_command = 'echo ">>> Failover - that will initialize new primary node search!"'
failover_on_backend_error = 'off'
search_primary_node_timeout = '0'
hostname0 = ''
backend_hostname0 = 'pg-0'
backend_port0 = 5432
backend_weight0 = 1
backend_data_directory0 = '/opt/bitnami/pgpool/data'
backend_flag0 = 'ALLOW_TO_FAILOVER'
backend_hostname1 = 'pg-1'
backend_port1 = 5432
backend_weight1 = 1
backend_data_directory1 = '/opt/bitnami/pgpool/data'
backend_flag1 = 'ALLOW_TO_FAILOVER'
backend_hostname2 = 'pg-2'
backend_port2 = 5432
backend_weight2 = 1
backend_data_directory2 = '/opt/bitnami/pgpool/data'
backend_flag2 = 'ALLOW_TO_FAILOVER'

FAILOVER_ON_BACKEND_ERROR=on
PGPOOL_ENABLE_LOAD_BALANCING=yes
```

## 4.2  消息队列

### 环境准备

#### 跨主机基于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/advertisedAddress=/advertisedAddress=broker01/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/advertisedAddress=/advertisedAddress=broker02/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/advertisedAddress=/advertisedAddress=broker03/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.
```

### 验证

#### 查看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 集群的搭建及测试。



## 4.3  redis集群安装

| 密码 | tte@C3uTpYmV |
| :--: | :----------: |

**创建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 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.12
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
```

节点3：

```
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.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 tte@C3uTpYmV --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 tte@C3uTpYmV -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)

# 5.应用服务环境

```
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
```

## 5.1  nacos注册中心

```
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.11:6373
        - 192.168.30.12:6375
    database: 0
    password: tte@C3uTpYmV
```

消息队列配置

![image-20230719163149864](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230719163149864.png)



```
pulsar://broker01:6650,broker02:6650,broker03:6650
```

![image-20230719163049382](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230719163049382.png)



```
 /data/tcyunsc2023.jks  改成 /data/package/tcyunsc2023.jks
```

## 5.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:1.0
```

修改jeecg-consumer.yaml文件和 jeecg-consumer-dev.yaml文件（数据库、消息队列、redis配置如上）

## 5.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-test.yaml、 jeecg-data-prod.yaml、 jeecg-data.yaml文件

![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

## 5.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:1.0
```

修改jeecg-agentapi-dev.yaml、jeecg-agentapi.yaml文件

## 5.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:1.0
```

修改jeecg-auth-prod.yaml、jeecg-auth-test.yaml、 jeecg-auth-dev.yaml、 jeecg-auth.yaml文件

![image-20230719170606090](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230719170606090.png)

## 5.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-prod.yaml、jeecg-gateway-test.yaml、jeecg-gateway-router.json、jeecg-gateway-dev.yaml文件

<img src="https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230721111348347.png"/>

## 5.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:1.0
```

修改 jeecg-management.yaml

<img src="https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230721111348347.png"/>

## 5.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:1.0 bash -c "sed -i '93s|addresses: ${XXL_JOB_ADDR:http://192.168.12.248:9080/xxl-job-admin}|addresses: ${XXL_JOB_ADDR:http://192.168.30.10:9080/xxl-job-admin}|' application.yml"
```

```
容器内
sed -i '93s|addresses: ${XXL_JOB_ADDR:http://192.168.12.248: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-test.yaml、jeecg-tenant-prod.yaml、jeecg-tenant.yaml

<img src="https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230721111348347.png"/>

## 5.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 manage:1.0
```

修改jeecg-management-prod.yaml、jeecg-management-dev.yaml、jeecg-management-test.yaml、jeecg-management.yaml

![image-20230721111348347](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230721111348347.png)







# 6.部署前端（应用参考示例）

镜像

```
tenantfront:1.0      managefront:1.0
```

```
managefront:1.0    "/docker-entrypoint.…"    80/tcp, 0.0.0.0:19090->19090/tcp, :::19090->19090/tcp   managefront

tenantfront:1.0    "/docker-entrypoint.…"    80/tcp, 0.0.0.0:18090->18090/tcp, :::18090->18090/tcp   tenantfront

```

## 6.1  managefront端配置文件

```
user root;
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    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;
    gzip on;
    gzip_min_length 1k;
    gzip_comp_level 1;
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;
    gzip_vary on;
    gzip_disable "MSIE [1-6]\.";
    gzip_buffers 32 4k;
    gzip_http_version 1.0;

     upstream management{
         server 192.168.55.12:9999;
     }
    server {
        listen       19090 ssl;
        server_name localhost;
        #server_name  www.tcyunsc.cn;
        ssl_certificate /usr/share/nginx/html/ssl/server.pem;
        ssl_certificate_key /usr/share/nginx/html/ssl/server.key;
        location / {
            root   /usr/share/nginx/html/secureManagement;
            index  index.html index.htm;
	    if (!-e $request_filename) {
	           rewrite ^(.*)$ /index.html?s=$1 last;
	           break;
          	}
        }
        location /security/ {
            proxy_pass https://management/;
            proxy_redirect          off;
            proxy_set_header        Host 192.168.55.12;
            proxy_set_header        X-Real-IP $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }  
}

```

映射关系

![image-20230721112824418](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230721112824418.png)

环境变量

![image-20230721113002800](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230721113002800.png)

```
docker run -d --name managefront --restart=always  -p 19090:19090 -v /data/managefront/conf/nginx.conf:/etc/nginx/nginx.conf:ro managefront:1.0
```



## 6.2  tenantfront端配置文件

```
user root;
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    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;
    gzip on;
    gzip_min_length 1k;
    gzip_comp_level 1;
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;
    gzip_vary on;
    gzip_disable "MSIE [1-6]\.";
    gzip_buffers 32 4k;
    gzip_http_version 1.0;
    upstream tenantfront{
         server 192.168.55.12:9999;
     }
    server {
        listen     18090 ssl;
        #server_name www.tcyunsc.cn;
        server_name localhost;
        ssl_certificate /usr/share/nginx/html/ssl/server.pem;
	ssl_certificate_key /usr/share/nginx/html/ssl/server.key;
        #charset koi8-r;
        #access_log  logs/host.access.log  main;
        location / {
            root   /usr/share/nginx/html/secureManagement;
            index  index.html index.htm;
	    if (!-e $request_filename) {
	           rewrite ^(.*)$ /index.html?s=$1 last;
	           break;
          	}
        }

        location /v1/tenant/ {
            proxy_pass https://tenantfront/;
            proxy_redirect          off;
            proxy_set_header        Host 192.168.55.12;
            proxy_set_header        X-Real-IP $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        }
        location /tenant/ {
            proxy_pass https://tenantfront/;
            proxy_redirect          off;
            proxy_set_header        Host 192.168.55.12;
            proxy_set_header        X-Real-IP $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

}

```

映射关系

![image-20230721113433539](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230721113433539.png)

环境变量

![image-20230721113402327](https://ye5201314-1312898079.cos.ap-guangzhou.myqcloud.com/image-20230721113402327.png)

```
docker run -d --name tenantfront --restart=always --net=myapp  -p 18090:18090 -v /data/tenantfront/conf/nginx.conf:/etc/nginx/nginx.conf:ro tenantfront:1.0
```

```
docker stop tenantfront
docker rm tenantfront
```

# 7.部署完成检查

```
浏览器打开
https://127.0.0.1:19090/

https://127.0.0.1:18090/
```

