Skip to content

Commit

Permalink
增加一个与调度器结合起来的节流注解,可支持集群状态下的任务调度。
Browse files Browse the repository at this point in the history
  • Loading branch information
InsideZhou committed May 13, 2020
1 parent 92b0b1d commit 2e11cf0
Show file tree
Hide file tree
Showing 12 changed files with 202 additions and 57 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ plugins {

allprojects {
group = 'me.insidezhou.southernquiet'
version = '4.3.0'
version = '4.3.1'

ext {
jsonpathVersion = '2.4.0'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
import me.insidezhou.southernquiet.keyvalue.KeyValueStore;
import me.insidezhou.southernquiet.keyvalue.driver.FileSystemKeyValueStore;
import me.insidezhou.southernquiet.throttle.DefaultThrottleManager;
import me.insidezhou.southernquiet.throttle.ThrottleAdvice;
import me.insidezhou.southernquiet.throttle.ThrottleBeanPostProcessor;
import me.insidezhou.southernquiet.throttle.ThrottleManager;
import me.insidezhou.southernquiet.throttle.annotation.ThrottleAdvice;
import me.insidezhou.southernquiet.throttle.annotation.ThrottleBeanPostProcessor;
import me.insidezhou.southernquiet.util.AsyncRunner;
import me.insidezhou.southernquiet.util.Metadata;
import org.springframework.beans.factory.annotation.Qualifier;
Expand All @@ -21,6 +21,7 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.util.StringUtils;
Expand All @@ -33,6 +34,7 @@

@Configuration
@EnableAsync
@EnableScheduling
@EnableConfigurationProperties
public class FrameworkAutoConfiguration {
public final static String ConfigRoot = "southern-quiet.framework";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import org.jetbrains.annotations.NotNull;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.util.Assert;
import org.springframework.util.PathMatcher;
import org.springframework.util.StringUtils;
Expand All @@ -29,8 +29,8 @@ public AuthAdvice(PathMatcher pathMatcher) {
public void before(@NotNull Method method, @NotNull Object[] args, Object target) throws AuthException {
Assert.notNull(target, "身份及权限验证时目标对象不该为null");

Auth methodAuthorization = AnnotationUtils.getAnnotation(method, Auth.class);
Auth classAuthorization = AnnotationUtils.getAnnotation(target.getClass(), Auth.class);
Auth methodAuthorization = AnnotatedElementUtils.findMergedAnnotation(method, Auth.class);
Auth classAuthorization = AnnotatedElementUtils.findMergedAnnotation(target.getClass(), Auth.class);

Map<Auth.MatchMode, List<Auth>> groupedAuth = Stream.of(methodAuthorization, classAuthorization).filter(Objects::nonNull)
.collect(Collectors.groupingBy(Auth::mode));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
package me.insidezhou.southernquiet.throttle.annotation;
package me.insidezhou.southernquiet.throttle;

import me.insidezhou.southernquiet.throttle.ThrottleManager;
import org.jetbrains.annotations.NotNull;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.core.annotation.AnnotationUtils;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

public class ThrottleAdvice implements MethodBeforeAdvice {
public class ThrottleAdvice implements MethodInterceptor {
private final ThrottleManager throttleManager;

public ThrottleAdvice(ThrottleManager throttleManager) {
this.throttleManager = throttleManager;
}

@Override
public void before(@NotNull Method method, @NotNull Object[] args, Object target) throws Throwable {
Throttle annotation = AnnotationUtils.getAnnotation(method, Throttle.class);
public Object invoke(MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
me.insidezhou.southernquiet.throttle.annotation.Throttle annotation = AnnotatedElementUtils.findMergedAnnotation(method, me.insidezhou.southernquiet.throttle.annotation.Throttle.class);
assert annotation != null;

String throttleName = Objects.requireNonNull(annotation).throttleName();
String throttleName = annotation.name();
long threshold = annotation.threshold();
TimeUnit[] timeUnits = annotation.timeUnit();

Expand All @@ -30,18 +30,20 @@ public void before(@NotNull Method method, @NotNull Object[] args, Object target
}

me.insidezhou.southernquiet.throttle.Throttle throttle;
TimeUnit timeUnit = null;

if (timeUnits.length > 0) {
//time based
throttle = throttleManager.getTimeBased(throttleName);

TimeUnit timeUnit = timeUnits[0];
timeUnit = timeUnits[0];
threshold = timeUnit.toMillis(threshold);
}
else {
//count based
throttle = throttleManager.getCountBased(throttleName);
}

if (!throttle.open(threshold)) throw new ThrottleException();
return throttle.open(threshold) ? invocation.proceed() : null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package me.insidezhou.southernquiet.throttle;

import me.insidezhou.southernquiet.throttle.annotation.ThrottledSchedule;
import me.insidezhou.southernquiet.throttle.annotation.Throttle;
import org.springframework.aop.framework.autoproxy.AbstractBeanFactoryAwareAdvisingPostProcessor;
import org.springframework.aop.support.ComposablePointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;

public class ThrottleBeanPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor {
public ThrottleBeanPostProcessor(ThrottleAdvice advice) {
this.advisor = new DefaultPointcutAdvisor(
new ComposablePointcut(AnnotationMatchingPointcut.forMethodAnnotation(Throttle.class))
.union(AnnotationMatchingPointcut.forMethodAnnotation(ThrottledSchedule.class)),
advice);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package me.insidezhou.southernquiet.throttle;

import java.util.concurrent.TimeUnit;

public class ThrottleException extends Exception {
public ThrottleException(String throttleName, long threshold, TimeUnit timeUnit) {
super("throttleName='" + throttleName + '\'' +
", threshold=" + threshold +
", timeUnit=" + timeUnit);

this.throttleName = throttleName;
this.threshold = threshold;
this.timeUnit = timeUnit;
}

private String throttleName;
private long threshold;
private TimeUnit timeUnit;

public String getThrottleName() {
return throttleName;
}

public void setThrottleName(String throttleName) {
this.throttleName = throttleName;
}

public long getThreshold() {
return threshold;
}

public void setThreshold(long threshold) {
this.threshold = threshold;
}

public TimeUnit getTimeUnit() {
return timeUnit;
}

public void setTimeUnit(TimeUnit timeUnit) {
this.timeUnit = timeUnit;
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
package me.insidezhou.southernquiet.throttle.annotation;

import org.springframework.core.annotation.AliasFor;

import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;

/**
* 节流器注解,在method上使用,对该method进行节流。
* <p>timeUnit可空,若为空则创建计数器节流器,否则创建时间节流器;
* <p>throttleName可空,若为空则使用类名#方法名作为节流器名称
*
*/
@Target({ElementType.METHOD})
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Throttle {
@AliasFor("threshold")
long value() default -1;

String throttleName() default "";
@AliasFor("value")
long threshold() default -1;

long threshold();
/**
* 若为空则使用类名#方法名作为节流器名称。
*/
String name() default "";

/**
* 若为空则创建计数器节流器,否则创建时间节流器。
*/
TimeUnit[] timeUnit() default {};

}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package me.insidezhou.southernquiet.throttle.annotation;

import org.springframework.core.annotation.AliasFor;
import org.springframework.scheduling.annotation.Scheduled;

import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Throttle
@Scheduled
public @interface ThrottledSchedule {
@AliasFor(annotation = Throttle.class)
long value() default -1;

@AliasFor(annotation = Throttle.class)
long threshold() default -1;

@AliasFor(annotation = Throttle.class)
String name() default "";

@AliasFor(annotation = Throttle.class)
TimeUnit[] timeUnit() default {};

@AliasFor(annotation = Scheduled.class)
String cron() default "";

@AliasFor(annotation = Scheduled.class)
String zone() default "";

@AliasFor(annotation = Scheduled.class)
long fixedDelay() default -1;

@AliasFor(annotation = Scheduled.class)
String fixedDelayString() default "";

@AliasFor(annotation = Scheduled.class)
long fixedRate() default -1;

@AliasFor(annotation = Scheduled.class)
String fixedRateString() default "";

@AliasFor(annotation = Scheduled.class)
long initialDelay() default -1;

@AliasFor(annotation = Scheduled.class)
String initialDelayString() default "";
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,49 +29,91 @@ private void reset() {
public void countBaseReturnObj() {
reset();

Integer count = throttleAnnotationTestProcessor.countBaseReturnObj(1);
Integer count = null;
try {
count = throttleAnnotationTestProcessor.countBaseReturnObj(1);
}
catch (Exception e) {
e.printStackTrace();
}
Assert.assertNull(count);

count = throttleAnnotationTestProcessor.countBaseReturnObj(1);
try {
count = throttleAnnotationTestProcessor.countBaseReturnObj(1);
}
catch (Exception e) {
e.printStackTrace();
}
Assert.assertNotNull(count);
Assert.assertEquals(1,count.intValue());
Assert.assertEquals(1, count.intValue());
}

@Test
public void countBaseVoid() {
reset();

throttleAnnotationTestProcessor.countBaseVoid(1);
try {
throttleAnnotationTestProcessor.countBaseVoid(1);
}
catch (Exception e) {
e.printStackTrace();
}
Assert.assertEquals(0, throttleAnnotationTestProcessor.getCountVoid());

throttleAnnotationTestProcessor.countBaseVoid(1);
try {
throttleAnnotationTestProcessor.countBaseVoid(1);
}
catch (Exception e) {
e.printStackTrace();
}
Assert.assertEquals(1, throttleAnnotationTestProcessor.getCountVoid());
}

@Test
public void timeBaseReturnObj() throws InterruptedException {
reset();

Integer count = throttleAnnotationTestProcessor.timeBaseReturnObj(1);
Integer count = null;
try {
count = throttleAnnotationTestProcessor.timeBaseReturnObj(1);
}
catch (Exception e) {
e.printStackTrace();
}
Assert.assertNull(count);

Thread.sleep(1100);

count = throttleAnnotationTestProcessor.timeBaseReturnObj(1);
try {
count = throttleAnnotationTestProcessor.timeBaseReturnObj(1);
}
catch (Exception e) {
e.printStackTrace();
}
Assert.assertNotNull(count);
Assert.assertEquals(1,count.intValue());
Assert.assertEquals(1, count.intValue());
}

@Test
public void timeBaseVoid() throws InterruptedException {
reset();

throttleAnnotationTestProcessor.timeBaseVoid(1);
try {
throttleAnnotationTestProcessor.timeBaseVoid(1);
}
catch (Exception e) {
e.printStackTrace();
}
Assert.assertEquals(0, throttleAnnotationTestProcessor.getCountVoid());

Thread.sleep(1100);

throttleAnnotationTestProcessor.timeBaseVoid(1);
try {
throttleAnnotationTestProcessor.timeBaseVoid(1);
}
catch (Exception e) {
e.printStackTrace();
}
Assert.assertEquals(1, throttleAnnotationTestProcessor.getCountVoid());
}

Expand Down
Loading

0 comments on commit 2e11cf0

Please sign in to comment.