Skip to content

Commit 8d3d6f2

Browse files
author
deleiguo
committed
add new modules
1 parent 001ce42 commit 8d3d6f2

File tree

38 files changed

+1045
-24
lines changed

38 files changed

+1045
-24
lines changed

source/java/interview/delei-interview-common/src/main/java/cn/delei/util/PrintUtil.java

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,25 @@
99
*/
1010
public class PrintUtil {
1111
private static final int PRINT_MAX_LENGTH = 100;
12-
private static final int PRINT_MIN_LENGTH = 20;
12+
private static final int PRINT_MIN_LENGTH = 15;
1313

1414
/**
15-
* 打印长分割线
15+
* 打印标题
1616
*/
1717
public static void printTitle() {
18-
System.out.println("<---------------------------------------------------------------->");
18+
printDivider();
1919
}
2020

2121
/**
2222
* 打印子分割线
2323
*/
2424
public static void printDivider() {
25-
System.out.println("------< *************************************************** >------");
25+
System.out.println("----------------------------------------------------------------");
2626
}
2727

2828
public static void printDivider(String title) {
2929
if (StrUtil.isNotBlank(title)) {
30-
int length = title.length();
31-
StringBuilder prefixBuilder = new StringBuilder();
32-
StringBuilder suffixBuilder = new StringBuilder();
33-
if (length <= PRINT_MIN_LENGTH) {
34-
int i = 0;
35-
do {
36-
prefixBuilder.append(" ");
37-
suffixBuilder.append(" ");
38-
i++;
39-
} while (i < (PRINT_MIN_LENGTH - length) / 2);
40-
}
41-
String result = prefixBuilder.toString() + title + suffixBuilder.toString();
42-
System.out.printf(" <--------------------------------[\t %-15s \t]-------------------------------->\n",
43-
result);
30+
System.out.printf("+ ---- %-5s \n", title);
4431
} else {
4532
printDivider();
4633
}
@@ -53,7 +40,7 @@ public static void printDivider(String title) {
5340
*/
5441
public static void printTitle(String title) {
5542
if (StrUtil.isNotBlank(title)) {
56-
System.out.printf(">------------------[\t %-15s \t]------------------<\n", title);
43+
System.out.printf("+ ------------------[ %-10s ]------------------ +\n", caclu(title));
5744
} else {
5845
printTitle();
5946
}
@@ -69,9 +56,24 @@ public static void printlnMemory(int memory) {
6956
System.out.println(runtime.freeMemory() / memory + "M(free)/" + runtime.totalMemory() / memory + "M(total)");
7057
}
7158

59+
private static String caclu(String str) {
60+
int length = str.length();
61+
StringBuilder prefixBuilder = new StringBuilder();
62+
StringBuilder suffixBuilder = new StringBuilder();
63+
if (length <= PRINT_MIN_LENGTH) {
64+
int i = 0;
65+
do {
66+
prefixBuilder.append(" ");
67+
suffixBuilder.append(" ");
68+
i++;
69+
} while (i < (PRINT_MIN_LENGTH - length) / 2);
70+
}
71+
return prefixBuilder.toString() + str + suffixBuilder.toString();
72+
}
73+
7274
public static void main(String[] args) {
7375
PrintUtil.printDivider("aaaa");
74-
PrintUtil.printDivider("bbbbbbbbbbb");
76+
PrintUtil.printTitle("bbbbbbbbbbb");
7577
PrintUtil.printDivider("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
7678
}
7779
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package cn.delei.distributed.limiter;
2+
3+
import cn.delei.util.PrintUtil;
4+
5+
import java.util.concurrent.atomic.AtomicInteger;
6+
7+
/**
8+
* 固定窗口限流简单实现
9+
*
10+
* @author deleiguo
11+
*/
12+
public class FixedWindowsRateLimiter {
13+
/**
14+
* 初始时间
15+
*/
16+
private long startTime;
17+
/**
18+
* 时间窗口限制,单位毫秒
19+
*/
20+
private int windowSize;
21+
/**
22+
* 窗口内限流阀值
23+
*/
24+
private int threshold;
25+
26+
private static final AtomicInteger ZERO = new AtomicInteger(0);
27+
28+
/**
29+
* 计数器
30+
*/
31+
private AtomicInteger counter;
32+
33+
private FixedWindowsRateLimiter() {
34+
}
35+
36+
public FixedWindowsRateLimiter(int windowSize, int threshold) {
37+
this.startTime = System.currentTimeMillis();
38+
this.windowSize = windowSize;
39+
this.threshold = threshold;
40+
this.counter = ZERO;
41+
}
42+
43+
public boolean tryAcquire() {
44+
long now = System.currentTimeMillis();
45+
int newCount = this.counter.addAndGet(1);
46+
// 判断是否在时间窗口内
47+
if ((now - this.startTime) < this.windowSize) {
48+
// 判断是否超过限流阀值
49+
if (newCount <= this.threshold) {
50+
return true;
51+
}
52+
return false;
53+
} else {
54+
// 超过时间窗口,重置
55+
this.startTime = now;
56+
this.counter.set(0);
57+
return true;
58+
}
59+
}
60+
61+
public static void main(String[] args) throws Exception {
62+
int win = 3000;
63+
int threshold = 20;
64+
// 时间窗口为1000毫秒,阀值为20
65+
FixedWindowsRateLimiter counterLimiter = new FixedWindowsRateLimiter(win, threshold);
66+
67+
int count = 0;
68+
int size = 50;
69+
PrintUtil.printTitle("01-模拟" + size + "次请求");
70+
// 模拟请求,看多少能通过
71+
for (int i = 0; i < size; i++) {
72+
if (counterLimiter.tryAcquire()) {
73+
count++;
74+
}
75+
}
76+
System.out.printf("模拟 %s 次请求,通过 %s ,限流 %s \n", size, count, (size - count));
77+
78+
//模拟时间窗口
79+
Thread.sleep(win + 200);
80+
81+
PrintUtil.printTitle("02-时间窗口过后,模拟" + size + "次请求");
82+
count = 0;
83+
for (int i = 0; i < size; i++) {
84+
if (counterLimiter.tryAcquire()) {
85+
count++;
86+
}
87+
}
88+
System.out.printf("模拟 %s 次请求,通过 %s ,限流 %s \n", size, count, (size - count));
89+
}
90+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package cn.delei.distributed.limiter;
2+
3+
import cn.delei.util.PrintUtil;
4+
5+
import java.util.concurrent.atomic.AtomicInteger;
6+
7+
8+
/**
9+
* 滑动窗口限流简单实现
10+
*
11+
* @author deleiguo
12+
*/
13+
public class SildeWindowRateLimiter {
14+
/**
15+
* 窗口大小,单位为毫秒
16+
*/
17+
private int windowSize;
18+
/**
19+
* 窗口内限流大小
20+
*/
21+
private int limit;
22+
/**
23+
* 切分小窗口的数目大小
24+
*/
25+
private int splitNum;
26+
/**
27+
* 每个小窗口的计数数组
28+
*/
29+
private AtomicInteger[] counters;
30+
/**
31+
* 当前小窗口计数器的索引
32+
*/
33+
private int index;
34+
/**
35+
* 窗口开始时间
36+
*/
37+
private long startTime;
38+
39+
private SildeWindowRateLimiter() {
40+
}
41+
42+
public SildeWindowRateLimiter(int windowSize, int limit, int splitNum) {
43+
this.limit = limit;
44+
this.windowSize = windowSize;
45+
this.splitNum = splitNum;
46+
counters = new AtomicInteger[splitNum];
47+
index = 0;
48+
startTime = System.currentTimeMillis();
49+
}
50+
51+
public boolean tryAcquire() {
52+
long now = System.currentTimeMillis();
53+
54+
// 计算滑动小窗口的数量
55+
long windowsNum = Math.max(now - windowSize - startTime, 0) / (windowSize / splitNum);
56+
// 滑动窗口
57+
slideWindow(windowsNum);
58+
59+
int count = 0;
60+
for (int i = 0; i < splitNum; i++) {
61+
count += counters[i].get();
62+
}
63+
if (count >= limit) {
64+
return false;
65+
} else {
66+
counters[index].addAndGet(1);
67+
return true;
68+
}
69+
}
70+
71+
/**
72+
* 滑动窗口
73+
*
74+
* @param windowsNum
75+
*/
76+
private void slideWindow(long windowsNum) {
77+
if (windowsNum == 0)
78+
return;
79+
long slideNum = Math.min(windowsNum, splitNum);
80+
for (int i = 0; i < slideNum; i++) {
81+
index = (index + 1) % splitNum;
82+
counters[index] = new AtomicInteger(0);
83+
}
84+
// 更新滑动窗口时间
85+
startTime = startTime + windowsNum * (windowSize / splitNum);
86+
}
87+
88+
public static void main(String[] args) throws Exception {
89+
int limit = 20;
90+
SildeWindowRateLimiter limiter = new SildeWindowRateLimiter(1000, limit, 10);
91+
92+
Thread.sleep(3000);
93+
94+
int count = 0;
95+
int failCount = 0;
96+
int size = 50;
97+
int group = 100;
98+
99+
PrintUtil.printTitle("模拟100组,每次间隔150ms,50次请求");
100+
for (int j = 0; j < group; j++) {
101+
count = 0;
102+
for (int i = 0; i < size; i++) {
103+
if (limiter.tryAcquire()) {
104+
count++;
105+
}
106+
}
107+
Thread.sleep(150);
108+
109+
// 模拟请求,看多少能通过
110+
for (int i = 0; i < size; i++) {
111+
if (limiter.tryAcquire()) {
112+
count++;
113+
}
114+
}
115+
if (count > limit) {
116+
System.out.println("时间窗口内放过的请求超过阈值,放过的请求数" + count + ",限流:" + limit);
117+
failCount++;
118+
}
119+
Thread.sleep((int) (Math.random() * 100));
120+
}
121+
System.out.printf("模拟 %s 次请求,限流失败组数 %s \n", size, failCount);
122+
}
123+
124+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<artifactId>delei-interview-mq</artifactId>
5+
<packaging>jar</packaging>
6+
<name>delei-interview-mq</name>
7+
<description>消息队列</description>
8+
9+
<parent>
10+
<groupId>cn.delei.interview</groupId>
11+
<artifactId>delei-interview-root</artifactId>
12+
<version>1.0.0</version>
13+
</parent>
14+
15+
<build>
16+
<finalName>${project.artifactId}-${project.version}</finalName>
17+
<plugins>
18+
<plugin>
19+
<groupId>org.springframework.boot</groupId>
20+
<artifactId>spring-boot-maven-plugin</artifactId>
21+
<version>2.1.18.RELEASE</version>
22+
<executions>
23+
<execution>
24+
<goals>
25+
<goal>repackage</goal>
26+
</goals>
27+
</execution>
28+
</executions>
29+
</plugin>
30+
</plugins>
31+
<resources>
32+
<resource>
33+
<directory>src/main/java</directory>
34+
<includes>
35+
<include>**/*.yml</include>
36+
<include>**/*.xml</include>
37+
</includes>
38+
<filtering>true</filtering>
39+
</resource>
40+
<resource>
41+
<directory>src/main/resources</directory>
42+
<includes>
43+
<include>**/*</include>
44+
</includes>
45+
<filtering>true</filtering>
46+
</resource>
47+
</resources>
48+
</build>
49+
50+
<dependencies>
51+
<!--delei-->
52+
<dependency>
53+
<groupId>cn.delei.interview</groupId>
54+
<artifactId>delei-interview-common</artifactId>
55+
<version>${delei.interview.version}</version>
56+
</dependency>
57+
<!-- Active MQ -->
58+
<dependency>
59+
<groupId>org.springframework.boot</groupId>
60+
<artifactId>spring-boot-starter-activemq</artifactId>
61+
</dependency>
62+
<!-- Rocket MQ -->
63+
<dependency>
64+
<groupId>org.apache.rocketmq</groupId>
65+
<artifactId>rocketmq-spring-boot-starter</artifactId>
66+
<version>2.2.1</version>
67+
</dependency>
68+
</dependencies>
69+
</project>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package cn.delei.mq;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
import org.springframework.context.ApplicationContext;
6+
7+
@SpringBootApplication
8+
public class RocketMQApplication {
9+
/**
10+
* Main方式启动方法
11+
*
12+
* @param args
13+
*/
14+
public static void main(String[] args) {
15+
// Spring Boot 启动入口
16+
ApplicationContext context = SpringApplication.run(RocketMQApplication.class, args);
17+
18+
}
19+
}

0 commit comments

Comments
 (0)