学习SpringCloud Alibaba,必然会使用Nacos进行服务注册与配置管理。然而,在实际的生产环境中,使用单服务器搭建nacos服务器是十分危险的,如若发生宕机或网络故障,整个微服务将无法访问。因此,通常使用集群的方式进行部署。
Nacos搭建集群要求至少部署3台服务器实例。Nacos使用delby作为内嵌数据库,在使用集群作为部署方式时,内嵌数据库无法保持数据同步与数据一致,故一般使用外接MySQL数据库的方式保存配置文件。
本次MySQL数据库使用一主一从的方式搭建,实现主从复制与读写分离。使用Nginx做反向代理与负载均衡,同样使用一主一从的方式,根据LVS/Keepalived来实现高可用。整体架构如下图所示。
整体架构 部署环境Nacos 2.1.0-BETA
MySQL 8.0
Nginx
Docker
Cent0S
一、搭建MySQL主从复制为了将配置文件在宿主机做挂载,先运行测试镜像拷贝配置文件
docker run -itd -p 3300:3306 --name mysql-demo -e MYSQL_ROOT_PASSWORD=root -d mysql:8.0.27 mkdir -p ~/mysql-master/conf ~/mysql-master/data docker cp mysql-demo:/etc/mysql/my.cnf ~/mysql-master/conf cp -r ~/mysql-master ~/mysql-slave docker stop mysql-demo docker rm mysql-demo
默认的bridge 网桥无法指定固定的ip,会导致mysql服务的ip不固定,最好配置为自定义网络
创建自定义网络类型
docker network create --subnet=172.18.0.0/16 -d bridge mynet
创建两个自定义网路的MySQL容器,使用mynet定义IP时,前面两个数字要与mynet的对应,后面两个可以随便指定,但不能超过255
docker run -itd -p 3301:3306 --name mysql-master --net mynet --ip 172.18.0.10 -v ~/mysql-master/conf/my.cnf:/etc/mysql/my.cnf -v ~/mysql-master/data:/var/lib/mysql --privileged=true --restart=always -e MYSQL_ROOT_PASSWORD=root -e TZ=Asia/Shanghai -d mysql:8.0.27 docker run -itd -p 3302:3306 --name mysql-slave --net mynet --ip 172.18.0.11 -v ~/mysql-slave/conf/my.cnf:/etc/mysql/my.cnf -v ~/mysql-slave/data:/var/lib/mysql --privileged=true --restart=always -e MYSQL_ROOT_PASSWORD=root -e TZ=Asia/Shanghai -d mysql:8.0.27
退出容器至宿主机中,配置mysql-master挂载的my.cnf文件
vim ~/mysql-master/conf/my.cnf server-id=100 log-bin=master-bin #开启二进制文件 #binlog-do-db=demo #需要同步的二进制数据库名; binlog-ignore-db=information_schema #不同步的二进制数据库名,如果不设置可以将其注释掉; binlog-ignore-db=mysql binlog-ignore-db=performance_schema binlog-ignore-db=sys #log-slave-update #这个是把更新的记录写到二进制文件中;
配置完成后,需要重启mysql-master容器使其修改的配置文件生效,使用如下命令使mysql进行重启
docker restart mysql-master
在Master数据库创建数据同步用户,授予用户 slave REPLICATION SLAVE权限和REPLICATION CLIENT权限,用于在主从库之间同步数据。首先,使用docker exec -it mysql-master bash命令进入容器。
CREATE USER 'slave'@'%' IDENTIFIED BY 'slave'; GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%'; ALTER USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY 'slave';
输入show master status;查看Master状态:
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
|---|---|---|---|---|
| master-bin.000017 | 710 | information_schema,mysql,performance_schema,sys |
记住File和Position,后面需要用到。此时一定不要操作Master库,否则将会引起Master状态的变化,File和Position字段也将会进行变化。
相同方法配置mysql-slave挂载的my.cnf文件
vim ~/mysql-slave/conf/my.cnf ## 设置server_id,注意要唯一 server-id=101 ## 开启二进制日志功能,以备Slave作为其它Slave的Master时使用 log-bin=slave-bin ## relay_log配置中继日志 relay_log=/var/lib/mysql/relay.log read_only=1 ## 设置为只读,该项如果不设置,表示slave可读可写
配置完成后,同样重启mysql-slave容器
docker restart mysql-slave
进入到mysql-slave容器的mysql客户端,执行如下命令:
change master to master_host='172.18.0.10', master_user='slave', master_password='slave', master_port=3306, master_log_file='master-bin.000018', master_log_pos=156, master_connect_retry=30;
命令说明:
| Param | Value |
|---|---|
| master_host | Master的地址,指的是容器的独立ip,可以通过docker inspect 容器名称 |
| master_port | Master的端口号,指的是容器的端口号 |
| master_user | 用于数据同步的用户 |
| master_password | 用于同步的用户的密码 |
| master_log_file | 指定 Slave 从哪个日志文件开始复制数据,即上文中提到的 File 字段的值 |
| master_log_pos | 从哪个 Position 开始读,即上文中提到的 Position 字段的值 |
| master_connect_retry | 如果连接失败,重试的时间间隔,单位是秒,默认是60秒 |
关于docker启动后的IP地址,可能有些同学不太熟悉,可以通过上面所说的:docker inspect 镜像ID查看:
docker inspect mysql-master | grep "IPAddress"
此时,可执行show slave status G;命令查看主从同步状态
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 172.18.0.10
Master_User: slave
Master_Port: 3306
Connect_Retry: 30
Master_Log_File: master-bin.000018
Read_Master_Log_Pos: 156
Relay_Log_File: relay.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: master-bin.000018
Slave_IO_Running: No
Slave_SQL_Running: No
上面的Slave_IO_Running和Slave_SQL_Running是需要关注的地方,因为我们还没有开启主从复制过程,所以两者都是No,此时执行命令start slave;开启同步。
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 172.18.0.10
Master_User: slave
Master_Port: 3306
Connect_Retry: 30
Master_Log_File: master-bin.000018
Read_Master_Log_Pos: 156
Relay_Log_File: relay.000002
Relay_Log_Pos: 325
Relay_Master_Log_File: master-bin.000018
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
如果Slave_SQL_Running:显示为No,请检查宿主机上的 ~/mysql-slave/data/auto.cnf 与 ~/mysql-slave/data/auto.cnf 是否相同,若相同,请根据容器中mysql命令select uuid();进行修改。
测试主从复制
使用如下命令进入mysql-master容器内部
docker exec -it mysql-master bash mysql -uroot -proot
连接mysql数据库,执行nacos-db.sql
CREATE DATABASE nacos_config;
USE nacos_config;
CREATE TABLE `config_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(255) DEFAULT NULL,
`content` longtext NOT NULL COMMENT 'content',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
`app_name` varchar(128) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
`c_desc` varchar(256) DEFAULT NULL,
`c_use` varchar(64) DEFAULT NULL,
`effect` varchar(64) DEFAULT NULL,
`type` varchar(64) DEFAULT NULL,
`c_schema` text,
`encrypted_data_key` text NOT NULL COMMENT '秘钥',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';
CREATE TABLE `config_info_aggr` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(255) NOT NULL COMMENT 'group_id',
`datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
`content` longtext NOT NULL COMMENT '内容',
`gmt_modified` datetime NOT NULL COMMENT '修改时间',
`app_name` varchar(128) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租户字段';
CREATE TABLE `config_info_beta` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`content` longtext NOT NULL COMMENT 'content',
`beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
`encrypted_data_key` text NOT NULL COMMENT '秘钥',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';
CREATE TABLE `config_info_tag` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
`tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`content` longtext NOT NULL COMMENT 'content',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';
CREATE TABLE `config_tags_relation` (
`id` bigint(20) NOT NULL COMMENT 'id',
`tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
`tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
`nid` bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`nid`),
UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';
CREATE TABLE `group_capacity` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',
`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值',
`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
`gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';
CREATE TABLE `his_config_info` (
`id` bigint(64) unsigned NOT NULL,
`nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`data_id` varchar(255) NOT NULL,
`group_id` varchar(128) NOT NULL,
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`content` longtext NOT NULL,
`md5` varchar(32) DEFAULT NULL,
`gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
`src_user` text,
`src_ip` varchar(20) DEFAULT NULL,
`op_type` char(10) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
`encrypted_data_key` text NOT NULL COMMENT '秘钥',
PRIMARY KEY (`nid`),
KEY `idx_gmt_create` (`gmt_create`),
KEY `idx_gmt_modified` (`gmt_modified`),
KEY `idx_did` (`data_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造';
CREATE TABLE `tenant_capacity` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',
`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
`gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表';
CREATE TABLE `tenant_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`kp` varchar(128) NOT NULL COMMENT 'kp',
`tenant_id` varchar(128) default '' COMMENT 'tenant_id',
`tenant_name` varchar(128) default '' COMMENT 'tenant_name',
`tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
`create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
`gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
`gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';
CREATE TABLE users (
username varchar(50) NOT NULL PRIMARY KEY,
password varchar(500) NOT NULL,
enabled boolean NOT NULL
);
CREATE TABLE roles (
username varchar(50) NOT NULL,
role varchar(50) NOT NULL,
constraint uk_username_role UNIQUE (username,role)
);
CREATE TABLE permissions (
role varchar(50) NOT NULL,
resource varchar(512) NOT NULL,
action varchar(8) NOT NULL,
constraint uk_role_permission UNIQUE (role,resource,action)
);
INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
此时进入mysql-slave容器中查看同步是否成功
docker exec -it mysql-slave bash mysql -uroot -proot show databases;
若与master一致,则集群搭建成功。
(
role varchar(50) NOT NULL,
resource varchar(512) NOT NULL,
action varchar(8) NOT NULL,
constraint uk_role_permission UNIQUE (role,resource,action)
);
INSERT INTO users (username, password, enabled) VALUES (‘nacos’, ‘$2a 10 10 10EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu’, TRUE);
INSERT INTO roles (username, role) VALUES (‘nacos’, ‘ROLE_ADMIN’);
此时进入mysql-slave容器中查看同步是否成功 ```shell docker exec -it mysql-slave bash mysql -uroot -proot show databases;
若与master一致,则MySQL集群搭建成功。
二、搭建NACOS集群


