# JavaTechnologyLearn **Repository Path**: lyhonline/JavaTechnologyLearn ## Basic Information - **Project Name**: JavaTechnologyLearn - **Description**: java技术、java中间件、docker以及微服务相关项目,全部都是经过测试可复用的。 - **Primary Language**: Unknown - **License**: GPL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2022-12-08 - **Last Updated**: 2025-07-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 相关环境简介 # 1. nacos作为注册中心 - naocs安装目录: /usr/nacos - 服务器镜像名称:centos7-mysql8.0 ip - 地址:192.168.139.20 - 启动目录: /usr/nacos/nacos/bin - 启动命令: sh startup.sh -m standalone - 服务提供者 nacos-provider8081 - 服务消费者 nacos-consumer8082 # 2. nacos作为配置中心 - 项目名字: nacos-config9001 - 具体配置按照:application.properties\bootstrap.properties进行配置 - 需要在:http://192.168.139.20:8848/nacos - 配置中心中新建配置,dateId 为项目名字+profile环境类型 - 获取配置的地方添加@RefreshScope注解可以实现自动刷新同步naocs配置 # 3. feign调用集成 - 项目名字:openfeign-consumer8083 - maven: 主要引用feigin、负载均衡、服务发现的包 然后就可以直接使用了 # 4. sentinel限流和链路追踪集成 - sentinel-dashboard管理控制台安装: - 服务器镜像名称:centos7-mysql8.0 - ip 地址:192.168.139.20 - 安装路径: /usr/sentinel-dashboard - 启动命令: nohup java -Dserver.port=8085 -Dcsp.sentinel.dashboard.server=localhost:8085-Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.6.jar & - 启动端口: 8085 - web端dashboard界面路径: http://192.168.139.20:8085/#/dashboard/home - 项目例子: sentinel8084 ## 4.1 sentinel限流和feign集成 - 项目例子: sentinel-openfeign8086 - 注意需要引用的maven包和相关服务发现的配置文件 ## 4.2 各种限流规则: 1. **默认快速失败**:簇点链路 > 选择对应的请求 > 点击流控按钮 >QPS 1 >点击新增并添加 快速点击(超过一秒一次QPS=1)请求对应的链接返回: Blocked by Sentinel (flow limiting) 2. **关联模式**, 对请求A进行限流,然后关联选择B:规则配置完成后,会再高并发请求B的时候,A请求会被限流。 3. **链路模式** 对于同时被请求A和请求B调用的请求C,在对C进行限流时候可以根据入口A或B进行单独限流。 4. **预热模式warn up** 可以对阈值设置一个预热时长,预热时间内逐渐到达阈值,使用jmeter的10个线程进行压测,开始报错比较多,然后越来越少,最后没有报错。 5. **排队模式** 对某资源设置排队模式,可以设置可以处理的线程数,然后其他的进入等待时间里边。 6. **慢调用比例模式** 在熔断规则里边,对对应的资源设置慢调用比例,设置RT超过200毫秒的即为慢调用,比例阈值:范围是0到1,可以理解为百分数,即100%以内;然后设置熔断时长(在达到慢调用阈值后会拒绝接收服务的时长),最后参数是统计时长,即统计慢调用比例的时间长度。 7. **异常比例模式**,于上边的类似 8. **异常数模式**,于上边的类似 9. 可以使用 @SentinelResource(value = "testHotKey",blockHandler = "dealHandler_testHotKey") 自定义某个资源报错后的处理器 ```java public String dealHandler_testHotKey(String p1, String p2, BlockException exception) { return "-----dealHandler_testHotKey"; } ``` # 5. 分布式事务 seata [Seata 官网](http://seata.io/zh-cn/docs/overview/what-is-seata.html) #### [Seata部署指南 官网](https://seata.io/zh-cn/docs/ops/deploy-guide-beginner.html) [(seata整合nacos 以db方式部署](https://blog.csdn.net/weixin_43582081/article/details/126071674) #### seata安装 ```xshell 安装路径:/usr/seata/seata/bin 启动命令: sh [seata-server.sh](http://seata-server.sh/) -h 127.0.0.1 -p 8091 -m db ``` ## seata分布式事务例子 ##### 业务概述: 这里我们会创建三个服务,一个订单服务,一个库存服务,一个账户服务。当用户下单时,会在订单服务中创建一个订单,然后通过远程调用库存服务来扣减下单商品的库存,再通过远程调用账户服务来扣减用户账户里面的余额,最后在订单服务中修改订单状态为已完成。 该操作跨越三个数据库,有两次远程调用,很明显会有分布式事务问题。 下订单--->扣库存--->减账户(余额) ##### 相关数据库: seata_order 存储订单的数据库 ```sql CREATE DATABASE seata_order; CREATE TABLE t_order ( `id` BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, `user_id` BIGINT(11) DEFAULT NULL COMMENT '用户id', `product_id` BIGINT(11) DEFAULT NULL COMMENT '产品id', `count` INT(11) DEFAULT NULL COMMENT '数量', `money` DECIMAL(11,0) DEFAULT NULL COMMENT '金额', `status` INT(1) DEFAULT NULL COMMENT '订单状态:0:创建中;1:已完结' ) ENGINE=INNODB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8; SELECT * FROM t_order; ``` seata_storage 存储库存的数据库 ```sql CREATE DATABASE seata_storage; CREATE TABLE t_storage ( `id` BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, `product_id` BIGINT(11) DEFAULT NULL COMMENT '产品id', `total` INT(11) DEFAULT NULL COMMENT '总库存', `used` INT(11) DEFAULT NULL COMMENT '已用库存', `residue` INT(11) DEFAULT NULL COMMENT '剩余库存' ) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; INSERT INTO seata_storage.t_storage(`id`, `product_id`, `total`, `used`, `residue`) VALUES ('1', '1', '100', '0', '100'); SELECT * FROM t_storage; ``` seata_account 存储账户信息的数据库 ```sql CREATE TABLE t_account ( `id` BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'id', `user_id` BIGINT(11) DEFAULT NULL COMMENT '用户id', `total` DECIMAL(10,0) DEFAULT NULL COMMENT '总额度', `used` DECIMAL(10,0) DEFAULT NULL COMMENT '已用余额', `residue` DECIMAL(10,0) DEFAULT '0' COMMENT '剩余可用额度' ) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; INSERT INTO seata_account.t_account(`id`, `user_id`, `total`, `used`, `residue`) VALUES ('1', '1', '1000', '0', '1000'); SELECT * FROM t_account; ``` 注意相关业务库中均需要undo_log: ```sql CREATE TABLE `undo_log` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT, `branch_id` BIGINT(20) NOT NULL, `xid` VARCHAR(100) NOT NULL, `context` VARCHAR(128) NOT NULL, `rollback_info` LONGBLOB NOT NULL, `log_status` INT(11) NOT NULL, `log_created` DATETIME NOT NULL, `log_modified` DATETIME NOT NULL, `ext` VARCHAR(100) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`) ) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8 ``` #### 相关服务: 在订单中开始调用,并在调用的方法上添加@GlobalTransactional(rollbackFor = Exception.class) 即可,后续方法报错都会全局回滚。 seata-order8088 seata-storage8089 seata-account8100 # 6. shardingsphere ## 6.1 服务部署 一主多从配置 - 主服务器:容器名`atguigu-mysql-master`,端口`3306` - 从服务器:容器名`atguigu-mysql-slave1`,端口`3307` - 从服务器:容器名`atguigu-mysql-slave2`,端口`3308` 1. 关闭防火墙 ```shell #关闭docker systemctl stop docker #关闭防火墙 systemctl stop firewalld #启动docker systemctl start docker ``` 2. 安装master数据库 ```shell docker run -d \ -p 3306:3306 \ -v /atguigu/mysql/master/conf:/etc/mysql/conf.d \ -v /atguigu/mysql/master/data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=123456 \ --name atguigu-mysql-master \ mysql:8.0.29 ``` 3. 创建mysql主服务器文件 默认情况下MySQL的binlog日志是自动开启的,可以通过如下配置定义一些可选配置 vim /atguigu/mysql/master/conf/my.cnf 配置如下内容 ```bash [mysqld] # 服务器唯一id,默认值1 server-id=1 # 设置日志格式,默认值ROW binlog_format=STATEMENT # 二进制日志名,默认binlog # log-bin=binlog # 设置需要复制的数据库,默认复制全部数据库 #binlog-do-db=mytestdb # 设置不需要复制的数据库 #binlog-ignore-db=mysql #binlog-ignore-db=infomation_schema ``` 重启MySQL容器 ```bash docker restart atguigu-mysql-master ``` 4. 使用命令行登录MySQL主服务器: ```bash #进入容器:env LANG=C.UTF-8 避免容器中显示中文乱码 docker exec -it atguigu-mysql-master env LANG=C.UTF-8 /bin/bash #进入容器内的mysql命令行 mysql -uroot -p #修改默认密码校验方式 ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; ``` 5. 主机中创建slave用户: ```bash -- 创建slave用户 CREATE USER 'atguigu_slave'@'%'; -- 设置密码 ALTER USER 'atguigu_slave'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; -- 授予复制权限 GRANT REPLICATION SLAVE ON *.* TO 'atguigu_slave'@'%'; -- 刷新权限 FLUSH PRIVILEGES; ``` 6. 主机中查询master状态: 7. 准备从服务器 可以配置多台从机slave1、slave2...,这里以配置slave1为例 8. 在docker中创建并启动MySQL从服务器:端口3307` ```bash docker run -d \ -p 3307:3306 \ -v /atguigu/mysql/slave1/conf:/etc/mysql/conf.d \ -v /atguigu/mysql/slave1/data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=123456 \ --name atguigu-mysql-slave1 \ mysql:8.0.29 ``` 9. 创建MySQL从服务器配置文件: vim /atguigu/mysql/slave1/conf/my.cnf **配置内容** ```bash [mysqld] # 服务器唯一id,每台服务器的id必须不同,如果配置其他从机,注意修改id server-id=2 # 中继日志名,默认xxxxxxxxxxxx-relay-bin #relay-log=relay-bin ``` 10. 使用命令行登录MySQL从服务器: ```bash #进入容器: docker exec -it atguigu-mysql-slave1 env LANG=C.UTF-8 /bin/bash #进入容器内的mysql命令行 mysql -uroot -p #修改默认密码校验方式 ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; ``` 11. 在从机上配置主从关系: 在从服务的mysql上执行下面的sql ```bash CHANGE MASTER TO MASTER_HOST='192.168.139.30', MASTER_USER='atguigu_slave',MASTER_PASSWORD='123456', MASTER_PORT=3306, MASTER_LOG_FILE='binlog.000003',MASTER_LOG_POS=1357; ``` 12. 启动主从同步 启动从机的复制功能,在主服务器上执行SQL ```bashs START SLAVE; -- 查看状态(不需要分号) SHOW SLAVE STATUS\G ``` 13. 下面两个参数都是Yes,则说明主从配置成功 ```bash Slave_IO_Running:Yes Slave_SQL_Running:Yes ``` 14. 实现主从同步 在主机中执行以下SQL,在从机中查看数据库、表和数据是否已经被同步 ```sql CREATE DATABASE db_user; USE db_user; CREATE TABLE t_user ( id BIGINT AUTO_INCREMENT, uname VARCHAR(30), PRIMARY KEY (id) ); INSERT INTO t_user(uname) VALUES('zhang3'); INSERT INTO t_user(uname) VALUES(@@hostname); ``` 15. 停止和重置 ```bash -- 在从机上执行。功能说明:停止I/O 线程和SQL线程的操作。 stop slave; -- 在从机上执行。功能说明:用于删除SLAVE数据库的relaylog日志文件,并重新启用新的relaylog文件。 reset slave; -- 在主机上执行。功能说明:删除所有的binglog日志文件,并将日志索引文件清空,重新开始所有新的日志文件。 -- 用于第一次进行搭建主从库时,进行主库binlog初始化工作; reset master; ``` ## 6.2 shardingSphere-jdbc #### 项目 shardingsphere-jdbc8101 #### 读写分离: **application.properties** 属性配置 以及测试测试类**ReadwriteTest**的代码 #### 事务测试 为了保证主从库间的事务一致性,避免跨服务的分布式事务,ShardingSphere-JDBC的`主从模型中,事务中的数据读写均用主库`。 * 不添加@Transactional:insert对主库操作,select对从库操作 * 添加@Transactional:则insert和select均对主库操作 **注意:**在JUnit环境下的@Transactional注解,默认情况下就会对事务进行回滚(即使在没加注解@Rollback,也会对事务回滚) 注意: **为了使测试数据不对数据库造成污染,在使用Spring-test进行的单元测试的时候,默认会对事务进行回滚,即@Rollback 默认是true**,如果想要测试数据不回滚,可设置@[Rollback](https://so.csdn.net/so/search?q=Rollback&spm=1001.2101.3001.7020)(value = false) 。 以及测试测试类**testTrans**的代码 #### 负载均衡测试 ```java testSelectAll 查两次user表,查看日志可以看出第第一次slave1 第二次是slave2 ``` ## 6.3 ShardingSphere-JDBC垂直分片 #### 服务器准备 服务器规划:使用`docker`方式创建如下容器 - 服务器:容器名`server-user`,端口`3301` - 服务器:容器名`server-order`,端口`3302` 1. 创建server-user服务器 - 创建容器: ```xshell docker run -d \ -p 3301:3306 \ -v /atguigu/server/user/conf:/etc/mysql/conf.d \ -v /atguigu/server/user/data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=123456 \ --name server-user \ mysql:8.0.29 ``` - 登录MySQL服务器 ```xshell #进入容器: docker exec -it server-user env LANG=C.UTF-8 /bin/bash #进入容器内的mysql命令行 mysql -uroot -p #修改默认密码插件 ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; ``` - 创建表 ```sql CREATE DATABASE db_user; USE db_user; CREATE TABLE t_user ( id BIGINT AUTO_INCREMENT, uname VARCHAR(30), PRIMARY KEY (id) ); ``` 2. 创建server-order容器 - 创建容器 ```xshell docker run -d \ -p 3302:3306 \ -v /atguigu/server/order/conf:/etc/mysql/conf.d \ -v /atguigu/server/order/data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=123456 \ --name server-order \ mysql:8.0.29 ``` - 登录MySQL服务器 ```xshell #进入容器: docker exec -it server-order env LANG=C.UTF-8 /bin/bash #进入容器内的mysql命令行 mysql -uroot -p #修改默认密码插件 ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; ``` - 创建数据库 ```xshell CREATE DATABASE db_order; USE db_order; CREATE TABLE t_order ( id BIGINT AUTO_INCREMENT, order_no VARCHAR(30), user_id BIGINT, amount DECIMAL(10,2), PRIMARY KEY(id) ); ``` #### 项目测试 shardingsphere-jdbc8102-verticalSlice ShardingTest 测试类 ​ application.properties 属性配置 ## 6.4 ShardingSphere-JDBC水平分片 #### 准备服务器 - 服务器:容器名`server-order0`,端口`3310` - 服务器:容器名`server-order1`,端口`3311` 1. 创建server-order0容器-创建容器 ```bash docker run -d \ -p 3310:3306 \ -v /atguigu/server/order0/conf:/etc/mysql/conf.d \ -v /atguigu/server/order0/data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=123456 \ --name server-order0 \ mysql:8.0.29 ``` 2. 登录MySQL服务器: ```bash #进入容器: docker exec -it server-order0 env LANG=C.UTF-8 /bin/bash #进入容器内的mysql命令行 mysql -uroot -p #修改默认密码插件 ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; ``` 3. 创建数据库 `注意:`水平分片的id需要在业务层实现,`不能依赖数据库的主键自增` ```sql CREATE DATABASE db_order; USE db_order; CREATE TABLE t_order0 ( id BIGINT, order_no VARCHAR(30), user_id BIGINT, amount DECIMAL(10,2), PRIMARY KEY(id) ); CREATE TABLE t_order1 ( id BIGINT, order_no VARCHAR(30), user_id BIGINT, amount DECIMAL(10,2), PRIMARY KEY(id) ); ``` 4. 创建server-order1容器-创建容器 ```bash docker run -d \ -p 3311:3306 \ -v /atguigu/server/order1/conf:/etc/mysql/conf.d \ -v /atguigu/server/order1/data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=123456 \ --name server-order1 \ mysql:8.0.29 ``` 5. 登录MySQL服务器: ```bash #进入容器: docker exec -it server-order1 env LANG=C.UTF-8 /bin/bash #进入容器内的mysql命令行 mysql -uroot -p #修改默认密码插件 ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; ``` 6. 创建数据库:**和server-order0相同 ```sql CREATE DATABASE db_order; USE db_order; CREATE TABLE t_order0 ( id BIGINT, order_no VARCHAR(30), user_id BIGINT, amount DECIMAL(10,2), PRIMARY KEY(id) ); CREATE TABLE t_order1 ( id BIGINT, order_no VARCHAR(30), user_id BIGINT, amount DECIMAL(10,2), PRIMARY KEY(id) ); ``` #### 项目配置 shardingsphere-jdbc8103-horizontalSlice 项目 详情参考项目的 属性配置文件和实体类以及测试用例 #### 项目简单解析 实现对对t_order进行分库分表,分别在server-order0、server-order1两个数据库上建立t_order0和t_order1一共四张表,配置对应的数据源,然后再根据user_id模2分别对数据进行拆分。 #### 关联表 在`server-order0、server-order1`服务器中分别创建两张订单详情表`t_order_item0、t_order_item1` 我们希望`同一个用户的订单表和订单详情表中的数据都在同一个数据源中,避免跨库关联`,因此这两张表我们使用相同的分片策略。 那么在`t_order_item`中我们也需要创建`order_no`和`user_id`这两个分片键 ```sql CREATE TABLE t_order_item0( id BIGINT, order_no VARCHAR(30), user_id BIGINT, price DECIMAL(10,2), `count` INT, PRIMARY KEY(id) ); CREATE TABLE t_order_item1( id BIGINT, order_no VARCHAR(30), user_id BIGINT, price DECIMAL(10,2), `count` INT, PRIMARY KEY(id) ); ``` 配置详情见: application-关联查询.properties #### 绑定表 **需求:**查询每个订单的订单号和总订单金额 配置添加 ```sql #------------------------绑定表 spring.shardingsphere.rules.sharding.binding-tables[0]=t_order,t_order_item ``` 配置完绑定表后再次进行关联查询的测试: - **如果不配置绑定表:测试的结果为8个SQL。**多表关联查询会出现笛卡尔积关联。 - **如果配置绑定表:测试的结果为4个SQL。** 多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提升。 `绑定表:`指分片规则一致的一组分片表。 使用绑定表进行多表关联查询时,必须使用分片键进行关联,否则会出现笛卡尔积关联或跨库关联,从而影响查询效率。 #### 广播表 指所有的分片数据源中都存在的表,表结构及其数据在每个数据库中均完全一致。 适用于数据量不大且需要与海量数据的表进行关联查询的场景,例如:字典表。 广播具有以下特性: (1)插入、更新操作会实时在所有节点上执行,保持各个分片的数据一致性 (2)查询操作,只从一个节点获取 (3)可以跟任何一个表进行 JOIN 操作 在server-order0、server-order1和server-user服务器中分别创建t_dict表 ```sql CREATE TABLE t_dict( id BIGINT, dict_type VARCHAR(200), PRIMARY KEY(id) ); ``` 添加配置 ```properties #数据节点可不配置,默认情况下,向所有数据源广播 spring.shardingsphere.rules.sharding.tables.t_dict.actual-data-nodes=server-user.t_dict,server-order$->{0..1}.t_dict # 广播表 spring.shardingsphere.rules.sharding.broadcast-tables[0]=t_dict ``` 具体查看项目测试用例 # 7. Shardingsphere-Proxy ## 7.0 安装位置和配置信息 **虚拟机: 192.168.138.30 server-proxy-a** **链接mysql : 192.168.138.30 3321 root root** ## 7.1 Shardingsphere-Proxy 安装 目前 ShardingSphere-Proxy 提供了 3 种获取方式: - [二进制发布包](https://shardingsphere.apache.org/document/5.1.1/cn/user-manual/shardingsphere-proxy/startup/bin/) - [Docker](https://shardingsphere.apache.org/document/5.1.1/cn/user-manual/shardingsphere-proxy/startup/docker/) - [Helm] ##### 二进制包安装 二进制包既可以Linux系统运行,又可以在windows系统运行 **step1:解压二进制包** `apache-shardingsphere-5.1.1-shardingsphere-proxy-bin.tar.gz` windows:使用解压软件解压文件 Linux:将文件上传至/opt目录,并解压 ```shell tar -zxvf apache-shardingsphere-5.1.1-shardingsphere-proxy-bin.tar.gz ``` **step2:MySQL驱动** `mysql-connector-java-8.0.22.jar` 将MySQl驱动放至解压目录中的`ext-lib`目录 **spte3:修改配置conf/server.yaml** ```yaml rules: - !AUTHORITY users: - root@%:root provider: type: ALL_PRIVILEGES_PERMITTED props: sql-show: true ``` **spte4:启动ShardingSphere-Proxy** Linux 操作系统请运行 `bin/start.sh` Windows 操作系统请运行 `bin/start.bat` 指定端口号和配置文件目录:`bin/start.bat ${proxy_port} ${proxy_conf_directory}` **step5:远程连接ShardingSphere-Proxy** 远程访问 ```shell mysql -h192.168.100.1 -P3307 -uroot -p ``` **step6:访问测试** ```sql show databases; ``` ##### 使用Docker安装 **step1:启动Docker容器** ```shell docker run -d \ -v /atguigu/server/proxy-a/conf:/opt/shardingsphere-proxy/conf \ -v /atguigu/server/proxy-a/ext-lib:/opt/shardingsphere-proxy/ext-lib \ -e ES_JAVA_OPTS="-Xmx256m -Xms256m -Xmn128m" \ -p 3321:3307 \ --name server-proxy-a \ apache/shardingsphere-proxy:5.1.1 ``` **step2:上传MySQL驱动** 将MySQl驱动上传至`/atguigu/server/proxy-a/ext-lib`目录 **spte3:修改配置server.yaml** ```yaml rules: - !AUTHORITY users: - root@%:root provider: type: ALL_PRIVILEGES_PERMITTED props: sql-show: true ``` 将配置文件上传至`/atguigu/server/proxy-a/conf`目录 **spte4:重启容器** ```shell docker restart server-proxy-a ``` **step5:远程连接ShardingSphere-Proxy** ShardingSphere-Proxy容器中默认情况下没有mysql命令行客户端的安装,因此需要远程访问 ```shell mysql -h192.168.100.201 -P3321 -uroot -p ``` **step6:访问测试** ```sql show databases; ``` ![image-20220819152009158](D:\BaiduNetdiskDownload\尚硅谷ShardingSphere5教程\笔记\assets\image-20220819152009158.png) **常见问题:docker容器无法远程连接** 容器可以成功的创建并启动,但是无法远程连接。排除防火墙和网络等问题后,看看是不是因为容器内存不足导致。 `原因:`容器可分配内存不足 `查看办法:`进入容器后查看ShardingSphere-Proxy的日志,如有有`cannot allocate memory`,则说明容器内存不足 ```shell docker exec -it server-proxy-a env LANG=C.UTF-8 /bin/bash cd /opt/shardingsphere-proxy/logs tail stdout.log ``` ![image-20220819151154763](D:\BaiduNetdiskDownload\尚硅谷ShardingSphere5教程\笔记\assets\image-20220819151154763.png) `解决方案:`创建容器的时候使用JVM参数 ```shell -e ES_JAVA_OPTS="-Xmx256m -Xms256m -Xmn128m" ``` ## 7.2 ShardingSphere-Proxy读写分离 shardingSphere-proxy8104 项目 ##### 1、修改配置文件 **修改配置config-readwrite-splitting.yaml** ```yaml schemaName: readwrite_splitting_db dataSources: write_ds: url: jdbc:mysql://192.168.100.201:3306/db_user?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1 read_ds_0: url: jdbc:mysql://192.168.100.201:3307/db_user?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1 read_ds_1: url: jdbc:mysql://192.168.100.201:3308/db_user?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1 rules: - !READWRITE_SPLITTING dataSources: readwrite_ds: type: Static props: write-data-source-name: write_ds read-data-source-names: read_ds_0,read_ds_1 ``` 将配置文件上传至`/atguigu/server/proxy-a/conf`目录 ##### **重启容器** ```shell docker restart server-proxy-a ``` ##### 2、实时查看日志 可以通过这种方式查看服务器中输出的SQL语句 ```shell docker exec -it server-proxy-a env LANG=C.UTF-8 /bin/bash tail -f /opt/shardingsphere-proxy/logs/stdout.log ``` ##### 3、远程访问测试 ```sql mysql> show databases; mysql> use readwrite_splitting_db; mysql> show tables; mysql> select * from t_user; mysql> select * from t_user; mysql> insert into t_user(uname) values('wang5'); ``` ## 7.3 ShardingSphere-Proxy垂直分片 配置和测试 ##### 1、修改配置文件 如果使用的docker就添加这个配置文件。 ###### **修改配置config-sharding.yaml** ```yaml schemaName: sharding_db dataSources: ds_0: url: jdbc:mysql://192.168.100.201:3301/db_user?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1 ds_1: url: jdbc:mysql://192.168.100.201:3302/db_order?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1 rules: - !SHARDING tables: t_user: actualDataNodes: ds_0.t_user t_order: actualDataNodes: ds_1.t_order ``` ##### 2、实时查看日志 可以通过这种方式查看服务器中输出的SQL语句 ```shell docker exec -it server-proxy-a env LANG=C.UTF-8 /bin/bash tail -f /opt/shardingsphere-proxy/logs/stdout.log ``` ##### 3、远程访问测试 ```sql mysql> show databases; mysql> use sharding_db; mysql> show tables; mysql> select * from t_order; mysql> select * from t_user; ``` ## 7.4 ShardingSphere-Proxy水平分片 ##### 1、修改配置文件 **修改配置config-sharding.yaml** ```yaml schemaName: sharding_db dataSources: ds_user: url: jdbc:mysql://192.168.100.201:3301/db_user?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1 ds_order0: url: jdbc:mysql://192.168.100.201:3310/db_order?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1 ds_order1: url: jdbc:mysql://192.168.100.201:3311/db_order?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1 rules: - !SHARDING tables: t_user: actualDataNodes: ds_user.t_user t_order: actualDataNodes: ds_order${0..1}.t_order${0..1} databaseStrategy: standard: shardingColumn: user_id shardingAlgorithmName: alg_mod tableStrategy: standard: shardingColumn: order_no shardingAlgorithmName: alg_hash_mod keyGenerateStrategy: column: id keyGeneratorName: snowflake t_order_item: actualDataNodes: ds_order${0..1}.t_order_item${0..1} databaseStrategy: standard: shardingColumn: user_id shardingAlgorithmName: alg_mod tableStrategy: standard: shardingColumn: order_no shardingAlgorithmName: alg_hash_mod keyGenerateStrategy: column: id keyGeneratorName: snowflake bindingTables: - t_order,t_order_item broadcastTables: - t_dict shardingAlgorithms: alg_inline_userid: type: INLINE props: algorithm-expression: server-order$->{user_id % 2} alg_mod: type: MOD props: sharding-count: 2 alg_hash_mod: type: HASH_MOD props: sharding-count: 2 keyGenerators: snowflake: type: SNOWFLAKE ``` ##### 2、实时查看日志 可以通过这种方式查看服务器中输出的SQL语句 ```shell docker exec -it server-proxy-a env LANG=C.UTF-8 /bin/bash tail -f /opt/shardingsphere-proxy/logs/stdout.log ``` ##### 3、远程访问测试 ```sql mysql> show databases; mysql> use sharding_db; mysql> show tables; mysql> select * from t_order; --测试水平分片 mysql> select * from t_dict; --测试广播表 ``` - # 9. java17源码项目 构建方式相关参考: [(47条消息) JDK11 源码阅读 报错:Java:找到太多的模块声明的报错_nemonobd的博客-CSDN博客](https://blog.csdn.net/kzc5335475/article/details/117392312) - 安装JDK17,到安装目录找到src.zip源码压缩包 - 解压到一个空项目中, 并修改项目结构中依赖的SDK为jdk17,并删除默认的源代码路劲,修改为解压的源代码 - 修改idea编译设置的最大堆内存,默认是700,修改为2048 - 在其他项目中也可以修改项目结构中的jdk17对应的源代码路径,这样别的项目也可以随时随地对jdk17源代码添加注释和调试了。 ![](img/img.png) # 10. redis ## redis docker方式安装步骤 **安装信息:** ```bash 宿主机器: 192.168.139.30 宿主机器redis的data和conf目录: /app/redis docke启动命令: docker run -p 6379:6379 --name redis -v /app/redis/redis.conf:/etc/redis/redis.conf -v /app/redis/data:/data -d redis redis-server /etc/redis/redis.conf ``` **安装步骤:** 1. 拉取最新版本redis docker pull redis 2. 在宿主机器中新建redis的data和conf目录 1. /app/redis 3. 去下载docker对应的redis安装包,为了使用解压出来的redis.conf文件 4. 修改配置文件redis.conf 1. protected-mode no 保护模式,限制为本地访问,修改后解除保护模式 2. requirepass 123456 设置密码(建议设置,不设置有风险) 3. appendonly yes 持久化设置 5. 使用命令启动 原文链接:https://blog.csdn.net/m0_55070913/article/details/126628271 ```shell 两种启动方式都可以,区别在于第一种是做端口映射,第二种是修改网络模式为host模式,直接映射ip和端口,部署集群和哨兵时候推荐第二种避免容器间网络不通的问题。 docker run -p 6379:6379 -v /app/redis/conf:/usr/local/etc/redis -v /app/redis/data:/data -d --name redis redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes docker run -v /app/redis/conf:/usr/local/etc/redis -v /app/redis/data:/data -d --net=host --name redis redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes ``` ``` -p 6379:6379 端口映射:前表示主机部分,:后表示容器部分。 ​ –name redis 指定该容器名称,查看和进行操作都比较方便。 ​ -v 挂载文件或目录 :前表示主机部分,:后表示容器部分。 ​ -d redis 表示后台启动redis ​ redis-server /etc/redis/redis.conf ​ 以配置文件启动redis,加载容器内的conf文件,最终找到的是挂载的目录/usr/local/docker/redis.conf ​ –appendonly yes 开启redis 持久化 配置中和启动时候都需要开启 ​ –requirepass 123456 设置密码为123456 ``` 6. 启动后链接客户 ```console docker run -it --rm redis redis-cli ``` ## redis 主从配置docker 1. 默认上边那个配置就是主节点 2. 从节点修改的配置 修改端口 port 6380 replicaof 192.168.0.60 6379 # 从本机6379的redis实例复制数据,Redis 5.0之前使用slaveof replica‐read‐only yes # 配置从节点只读 masterauth 123456 主节点的密码 3. 启动两个从节点 **端口映射方式启动** docker run -p 6380:6380 -v /app/redis-slave1/conf:/usr/local/etc/redis -v /app/redis-slave1/data:/data -d --name redis-slave1 redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes docker run -p 6381:6381 -v /app/redis-slave2/conf:/usr/local/etc/redis -v /app/redis-slave2/data:/data -d --name redis-slave2 redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes **设置为host网络模式启动** **docker run -v /app/redis-slave1/conf:/usr/local/etc/redis -v /app/redis-slave1/data:/data -d --net=host --name redis-slave1 redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes** **docker run -v /app/redis-slave2/conf:/usr/local/etc/redis -v /app/redis-slave2/data:/data -d --net=host --name redis-slave2 redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes** ## redis 哨兵设置 哨兵启动命令 哨兵26379 docker run --name redis-sentinel-01 \ --privileged=true \ -p 26379:26379 \ -v /app/redis-sentinel-26379/sentinel.conf:/etc/redis/sentinel.conf \ -d --net=host redis redis-sentinel /etc/redis/sentinel.conf 哨兵-26380 docker run --name redis-sentinel-02 \ --privileged=true \ -p 26380:26380 \ -v /app/redis-sentinel-26380/sentinel.conf:/etc/redis/sentinel.conf \ -d --net=host redis redis-sentinel /etc/redis/sentinel.conf 哨兵-26381 docker run --name redis-sentinel-03 \ --privileged=true \ -p 26381:26381 \ -v /app/redis-sentinel-26381/sentinel.conf:/etc/redis/sentinel.conf \ -d --net=host redis redis-sentinel /etc/redis/sentinel.conf ## redis高可用集群搭建 redis集群至少需要三个master节点,我这里搭建三个master节点,并且给每个master节点搭建一个slave节点,总共6个节点,这里用三台机器部署6个redis实例。 8011 8012 8021 8022 8031 8032 修改配置 1)daemonize yes 7 (2)port 8001(分别对每个机器的端口号进行设置) 8 (3)pidfile /var/run/redis_8001.pid # 把pid进程号写入pidfile配置的文件 9 (4)dir /usr/local/redis‐cluster/8001/(指定数据文件存放位置,必须要指定不同的目录位置,不然会 丢失数据) 10 (5)cluster‐enabled yes(启动集群模式) 11 (6)cluster‐config‐file nodes‐8001.conf(集群节点信息文件,这里800x最好和port对应上) 12 (7)cluster‐node‐timeout 10000 13 (8)# bind 127.0.0.1(bind绑定的是自己机器网卡的ip,如果有多块网卡可以配多个ip,代表允许客户端通 过机器的哪些网卡ip去访问,内网一般可以不配置bind,注释掉即可) 14 (9)protected‐mode no (关闭保护模式) 15 (10)appendonly yes 16 如果要设置密码需要增加如下配置: 17 (11)requirepass zhuge (设置redis访问密码) 18 (12)masterauth zhuge (设置集群节点间访问密码,跟上面一致) 每个docker都执行一下启动命令 使用网络模式host模式 docker run -v /app/redis-cluster/8011:/usr/local/etc/redis -v /app/redis-cluster/8011/data:/data -d --net=host --name redis-cluster8011 redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes docker run -v /app/redis-cluster/8012:/usr/local/etc/redis -v /app/redis-cluster/8012/data:/data -d --net=host --name redis-cluster8012 redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes docker run -v /app/redis-cluster/8021:/usr/local/etc/redis -v /app/redis-cluster/8021/data:/data -d --net=host --name redis-cluster8021 redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes docker run -v /app/redis-cluster/8022:/usr/local/etc/redis -v /app/redis-cluster/8022/data:/data -d --net=host --name redis-cluster8022 redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes docker run -v /app/redis-/8031:/usr/local/etc/redis -v /app/redis-cluster/8031/data:/data -d --net=host --name redis-cluster8031 redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes docker run -v /app/redis-cluster/8032:/usr/local/etc/redis -v /app/redis-cluster/8032/data:/data -d --net=host --name redis-cluster8032 redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes 在redis-cli上执行创建集群 redis‐cli ‐a 123456 ‐‐cluster create ‐‐cluster‐replicas 1 192.168.139.30:8011 192.168.139.30:8012 192.168.139.30:8021 192.168.139.30:8022 192.168.139.30:8031 192.168.139.30:8032 # MongoDB ## docker 安装 拉取镜像 docker pull MongoDB 密码启动镜像 docker run -d --name mongodb --restart always --privileged -p 27017:27017 -v /app/mongodb/data:/data/db -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=123456 mongodb mongod --auth # Zookeeper ## Zookeeper docker启动命令 docker run -d --name zookeeper --privileged=true -p 2181:2181 -v /app/zookeeper/zookeeper-2181/data:/data -v /app/zookeeper/zookeeper-2181/conf:/ls -v /app/zookeeper/zookeeper-2181/logs:/datalog zookeeper:3.5.7 集群zoo.cfg,三个一样 ```shell # Zookeeper保存数据的目录,默认情况下,Zookeeper将写数据的日志文件也保存在这个目录里 dataDir=/data # 事物日志存储地点,如果没提供的话使用的则是 dataDir dataLogDir=/datalog # 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。tickTime以毫秒为单位 tickTime=2000 # 集群中的follower服务器(F)与leader服务器(L)之间初始连接时能容忍的最多心跳数(tickTime的数量) initLimit=5 # 集群中的follower服务器与leader服务器之间请求和应答之间能容忍的最多心跳数(tickTime的数量) syncLimit=2 # 默认值为3,不支持以系统属性方式配置。用于配置Zookeeper在自动清理的时候需要保留的快照数据文件数量和对应的事务日志文件。此参数的最小值为3,如果配置的值小于3会自动调整到3 autopurge.snapRetainCount=3 # 默认值为0,单位为小时,不支持以系统属性方式配置。用于配置Zookeeper进行历史文件自动清理的频率。如果配置为0或负数,表示不需要开启定时清理功能 autopurge.purgeInterval=0 # 默认为60,不支持以系统属性方式配置。从Socket层面限制单个客户端与单台服务器之间的并发连接数,即以ip地址来进行连接数的限制。 # 如果设置为0,表示不做任何限制。仅仅是单台客户端与单个Zookeeper服务器连接数的限制,不能控制所有客户端的连接数总和 maxClientCnxns=60 # 3.5.0中的新功能:当设置为false时,可以在复制模式下启动单个服务器,单个参与者可以使用观察者运行,并且群集可以重新配置为一个节点,并且从一个节点。 # 对于向后兼容性,默认值为true。可以使用QuorumPeerConfig的setStandaloneEnabled方法或通过将“standaloneEnabled = false”或“standaloneEnabled = true”添加到服务器的配置文件来设置它。 standaloneEnabled=false # 内嵌的管理控制台,停用这个服务 admin.enableServer=false # 开启四字命令,将所有命令添加到白名单中 4lw.commands.whitelist=* # 开启端口监听 quorumListenOnAllIPs=true # 集群中服务的列表 server.1=172.168.0.1:2888:3888 server.2=172.168.0.2:2888:3888 server.3=172.168.0.3:2888:3888 ``` 为集群创建网络 docker network create --driver bridge --subnet=172.168.0.0/16 --gateway=172.168.1.1 mynet-zookeeper 集群启动 docker run -d --restart always --name zookeeper-node1 --network zookeeper-net --ip 172.21.0.1 -p 2191:2181 -e ZOO_MY_ID=1 -v /app/zookeeper/zookeeper-cluster/node1/conf/zoo.cfg:/conf/zoo.cfg -v /app/zookeeper/zookeeper-cluster/node1/data:/data -v /app/zookeeper/zookeeper-cluster/node1/datalog:/datalog -v /app/zookeeper/zookeeper-cluster/node1/logs:/logs zookeeper:3.5.7 docker run -d --restart always --name zookeeper-node2 --network zookeeper-net --ip 172.21.0.2 -p 2192:2181 -e ZOO_MY_ID=1 -v /app/zookeeper/zookeeper-cluster/node2/conf/zoo.cfg:/conf/zoo.cfg -v /app/zookeeper/zookeeper-cluster/node2/data:/data -v /app/zookeeper/zookeeper-cluster/node2/datalog:/datalog -v /app/zookeeper/zookeeper-cluster/node2/logs:/logs zookeeper:3.5.7 docker run -d --restart always --name zookeeper-node3 --network zookeeper-net --ip 172.21.0.3 -p 2193:2181 -e ZOO_MY_ID=1 -v /app/zookeeper/zookeeper-cluster/node3/conf/zoo.cfg:/conf/zoo.cfg -v /app/zookeeper/zookeeper-cluster/node3/data:/data -v /app/zookeeper/zookeeper-cluster/node3/datalog:/datalog -v /app/zookeeper/zookeeper-cluster/node3/logs:/logs zookeeper:3.5.7 启动后修改data/myid文件 修改为跟对应的 分别在zk、zk2、zk3、的datadir中新建myid文件, 写入一个数字, 该数字表示这是第几号server. 该数字必须和zoo.cfg文件中的server.x中的x一一对应. /opt/zk/zk/data/myid文件中写入0, /opt/zk/zk2/data/myid文件中写入1, /opt/zk/zk3/data/myid文件中写入2. 查看容器中zookeeper程序状态 docker exec -it 0dd3eae27172 zkServer.sh status # kafka安装 [Docker - 通过容器部署Kafka环境教程(以及ZooKeeper) (hangge.com)](https://www.hangge.com/blog/cache/detail_2791.html) ``` docker run -d --name kafka --publish 9092:9092 \ --link zookeeper \ --env KAFKA_ZOOKEEPER_CONNECT=192.168.139.30:2181 \ --env KAFKA_ADVERTISED_HOST_NAME=192.168.139.30 \ --env KAFKA_ADVERTISED_PORT=9092 \ --env KAFKA_LOG_DIRS=/kafka/kafka-logs-1 \ -v /app/kafka/kafka-9092/logs:/kafka/kafka-logs-1 \ wurstmeister/kafka ``` 查看所有topic命令 docker exec kafka kafka-topics.sh --list --zookeeper 192.168.139.30:2191 docker run -d --name kafka --publish 9092:9092 \--link zookeeper \--env KAFKA_ZOOKEEPER_CONNECT=192.168.139.30:2181 \--env KAFKA_ADVERTISED_HOST_NAME=192.168.139.30 \--env KAFKA_ADVERTISED_PORT=9092 \--env KAFKA_LOG_DIRS=/kafka/kafka-logs-1 \-v /app/kafka/kafka-9092/logs:/kafka/kafka-logs-1 \wurstmeister/kafka kafka-manager安装 ``` docker run -d --name kfk-manager -p 9000:9000 -e ZK_HOSTS=192.168.139.30:2181 sheepkiller/kafka-manager:latest ``` docker启动所有容器 docker start $(docker ps -a | awk '{ print $1}' | tail -n +2) # ES安装 sudo mkdir -p /opt/elasticsearch/config sudo mkdir -p /opt/elasticsearch/data sudo mkdir -p /opt/elasticsearch/plugins # Kibana docker run -d -p 5601:5601 --network elasticsearch-network -v /app/kibana/kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml --restart=always --name kibana kibana:7.17.7 ES集群安装 docker run --name elasticsearch-node1 -p 9200:9200 -p 9300:9300 --network es-net -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -v /etc/lcaltime:/etc/localtime -v /app/elasticsearch/elasticsearch-cluster/node1/config/es1.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /app/elasticsearch/elasticsearch-cluster/node1/data:/usr/share/elasticsearch/data -v /app/elasticsearch/elasticsearch-cluster/node1/plugins:/usr/share/elasticsearch/plugins -d elasticsearch:7.17.7 ```console docker run -d --name elasticsearch -e ES_JAVA_OPTS="-Xms128m -Xmx512m" -v /app/elasticsearch/elasticsearch-single/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml --net elasticsearch-network -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.17.7 ``` 主节点 docker run -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d -p 9200:9200 -p 9300:9300 -v /app/elasticsearch/elasticsearch-cluster/node1/config/es1.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /app/elasticsearch/elasticsearch-cluster/node1/data:/usr/share/elasticsearch/data --name elasticsearch01 docker.io/elasticsearch:7.9.3 # Nacos集群部署