java进阶训练营作业
- 配置文件
server9091.properties
server9092.properties
server9093.properties
- 启动命令:
kafka-server-start.bat ../../config/server9001.properties
kafka-server-start.bat ../../config/server9002.properties
kafka-server-start.bat ../../config/server9003.properties
- 创建topic
kafka-topics.bat --zookeeper localhost:2181 --create --topic test32 --partitions 3 --replication-factor 2
- 生产者性能测试
kafka-producer-perf-test.bat --topic test32 --num-records 100000 --record-size 1000 --throughput 200000 --producer-props bootstrap.servers=localhost:9092
D:\kafka_2.13-2.7.0\bin\windows>kafka-producer-perf-test.bat --topic test32 --num-records 100000 --record-size 1000 --throughput 200000 --producer-props bootstrap.servers=localhost:9092
100000 records sent, 39984.006397 records/sec (38.13 MB/sec), 560.85 ms avg latency, 950.00 ms max latency, 534 ms 50th, 892 ms 95th, 947 ms 99th, 949 ms 99.9th.
D:\kafka_2.13-2.7.0\bin\windows>kafka-producer-perf-test.bat --topic test32 --num-records 100000 --record-size 1000 --throughput 200000 --producer-props bootstrap.servers=localhost:9092
100000 records sent, 50581.689428 records/sec (48.24 MB/sec), 446.13 ms avg latency, 663.00 ms max latency, 473 ms 50th, 592 ms 95th, 644 ms 99th, 660 ms 99.9th.
D:\kafka_2.13-2.7.0\bin\windows>kafka-producer-perf-test.bat --topic test32 --num-records 100000 --record-size 1000 --throughput 200000 --producer-props bootstrap.servers=localhost:9092
100000 records sent, 52659.294365 records/sec (50.22 MB/sec), 439.13 ms avg latency, 870.00 ms max latency, 370 ms 50th, 826 ms 95th, 865 ms 99th, 869 ms 99.9th.
- 消费者性能测试
kafka-consumer-perf-test.bat --bootstrap-server localhost:9092 --topic test32 --fetch-size 1048576 --messages 100000 --threads 1
D:\kafka_2.13-2.7.0\bin\windows>kafka-consumer-perf-test.bat --bootstrap-server localhost:9092 --topic test32 --fetch-size 1048576 --messages 100000 --threads 1
WARNING: option [threads] and [num-fetch-threads] have been deprecated and will be ignored by the test
start.time, end.time, data.consumed.in.MB, MB.sec, data.consumed.in.nMsg, nMsg.sec, rebalance.time.ms, fetch.time.ms, fetch.MB.sec, fetch.nMsg.sec
2021-12-20 10:37:00:924, 2021-12-20 10:37:01:748, 95.6802, 116.1168, 100329, 121758.4951, 1639967821502, -1639967820678, -0.0000, -0.0001
D:\kafka_2.13-2.7.0\bin\windows>kafka-consumer-perf-test.bat --bootstrap-server localhost:9092 --topic test32 --fetch-size 1048576 --messages 100000 --threads 1
WARNING: option [threads] and [num-fetch-threads] have been deprecated and will be ignored by the test
start.time, end.time, data.consumed.in.MB, MB.sec, data.consumed.in.nMsg, nMsg.sec, rebalance.time.ms, fetch.time.ms, fetch.MB.sec, fetch.nMsg.sec
2021-12-20 10:37:10:088, 2021-12-20 10:37:10:615, 95.6802, 181.5564, 100329, 190377.6091, 1639967830374, -1639967829847, -0.0000, -0.0001
- 配置 redis 的主从复制:
启动两个redis-server, 端口分别为6379、6380
docker run -p 6379:6379 -v /d/wj_work/redis:/usr/local/etc/redis --network host --name redis-6379 -d redis redis-server /usr/local/etc/redis/redis-6379.conf
docker run -p 6380:6380 -v /d/wj_work/redis:/usr/local/etc/redis --network host --name redis-6380 -d redis redis-server /usr/local/etc/redis/redis-6380.conf
- 方式1、通过在redis-6380命令行执行:SLAVEOF 10.1.3.89 6379 (宿主机ip: 10.1.3.89)
- 方式2、配置redis-6380.conf文件: replicaof 127.0.0.1 6379
方式1的方式从服务重启后主从关系会丢失,而第2种方式主从关系会持久化
redis-6379.conf
redis-6380.conf
- sentinel 高可用
docker run -p 26379:26379 -v /d/wj_work/redis:/usr/local/etc/redis --network host --name redis-sentinel-1 -d redis redis-sentinel /usr/local/etc/redis/sentinel-1.conf
docker run -p 26380:26380 -v /d/wj_work/redis:/usr/local/etc/redis --network host --name redis-sentinel-2 -d redis redis-sentinel /usr/local/etc/redis/sentinel-2.conf
docker run -p 26381:26381 -v /d/wj_work/redis:/usr/local/etc/redis --network host --name redis-sentinel-3 -d redis redis-sentinel /usr/local/etc/redis/sentinel-3.conf
sentinel-1.conf
sentinel-2.conf
sentinel-3.conf
- Cluster 集群
docker run -p 6390:6390 -p 16390:16390 --name redis-6390 -d redis redis-server --cluster-enabled yes --cluster-announce-ip 10.1.3.89 --port 6390
docker run -p 6391:6391 -p 16391:16391 --name redis-6391 -d redis redis-server --cluster-enabled yes --cluster-announce-ip 10.1.3.89 --port 6391
docker run -p 6392:6392 -p 16392:16392 --name redis-6392 -d redis redis-server --cluster-enabled yes --cluster-announce-ip 10.1.3.89 --port 6392
docker run -p 6393:6393 -p 16393:16393 --name redis-6393 -d redis redis-server --cluster-enabled yes --cluster-announce-ip 10.1.3.89 --port 6393
docker run -p 6394:6394 -p 16394:16394 --name redis-6394 -d redis redis-server --cluster-enabled yes --cluster-announce-ip 10.1.3.89 --port 6394
docker run -p 6395:6395 -p 16395:16395 --name redis-6395 -d redis redis-server --cluster-enabled yes --cluster-announce-ip 10.1.3.89 --port 6395
redis-cli --cluster create --cluster-replicas 1 10.1.3.89:6390 10.1.3.89:6391 10.1.3.89:6392 10.1.3.89:6393 10.1.3.89:6394 10.1.3.89:6395
-
在 Java 中实现一个简单的分布式锁;
v1版本不支持锁重入,v2版本支持锁的重入
- 在 Java 中实现一个分布式计数器,模拟减库存。
1.具体实现 2.[单元测试类](10cache/lock/src/test/java/com/wjchenge/lock/homework5/RedisMessagePublisherTest.java76以有有有有有有有有有有有有有有有有有有有777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777kjmkjmkjmkjmkjmkjmk
)
基于 ShardingSphere 的 Atomikos XA 实现的demo
测试总结:
- 使用 shardingsphere 版本
5.0.0
和5.0.alpha
测试返回 TransactionType 为LOCAL
, 但测试提交成功\失败数据库数据符合预期 - 使用 shardingsphere 版本
5.0.beta
测试返回 TransactionType 为XA
, 数据库数据结果符合预期 - 使用 shardingsphere 版本
5.0.0
和5.0.alpha
使用事务注解类ShardingSphereTransactionType
- 使用 shardingsphere 版本
5.0.beta
使用事务注解类ShardingTransactionType
- 使用 PreparedStatement 逐条提交插入
- 使用 PreparedStatement 批量提交插入
- 使用 PreparedStatement 分批次批量提交(
每次提交10000条
)插入 - 使用 PreparedStatement 多线程批量提交插入(
使用最大线程数为16的线程池,每个线程操作5000条数据
) - 使用 PreparedStatement 拼接为1条sql语句插入,(INSERT INTO TABLE () VALUES (),(),()...)
- 使用 PreparedStatement 多线程拼接sql语句插入,(INSERT INTO TABLE () VALUES (),(),()...) (
使用最大线程数为16的线程池,每个线程操作5000条数据
) - 使用 PreparedStatement 使用
数据库线程池
多线程拼接sql语句插入,(INSERT INTO TABLE () VALUES (),(),()...) (使用最大线程数为16的线程池,每个线程操作5000条数据
)
####执行效率如下:
方式 | 执行时间 |
---|---|
1 | 2124064 ms |
2 | 2030671 ms |
3 | 1979680 ms |
4 | 167804 ms |
5 | 12190ms |
6 | 7556ms |
7 | 5009ms |
作业9 实现思路如下:
作业10 实现思路如下:
根据name
字段插入的内容,如果内容为master
插入master
库, 内容为slave
插入slave
库
- 使用 xml 装配Bean
- 使用注解 @Component 和 @Autowired 装配Bean
- 使用注解 @Bean 和 @Autowired 装配Bean
自定义Starter 两个主要类:
- CustomerProperties
解析
customer
开头的配置文件属性 - AutoConfiguration
自动装配类触发条件:配置文件包含:
customer.id
- spring.factories Spring Boot 启动扫描需要自动装配的文件配置
测试类运行效果: Class1 have 1 students and one is Student(id=1000, name=KK102)
1)使用 JDBC 原生接口,实现数据库的增删改查操作。
2)使用事务,PrepareStatement 方式,批处理方式,改进上述操作。
JDBCDemo2
3)配置 Hikari 连接池,改进上述操作。提交代码到 GitHub。
- 添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
- 配置连接池:application.properties
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/wjchenge_test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
spring.datasource.hikari.username=root
spring.datasource.hikari.password=root
- 使用 sleep 等待线程执行完成拿到结果
- 使用 join 等待线程执行完成拿到结果
- 使用 自旋机制 拿到结果
- 使用 Future 拿到结果
- 使用 阻塞队列 拿到结果
- 使用 sleep 等待线程执行完成拿到结果
- 使用 join 等待线程执行完成拿到结果
- 使用 自旋机制 拿到结果
- 使用 Future 拿到结果
- 使用 阻塞队列 拿到结果
访问 http://localhost:8808/test 运行结果如下:
Executing request GET http://127.0.0.1:8801/test
----------------------------------------
hello,nio1
Executing request GET http://127.0.0.1:8801/favicon.ico
----------------------------------------
hello,nio1
大体思路利用Java SPI扩展机制进行过滤器的扩展实现:
META-INF/services/nio.wjchenge.netty.gateway.v2.filter.HttpRequestFilter
gateway服务运行结果如下:
Executing request GET http://127.0.0.1:8801/test
----------------------------------------
hello,nio1
Executing request GET http://127.0.0.1:8801/favicon.ico
----------------------------------------
hello,nio1
HttpServer服务运行结果如下:
打印请求体-------------------begin
GET /test HTTP/1.1
Host: localhost:8808
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: "Google Chrome";v="93", " Not;A Brand";v="99", "Chromium";v="93"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: _ga=GA1.1.1196342184.1629275253; _gid=GA1.1.2046123892.1633932950
mao: soul
打印请求体-------------------end
打印请求体-------------------begin
GET /favicon.ico HTTP/1.1
Host: localhost:8808
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
sec-ch-ua: "Google Chrome";v="93", " Not;A Brand";v="99", "Chromium";v="93"
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36
sec-ch-ua-platform: "Windows"
Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: no-cors
Sec-Fetch-Dest: image
Referer: http://localhost:8808/test
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: _ga=GA1.1.1196342184.1629275253; _gid=GA1.1.2046123892.1633932950
mao: soul
打印请求体-------------------end
大体思路利用Java SPI扩展机制进行过滤器的扩展实现,与过滤器实现细节唯一不同的地方在于如果不配置路由规则默认使用随机路由规则
,
如果配置多个路由规则则使用系统最先读取到的规则
为准
目前实现了随机算法、轮询算法、随机权重算法路由规则
META-INF/services/nio.wjchenge.netty.gateway.v3.router.HttpEndpointRouter
实现思路
先生成随机数,然后根据随机数下标取集合的值
实现思路
按顺序循环取集合的值
实现思路
方案1:根据服务配置的权重进行服务集合重新赋值,配置多少权重集合中就存在多少条记录。该方案实现简单,但如果权重配置过大则比较耗费内存。
方案2:假设我们有一组服务[A, B, C], 他们对应的权重为[20, 30, 50], 权重总和为100。现在把这些权重值平铺在一维坐标上,分布情况[0, 20)
属于服务A, [20, 50) 属于服务B, [50, 100) 属于服务C, 然后生成 [0, 100) 范围的随机数,接下来计算该随机数属于哪个区间。
方案2实现:WeightRandomHttpEndpointRouter
####各路由算法测试结果(测试10次,每次模拟调用服务10000次
)如下:
- 随机路由算法
{server3=5377, server2=1839, server1=2784}
{server2=4483, server1=5517}
{server3=5503, server2=4497}
{server3=4176, server1=5824}
{server2=2809, server1=7191}
{server2=8429, server1=1571}
{server3=8889, server1=1111}
{server3=3465, server2=3509, server1=3026}
{server1=10000}
{server3=6027, server2=3598, server1=375}
- 轮询路由算法
{server3=3334, server2=3333, server1=3333}
{server3=3333, server2=3334, server1=3333}
{server3=3333, server2=3333, server1=3334}
{server3=3334, server2=3333, server1=3333}
{server3=3333, server2=3334, server1=3333}
{server3=3333, server2=3333, server1=3334}
{server3=3334, server2=3333, server1=3333}
{server3=3333, server2=3334, server1=3333}
{server3=3333, server2=3333, server1=3334}
{server3=3334, server2=3333, server1=3333}
- 随机权重路由算法
{server3=4951, server2=3120, server1=1929}
{server3=5029, server2=3028, server1=1943}
{server3=5128, server2=2915, server1=1957}
{server3=4935, server2=3093, server1=1972}
{server3=5069, server2=3003, server1=1928}
{server3=5076, server2=3016, server1=1908}
{server3=4975, server2=3090, server1=1935}
{server3=5167, server2=2937, server1=1896}
{server3=5038, server2=3051, server1=1911}
{server3=5072, server2=3038, server1=1890}
作业6 (必做)写一段代码,使用 HttpClient 或 OkHttp 访问 http://localhost:8801 ,代码提交到 GitHub
运行结果
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Executing request GET http://127.0.0.1:8801/
----------------------------------------
hello,nio1