Skip to content

Commit

Permalink
feat: 分布式示例
Browse files Browse the repository at this point in the history
  • Loading branch information
dunwu committed Dec 31, 2024
1 parent 2b38ba8 commit 973d07a
Show file tree
Hide file tree
Showing 12 changed files with 420 additions and 5 deletions.
52 changes: 52 additions & 0 deletions codes/java-distributed/java-distributed-id/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>io.github.dunwu.distributed</groupId>
<artifactId>java-distributed</artifactId>
<version>1.0.0</version>
</parent>

<groupId>io.github.dunwu.javatech</groupId>
<artifactId>java-distributed-id</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>${project.artifactId}</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package io.github.dunwu.distributed.id;

import cn.hutool.core.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;

import java.util.List;

/**
* ZK 分布式 ID
*
* @author <a href="mailto:[email protected]">Zhang Peng</a>
* @date 2024-12-20
*/
@Slf4j
public class ZookeeperDistributedId {

public static void main(String[] args) throws Exception {

// 获取客户端
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", retryPolicy);

// 开启会话
client.start();

String id1 = client.create()
.creatingParentsIfNeeded()
.withMode(CreateMode.PERSISTENT_SEQUENTIAL)
.forPath("/zkid/id_");
log.info("id: {}", id1);

String id2 = client.create()
.creatingParentsIfNeeded()
.withMode(CreateMode.PERSISTENT_SEQUENTIAL)
.forPath("/zkid/id_");
log.info("id: {}", id2);

List<String> children = client.getChildren().forPath("/zkid");
if (CollectionUtil.isNotEmpty(children)) {
for (String child : children) {
client.delete().forPath("/zkid/" + child);
}
}
client.delete().forPath("/zkid");

// 关闭客户端
client.close();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package io.github.dunwu.distributed.id;

import lombok.extern.slf4j.Slf4j;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.atomic.AtomicValue;
import org.apache.curator.framework.recipes.atomic.DistributedAtomicLong;
import org.apache.curator.retry.ExponentialBackoffRetry;

/**
* ZK 分布式 ID
* <p>
* 基于原子计数器生成 ID
*
* @author <a href="mailto:[email protected]">Zhang Peng</a>
* @date 2024-12-20
*/
@Slf4j
public class ZookeeperDistributedId2 {

public static void main(String[] args) throws Exception {

// 获取客户端
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", retryPolicy);
DistributedAtomicLong atomicLong = new DistributedAtomicLong(client, "/zkid", retryPolicy);

// 开启会话
client.start();

// 基于原子计数器生成 ID
AtomicValue<Long> id1 = atomicLong.increment();
log.info("id: {}", id1.postValue());

AtomicValue<Long> id2 = atomicLong.increment();
log.info("id: {}", id2.postValue());

// 清理节点
client.delete().forPath("/zkid");

// 关闭客户端
client.close();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-- 缓存 Key
local key = KEYS[1]
-- 访问请求数
local permits = tonumber(ARGV[1])
-- 过期时间
local seconds = tonumber(ARGV[2])
-- 限流阈值
local limit = tonumber(ARGV[3])

-- 获取统计值
local count = tonumber(redis.call('GET', key) or "0")

if count + permits > limit then
-- 请求拒绝
return -1
else
-- 请求通过
redis.call('INCRBY', key, permits)
redis.call('EXPIRE', key, seconds)
return count + permits
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
local tokenKey = KEYS[1]
local timeKey = KEYS[2]

-- 申请令牌数
local permits = tonumber(ARGV[1])
-- QPS
local qps = tonumber(ARGV[2])
-- 桶的容量
local capacity = tonumber(ARGV[3])
-- 当前时间(单位:毫秒)
local nowMillis = tonumber(ARGV[4])
-- 填满令牌桶所需要的时间
local fillTime = capacity / qps
local ttl = math.min(capacity, math.floor(fillTime * 2))

local currentTokenNum = tonumber(redis.call("GET", tokenKey))
if currentTokenNum == nil then
currentTokenNum = capacity
end

local endTimeMillis = tonumber(redis.call("GET", timeKey))
if endTimeMillis == nil then
endTimeMillis = 0
end

local gap = nowMillis - endTimeMillis
local newTokenNum = math.max(0, gap * qps / 1000)
local currentTokenNum = math.min(capacity, currentTokenNum + newTokenNum)

if currentTokenNum < permits then
-- 请求拒绝
return -1
else
-- 请求通过
local finalTokenNum = currentTokenNum - permits
redis.call("SETEX", tokenKey, ttl, finalTokenNum)
redis.call("SETEX", timeKey, ttl, nowMillis)
return finalTokenNum
end
1 change: 0 additions & 1 deletion codes/java-distributed/java-load-balance/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
<artifactId>java-load-balance</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>${project.artifactId}</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down
3 changes: 1 addition & 2 deletions codes/java-distributed/java-rate-limit/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>io.github.dunwu.javatech</groupId>
<groupId>io.github.dunwu.distributed</groupId>
<artifactId>java-rate-limit</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>${project.artifactId}</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down
40 changes: 40 additions & 0 deletions codes/java-distributed/java-task/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>io.github.dunwu.distributed</groupId>
<artifactId>java-distributed</artifactId>
<version>1.0.0</version>
</parent>

<groupId>io.github.dunwu.distributed</groupId>
<artifactId>java-task</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<optional>true</optional>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package io.github.dunwu.local.task;

import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

@Slf4j
public class DelayQueueExample {

public static void main(String[] args) throws InterruptedException {
BlockingQueue<SampleTask> delayQueue = new DelayQueue<>();
long now = System.currentTimeMillis();
delayQueue.put(new SampleTask(now + 1000));
delayQueue.put(new SampleTask(now + 2000));
delayQueue.put(new SampleTask(now + 3000));
for (int i = 0; i < 3; i++) {
log.info("task 执行时间:{}", DateUtil.format(new Date(delayQueue.take().getTime()), "yyyy-MM-dd HH:mm:ss"));
}
}

static class SampleTask implements Delayed {

long time;

public SampleTask(long time) {
this.time = time;
}

public long getTime() {
return time;
}

@Override
public int compareTo(Delayed o) {
return Long.compare(this.getDelay(TimeUnit.MILLISECONDS), o.getDelay(TimeUnit.MILLISECONDS));
}

@Override
public long getDelay(TimeUnit unit) {
return unit.convert(time - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}

}

}


Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package io.github.dunwu.local.task;

import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Slf4j
public class ScheduledExecutorServiceExample {

public static void main(String[] args) {
// 创建一个 ScheduledExecutorService 对象,它将使用一个线程池来执行任务
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

// 创建一个 Runnable 对象,这个任务将在 2 秒后执行,并且每 1 秒重复执行一次
Runnable task = () -> {
log.info("task 执行时间:{}", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
};

// 安排任务在 2 秒后执行,并且每 1 秒重复执行一次
executor.scheduleAtFixedRate(task, 2, 1, TimeUnit.SECONDS);

// 主线程等待 10 秒后结束
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}

// 关闭 executor,这将停止所有正在执行的任务,并拒绝新任务的提交
executor.shutdown();
}

}
Loading

0 comments on commit 973d07a

Please sign in to comment.