Skip to content

Commit 973d07a

Browse files
committed
feat: 分布式示例
1 parent 2b38ba8 commit 973d07a

File tree

12 files changed

+420
-5
lines changed

12 files changed

+420
-5
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<parent>
7+
<groupId>io.github.dunwu.distributed</groupId>
8+
<artifactId>java-distributed</artifactId>
9+
<version>1.0.0</version>
10+
</parent>
11+
12+
<groupId>io.github.dunwu.javatech</groupId>
13+
<artifactId>java-distributed-id</artifactId>
14+
<version>1.0.0</version>
15+
<packaging>jar</packaging>
16+
<name>${project.artifactId}</name>
17+
18+
<properties>
19+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
20+
<java.version>1.8</java.version>
21+
<maven.compiler.source>${java.version}</maven.compiler.source>
22+
<maven.compiler.target>${java.version}</maven.compiler.target>
23+
</properties>
24+
25+
<dependencies>
26+
<dependency>
27+
<groupId>org.apache.zookeeper</groupId>
28+
<artifactId>zookeeper</artifactId>
29+
</dependency>
30+
<dependency>
31+
<groupId>org.apache.curator</groupId>
32+
<artifactId>curator-recipes</artifactId>
33+
</dependency>
34+
<dependency>
35+
<groupId>redis.clients</groupId>
36+
<artifactId>jedis</artifactId>
37+
</dependency>
38+
<dependency>
39+
<groupId>cn.hutool</groupId>
40+
<artifactId>hutool-all</artifactId>
41+
</dependency>
42+
<dependency>
43+
<groupId>org.projectlombok</groupId>
44+
<artifactId>lombok</artifactId>
45+
</dependency>
46+
<dependency>
47+
<groupId>ch.qos.logback</groupId>
48+
<artifactId>logback-classic</artifactId>
49+
<optional>true</optional>
50+
</dependency>
51+
</dependencies>
52+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package io.github.dunwu.distributed.id;
2+
3+
import cn.hutool.core.collection.CollectionUtil;
4+
import lombok.extern.slf4j.Slf4j;
5+
import org.apache.curator.RetryPolicy;
6+
import org.apache.curator.framework.CuratorFramework;
7+
import org.apache.curator.framework.CuratorFrameworkFactory;
8+
import org.apache.curator.retry.ExponentialBackoffRetry;
9+
import org.apache.zookeeper.CreateMode;
10+
11+
import java.util.List;
12+
13+
/**
14+
* ZK 分布式 ID
15+
*
16+
* @author <a href="mailto:forbreak@163.com">Zhang Peng</a>
17+
* @date 2024-12-20
18+
*/
19+
@Slf4j
20+
public class ZookeeperDistributedId {
21+
22+
public static void main(String[] args) throws Exception {
23+
24+
// 获取客户端
25+
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
26+
CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", retryPolicy);
27+
28+
// 开启会话
29+
client.start();
30+
31+
String id1 = client.create()
32+
.creatingParentsIfNeeded()
33+
.withMode(CreateMode.PERSISTENT_SEQUENTIAL)
34+
.forPath("/zkid/id_");
35+
log.info("id: {}", id1);
36+
37+
String id2 = client.create()
38+
.creatingParentsIfNeeded()
39+
.withMode(CreateMode.PERSISTENT_SEQUENTIAL)
40+
.forPath("/zkid/id_");
41+
log.info("id: {}", id2);
42+
43+
List<String> children = client.getChildren().forPath("/zkid");
44+
if (CollectionUtil.isNotEmpty(children)) {
45+
for (String child : children) {
46+
client.delete().forPath("/zkid/" + child);
47+
}
48+
}
49+
client.delete().forPath("/zkid");
50+
51+
// 关闭客户端
52+
client.close();
53+
}
54+
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package io.github.dunwu.distributed.id;
2+
3+
import lombok.extern.slf4j.Slf4j;
4+
import org.apache.curator.RetryPolicy;
5+
import org.apache.curator.framework.CuratorFramework;
6+
import org.apache.curator.framework.CuratorFrameworkFactory;
7+
import org.apache.curator.framework.recipes.atomic.AtomicValue;
8+
import org.apache.curator.framework.recipes.atomic.DistributedAtomicLong;
9+
import org.apache.curator.retry.ExponentialBackoffRetry;
10+
11+
/**
12+
* ZK 分布式 ID
13+
* <p>
14+
* 基于原子计数器生成 ID
15+
*
16+
* @author <a href="mailto:forbreak@163.com">Zhang Peng</a>
17+
* @date 2024-12-20
18+
*/
19+
@Slf4j
20+
public class ZookeeperDistributedId2 {
21+
22+
public static void main(String[] args) throws Exception {
23+
24+
// 获取客户端
25+
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
26+
CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", retryPolicy);
27+
DistributedAtomicLong atomicLong = new DistributedAtomicLong(client, "/zkid", retryPolicy);
28+
29+
// 开启会话
30+
client.start();
31+
32+
// 基于原子计数器生成 ID
33+
AtomicValue<Long> id1 = atomicLong.increment();
34+
log.info("id: {}", id1.postValue());
35+
36+
AtomicValue<Long> id2 = atomicLong.increment();
37+
log.info("id: {}", id2.postValue());
38+
39+
// 清理节点
40+
client.delete().forPath("/zkid");
41+
42+
// 关闭客户端
43+
client.close();
44+
}
45+
46+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
-- 缓存 Key
2+
local key = KEYS[1]
3+
-- 访问请求数
4+
local permits = tonumber(ARGV[1])
5+
-- 过期时间
6+
local seconds = tonumber(ARGV[2])
7+
-- 限流阈值
8+
local limit = tonumber(ARGV[3])
9+
10+
-- 获取统计值
11+
local count = tonumber(redis.call('GET', key) or "0")
12+
13+
if count + permits > limit then
14+
-- 请求拒绝
15+
return -1
16+
else
17+
-- 请求通过
18+
redis.call('INCRBY', key, permits)
19+
redis.call('EXPIRE', key, seconds)
20+
return count + permits
21+
end
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
local tokenKey = KEYS[1]
2+
local timeKey = KEYS[2]
3+
4+
-- 申请令牌数
5+
local permits = tonumber(ARGV[1])
6+
-- QPS
7+
local qps = tonumber(ARGV[2])
8+
-- 桶的容量
9+
local capacity = tonumber(ARGV[3])
10+
-- 当前时间(单位:毫秒)
11+
local nowMillis = tonumber(ARGV[4])
12+
-- 填满令牌桶所需要的时间
13+
local fillTime = capacity / qps
14+
local ttl = math.min(capacity, math.floor(fillTime * 2))
15+
16+
local currentTokenNum = tonumber(redis.call("GET", tokenKey))
17+
if currentTokenNum == nil then
18+
currentTokenNum = capacity
19+
end
20+
21+
local endTimeMillis = tonumber(redis.call("GET", timeKey))
22+
if endTimeMillis == nil then
23+
endTimeMillis = 0
24+
end
25+
26+
local gap = nowMillis - endTimeMillis
27+
local newTokenNum = math.max(0, gap * qps / 1000)
28+
local currentTokenNum = math.min(capacity, currentTokenNum + newTokenNum)
29+
30+
if currentTokenNum < permits then
31+
-- 请求拒绝
32+
return -1
33+
else
34+
-- 请求通过
35+
local finalTokenNum = currentTokenNum - permits
36+
redis.call("SETEX", tokenKey, ttl, finalTokenNum)
37+
redis.call("SETEX", timeKey, ttl, nowMillis)
38+
return finalTokenNum
39+
end

codes/java-distributed/java-load-balance/pom.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
<artifactId>java-load-balance</artifactId>
88
<version>1.0.0</version>
99
<packaging>jar</packaging>
10-
<name>${project.artifactId}</name>
1110

1211
<properties>
1312
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

codes/java-distributed/java-rate-limit/pom.xml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
44
<modelVersion>4.0.0</modelVersion>
55

6-
<groupId>io.github.dunwu.javatech</groupId>
6+
<groupId>io.github.dunwu.distributed</groupId>
77
<artifactId>java-rate-limit</artifactId>
88
<version>1.0.0</version>
99
<packaging>jar</packaging>
10-
<name>${project.artifactId}</name>
1110

1211
<properties>
1312
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<parent>
7+
<groupId>io.github.dunwu.distributed</groupId>
8+
<artifactId>java-distributed</artifactId>
9+
<version>1.0.0</version>
10+
</parent>
11+
12+
<groupId>io.github.dunwu.distributed</groupId>
13+
<artifactId>java-task</artifactId>
14+
<version>1.0.0</version>
15+
<packaging>jar</packaging>
16+
17+
<properties>
18+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
19+
<java.version>1.8</java.version>
20+
<maven.compiler.source>${java.version}</maven.compiler.source>
21+
<maven.compiler.target>${java.version}</maven.compiler.target>
22+
</properties>
23+
24+
<dependencies>
25+
<dependency>
26+
<groupId>cn.hutool</groupId>
27+
<artifactId>hutool-all</artifactId>
28+
</dependency>
29+
<dependency>
30+
<groupId>org.projectlombok</groupId>
31+
<artifactId>lombok</artifactId>
32+
</dependency>
33+
<dependency>
34+
<groupId>ch.qos.logback</groupId>
35+
<artifactId>logback-classic</artifactId>
36+
<version>1.2.3</version>
37+
<optional>true</optional>
38+
</dependency>
39+
</dependencies>
40+
</project>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package io.github.dunwu.local.task;
2+
3+
import cn.hutool.core.date.DateUtil;
4+
import lombok.extern.slf4j.Slf4j;
5+
6+
import java.util.Date;
7+
import java.util.concurrent.BlockingQueue;
8+
import java.util.concurrent.DelayQueue;
9+
import java.util.concurrent.Delayed;
10+
import java.util.concurrent.TimeUnit;
11+
12+
@Slf4j
13+
public class DelayQueueExample {
14+
15+
public static void main(String[] args) throws InterruptedException {
16+
BlockingQueue<SampleTask> delayQueue = new DelayQueue<>();
17+
long now = System.currentTimeMillis();
18+
delayQueue.put(new SampleTask(now + 1000));
19+
delayQueue.put(new SampleTask(now + 2000));
20+
delayQueue.put(new SampleTask(now + 3000));
21+
for (int i = 0; i < 3; i++) {
22+
log.info("task 执行时间:{}", DateUtil.format(new Date(delayQueue.take().getTime()), "yyyy-MM-dd HH:mm:ss"));
23+
}
24+
}
25+
26+
static class SampleTask implements Delayed {
27+
28+
long time;
29+
30+
public SampleTask(long time) {
31+
this.time = time;
32+
}
33+
34+
public long getTime() {
35+
return time;
36+
}
37+
38+
@Override
39+
public int compareTo(Delayed o) {
40+
return Long.compare(this.getDelay(TimeUnit.MILLISECONDS), o.getDelay(TimeUnit.MILLISECONDS));
41+
}
42+
43+
@Override
44+
public long getDelay(TimeUnit unit) {
45+
return unit.convert(time - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
46+
}
47+
48+
}
49+
50+
}
51+
52+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package io.github.dunwu.local.task;
2+
3+
import cn.hutool.core.date.DateUtil;
4+
import lombok.extern.slf4j.Slf4j;
5+
6+
import java.util.Date;
7+
import java.util.concurrent.Executors;
8+
import java.util.concurrent.ScheduledExecutorService;
9+
import java.util.concurrent.TimeUnit;
10+
11+
@Slf4j
12+
public class ScheduledExecutorServiceExample {
13+
14+
public static void main(String[] args) {
15+
// 创建一个 ScheduledExecutorService 对象,它将使用一个线程池来执行任务
16+
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
17+
18+
// 创建一个 Runnable 对象,这个任务将在 2 秒后执行,并且每 1 秒重复执行一次
19+
Runnable task = () -> {
20+
log.info("task 执行时间:{}", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
21+
};
22+
23+
// 安排任务在 2 秒后执行,并且每 1 秒重复执行一次
24+
executor.scheduleAtFixedRate(task, 2, 1, TimeUnit.SECONDS);
25+
26+
// 主线程等待 10 秒后结束
27+
try {
28+
Thread.sleep(10000);
29+
} catch (InterruptedException e) {
30+
e.printStackTrace();
31+
}
32+
33+
// 关闭 executor,这将停止所有正在执行的任务,并拒绝新任务的提交
34+
executor.shutdown();
35+
}
36+
37+
}

0 commit comments

Comments
 (0)