├── doc
├── user
│ ├── 01-basic.md
│ ├── 03-差异化实现.md
│ └── 02-spring.md
├── CI集成.md
├── 发布流程.md
└── 项目原型.md
├── .coveralls.yml
├── rate-limit-core
├── src
│ └── main
│ │ ├── resources
│ │ └── README.md
│ │ └── java
│ │ └── com
│ │ └── github
│ │ └── houbb
│ │ └── rate
│ │ └── limit
│ │ └── core
│ │ ├── support
│ │ ├── package-info.java
│ │ ├── proxy
│ │ │ ├── package-info.java
│ │ │ ├── dynamic
│ │ │ │ ├── package-info.java
│ │ │ │ └── DynamicProxy.java
│ │ │ ├── AbstractProxy.java
│ │ │ ├── cglib
│ │ │ │ └── CglibProxy.java
│ │ │ └── RateLimitProxy.java
│ │ ├── reject
│ │ │ ├── RateLimitRejectListener.java
│ │ │ ├── RateLimitRejectListenerException.java
│ │ │ └── RateLimitRejectListenerContext.java
│ │ ├── method
│ │ │ └── RateLimitMethodService.java
│ │ ├── token
│ │ │ └── RateLimitTokenService.java
│ │ └── config
│ │ │ └── RateLimitConfigService.java
│ │ ├── constant
│ │ └── RateLimitConst.java
│ │ ├── util
│ │ └── InnerRateLimitUtils.java
│ │ ├── annotation
│ │ ├── RateLimits.java
│ │ └── RateLimit.java
│ │ ├── dto
│ │ ├── RateLimitSlideWindowDto.java
│ │ ├── RateLimitSlideWindowInfo.java
│ │ ├── RateLimitLeakyBucketDto.java
│ │ └── RateLimitTokenBucketDto.java
│ │ ├── exception
│ │ └── RateLimitRuntimeException.java
│ │ ├── core
│ │ ├── RateLimits.java
│ │ ├── RateLimitFixedWindow.java
│ │ ├── RateLimitSlideWindowQueue.java
│ │ ├── RateLimitTokenBucket.java
│ │ ├── RateLimitContext.java
│ │ ├── RateLimitLeakyBucket.java
│ │ ├── AbstractRateLimit.java
│ │ └── RateLimitSlideWindow.java
│ │ └── bs
│ │ └── RateLimitBs.java
└── pom.xml
├── rate-limit-spring
├── src
│ └── main
│ │ ├── resources
│ │ └── README.md
│ │ └── java
│ │ └── com
│ │ └── github
│ │ └── houbb
│ │ └── rate
│ │ └── limit
│ │ └── spring
│ │ ├── annotation
│ │ └── EnableRateLimit.java
│ │ ├── aop
│ │ └── RateLimitAspect.java
│ │ └── config
│ │ └── RateLimitConfig.java
└── pom.xml
├── rate-limit-test
├── src
│ ├── test
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── github
│ │ │ │ └── houbb
│ │ │ │ └── rate
│ │ │ │ └── limit
│ │ │ │ └── test
│ │ │ │ ├── README.md
│ │ │ │ ├── core
│ │ │ │ ├── package-info.java
│ │ │ │ └── RateLimitCoreTest.java
│ │ │ │ ├── bs
│ │ │ │ └── RateLimitBsTest.java
│ │ │ │ └── spring
│ │ │ │ └── SpringConfigTest.java
│ │ └── resources
│ │ │ ├── application-test.properties
│ │ │ └── logback-test.xml
│ └── main
│ │ ├── resources
│ │ └── log4j2.xml
│ │ └── java
│ │ └── com
│ │ └── github
│ │ └── houbb
│ │ └── rate
│ │ └── limit
│ │ └── test
│ │ └── core
│ │ ├── config
│ │ └── SpringConfig.java
│ │ └── service
│ │ ├── ClassUserService.java
│ │ ├── UserService.java
│ │ ├── RepeatUserService.java
│ │ └── RepeatClassUserService.java
└── pom.xml
├── rate-limit-api
├── src
│ └── main
│ │ └── java
│ │ └── com
│ │ └── github
│ │ └── houbb
│ │ └── rate
│ │ └── limit
│ │ └── api
│ │ ├── package-info.java
│ │ ├── support
│ │ ├── package-info.java
│ │ ├── IRateLimitTokenService.java
│ │ ├── IRateLimitRejectListener.java
│ │ ├── IRateLimitMethodService.java
│ │ ├── IRateLimitConfigService.java
│ │ └── IRateLimitRejectListenerContext.java
│ │ ├── core
│ │ ├── IRateLimit.java
│ │ └── IRateLimitContext.java
│ │ └── dto
│ │ └── RateLimitConfigDto.java
└── pom.xml
├── rate-limit-test2
├── src
│ ├── main
│ │ └── java
│ │ │ └── com
│ │ │ └── github
│ │ │ └── houbb
│ │ │ └── rate
│ │ │ └── limit
│ │ │ └── test2
│ │ │ ├── package-info.java
│ │ │ ├── RateLimitApplication.java
│ │ │ └── service
│ │ │ └── UserService.java
│ └── test
│ │ └── java
│ │ └── com
│ │ └── github
│ │ └── houbb
│ │ └── rate
│ │ └── limit
│ │ └── test2
│ │ └── UserServiceTest.java
└── pom.xml
├── rate-limit-springboot-starter
├── src
│ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── houbb
│ │ │ └── rate
│ │ │ └── limit
│ │ │ └── springboot
│ │ │ └── starter
│ │ │ ├── package-info.java
│ │ │ └── config
│ │ │ └── RateLimitAutoConfig.java
│ │ └── resources
│ │ └── META-INF
│ │ └── spring.factories
└── pom.xml
├── cgit.bat
├── .gitignore
├── .travis.yml
├── release.bat
├── release_rm.sh
├── CHANGELOG.md
├── release.sh
├── README.md
├── pom.xml
└── LICENSE.txt
/doc/user/01-basic.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.coveralls.yml:
--------------------------------------------------------------------------------
1 | service_name: travis-ci
--------------------------------------------------------------------------------
/rate-limit-core/src/main/resources/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/rate-limit-spring/src/main/resources/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/rate-limit-test/src/test/java/com/github/houbb/rate/limit/test/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/rate-limit-test/src/test/resources/application-test.properties:
--------------------------------------------------------------------------------
1 | logging.level.root=INFO
--------------------------------------------------------------------------------
/rate-limit-api/src/main/java/com/github/houbb/rate/limit/api/package-info.java:
--------------------------------------------------------------------------------
1 | package com.github.houbb.rate.limit.api;
2 |
--------------------------------------------------------------------------------
/rate-limit-test2/src/main/java/com/github/houbb/rate/limit/test2/package-info.java:
--------------------------------------------------------------------------------
1 | package com.github.houbb.rate.limit.test2;
--------------------------------------------------------------------------------
/rate-limit-test/src/test/java/com/github/houbb/rate/limit/test/core/package-info.java:
--------------------------------------------------------------------------------
1 | package com.github.houbb.rate.limit.test.core;
2 |
--------------------------------------------------------------------------------
/rate-limit-api/src/main/java/com/github/houbb/rate/limit/api/support/package-info.java:
--------------------------------------------------------------------------------
1 | package com.github.houbb.rate.limit.api.support;
2 |
--------------------------------------------------------------------------------
/rate-limit-core/src/main/java/com/github/houbb/rate/limit/core/support/package-info.java:
--------------------------------------------------------------------------------
1 | package com.github.houbb.rate.limit.core.support;
2 |
--------------------------------------------------------------------------------
/rate-limit-core/src/main/java/com/github/houbb/rate/limit/core/support/proxy/package-info.java:
--------------------------------------------------------------------------------
1 | package com.github.houbb.rate.limit.core.support.proxy;
2 |
--------------------------------------------------------------------------------
/rate-limit-springboot-starter/src/main/java/com/github/houbb/rate/limit/springboot/starter/package-info.java:
--------------------------------------------------------------------------------
1 | package com.github.houbb.rate.limit.springboot.starter;
--------------------------------------------------------------------------------
/rate-limit-springboot-starter/src/main/resources/META-INF/spring.factories:
--------------------------------------------------------------------------------
1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.github.houbb.rate.limit.springboot.starter.config.RateLimitAutoConfig
--------------------------------------------------------------------------------
/cgit.bat:
--------------------------------------------------------------------------------
1 | :: 用于提交当前变更(windows)
2 | :: author: houbb
3 | :: LastUpdateTime: 2018-11-22 09:08:52
4 | :: 用法:双击运行,或者当前路径 cmd 直接输入 .\cgit.bat
5 |
6 | git pull
7 | git add .
8 | git commit -m "[Feature] add for new"
9 | git push
10 | git status
11 |
12 |
--------------------------------------------------------------------------------
/rate-limit-core/src/main/java/com/github/houbb/rate/limit/core/constant/RateLimitConst.java:
--------------------------------------------------------------------------------
1 | package com.github.houbb.rate.limit.core.constant;
2 |
3 | /**
4 | * 常量
5 | * @since 1.1.0
6 | * @author dh
7 | */
8 | public final class RateLimitConst {
9 |
10 | /**
11 | * 默认缓存 key 的命名空间
12 | */
13 | public static final String DEFAULT_CACHE_KEY_NAMESPACE = "RATE_LIMIT";
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # maven ignore
2 |
3 | *.jar
4 | *.war
5 | *.zip
6 | *.tar
7 | *.tar.gz
8 | target
9 |
10 | # eclipse ignore
11 | .settings/
12 | .project
13 | .classpath
14 |
15 | # idea ignore
16 | .idea/
17 | *.ipr
18 | *.iml
19 | *.iws
20 |
21 | # temp ignore
22 | *.log
23 | *.cache
24 | *.diff
25 | *.patch
26 | *.tmp
27 | *.java~
28 | *.properties~
29 | *.xml~
30 |
31 | # system ignore
32 | .DS_Store
33 | Thumbs.db
--------------------------------------------------------------------------------
/rate-limit-test/src/test/resources/logback-test.xml:
--------------------------------------------------------------------------------
1 |
动态代理
8 | * 9 | *Created: 2019-03-05 22:2310 | *
Project: async11 | * 12 | * @author houbinbin 13 | */ 14 | package com.github.houbb.rate.limit.core.support.proxy.dynamic; 15 | -------------------------------------------------------------------------------- /rate-limit-api/src/main/java/com/github/houbb/rate/limit/api/support/IRateLimitTokenService.java: -------------------------------------------------------------------------------- 1 | package com.github.houbb.rate.limit.api.support; 2 | 3 | /** 4 | * @author binbin.hou 5 | * @since 1.0.0 6 | */ 7 | public interface IRateLimitTokenService { 8 | 9 | /** 10 | * 根据入参构建对应的 token 11 | * @param params 从请求入参中获取信息 12 | * @return 结果 13 | * @since 1.0.0 14 | */ 15 | String getTokenId(final Object[] params); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /doc/CI集成.md: -------------------------------------------------------------------------------- 1 | # 文档说明 2 | 3 | 作者:侯宾宾 4 | 5 | 时间:2018-04-24 10:11:43 6 | 7 | 说明:如何进行项目的持续集成+测试覆盖率 8 | 9 | # Travis-CI 10 | 11 | [https://www.travis-ci.org](https://www.travis-ci.org) 直接添加此项目 12 | 13 | # Coveralls 14 | 15 | - 添加项目 16 | 17 | [https://coveralls.io/repos/new](https://coveralls.io/repos/new) 直接添加项目 18 | 19 | - 生成密匙 20 | 21 | ``` 22 | travis encrypt COVERALLS_TOKEN=${your_repo_token} 23 | ``` 24 | 25 | - 添加到文件 26 | 27 | ``` 28 | travis encrypt COVERALLS_TOKEN=${your_repo_token} --add 29 | ``` 30 | 31 | -------------------------------------------------------------------------------- /rate-limit-api/src/main/java/com/github/houbb/rate/limit/api/support/IRateLimitRejectListener.java: -------------------------------------------------------------------------------- 1 | package com.github.houbb.rate.limit.api.support; 2 | 3 | /** 4 | * @author binbin.hou 5 | * @since 1.0.0 6 | */ 7 | public interface IRateLimitRejectListener { 8 | 9 | /** 10 | * 监听拒绝的信息 11 | * 12 | * 失败时,默认抛出异常。 13 | * 14 | * 用户可以结果业务添加对应的报警+黑名单拉黑等操作。 15 | * @param context 上下文 16 | * @since 1.0.0 17 | */ 18 | void listen(final IRateLimitRejectListenerContext context); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /rate-limit-api/src/main/java/com/github/houbb/rate/limit/api/support/IRateLimitMethodService.java: -------------------------------------------------------------------------------- 1 | package com.github.houbb.rate.limit.api.support; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | /** 6 | * @author binbin.hou 7 | * @since 1.0.0 8 | */ 9 | public interface IRateLimitMethodService { 10 | 11 | /** 12 | * 根据入参构建对应的 key 13 | * @param method 方法 14 | * @param params 入参 15 | * @return 结果 16 | * @since 0.0.1 17 | */ 18 | String getMethodId(final Method method, final Object[] params); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /rate-limit-test2/src/main/java/com/github/houbb/rate/limit/test2/RateLimitApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.houbb.rate.limit.test2; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author binbin.hou 8 | * @since 0.0.10 9 | */ 10 | @SpringBootApplication 11 | public class RateLimitApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(RateLimitApplication.class, args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /rate-limit-core/src/main/java/com/github/houbb/rate/limit/core/support/reject/RateLimitRejectListener.java: -------------------------------------------------------------------------------- 1 | package com.github.houbb.rate.limit.core.support.reject; 2 | 3 | import com.github.houbb.rate.limit.api.support.IRateLimitRejectListener; 4 | import com.github.houbb.rate.limit.api.support.IRateLimitRejectListenerContext; 5 | 6 | /** 7 | * @author binbin.hou 8 | * @since 1.0.0 9 | */ 10 | public class RateLimitRejectListener implements IRateLimitRejectListener { 11 | 12 | @Override 13 | public void listen(IRateLimitRejectListenerContext context) { 14 | 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /rate-limit-test/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 |
服务实现
15 | * 16 | *Created: 2018/8/5 下午10:5317 | *
Project: rate-tryAcquire18 | * 19 | * @author houbinbin 20 | * @version 0.0.1 21 | * @since 0.0.1 22 | */ 23 | @Service 24 | public class UserService { 25 | 26 | private static final Log log = LogFactory.getLog(UserService.class); 27 | 28 | @RateLimit(interval = 2, count = 5) 29 | public void limitCount() { 30 | log.info("{}", Thread.currentThread().getName()); 31 | } 32 | 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /rate-limit-test/src/main/java/com/github/houbb/rate/limit/test/core/service/ClassUserService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018. houbinbin Inc. 3 | * rate-tryAcquire All rights reserved. 4 | */ 5 | 6 | package com.github.houbb.rate.limit.test.core.service; 7 | 8 | import com.github.houbb.log.integration.core.Log; 9 | import com.github.houbb.log.integration.core.LogFactory; 10 | import com.github.houbb.rate.limit.core.annotation.RateLimit; 11 | import org.springframework.stereotype.Service; 12 | 13 | /** 14 | *
服务实现
15 | * 16 | *Created: 2018/8/5 下午10:5317 | *
Project: rate-tryAcquire18 | * 19 | * @author houbinbin 20 | * @version 0.0.1 21 | * @since 0.0.1 22 | */ 23 | @Service 24 | @RateLimit(interval = 2, count = 5) 25 | public class ClassUserService { 26 | 27 | private static final Log log = LogFactory.getLog(ClassUserService.class); 28 | 29 | public void limitCount() { 30 | log.info("{}", Thread.currentThread().getName()); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /rate-limit-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 |
服务实现
16 | * 17 | *Created: 2018/8/5 下午10:5318 | *
Project: rate-tryAcquire19 | * 20 | * @author houbinbin 21 | * @version 0.0.1 22 | * @since 0.0.1 23 | */ 24 | @Service 25 | public class UserService { 26 | 27 | private static final Log log = LogFactory.getLog(UserService.class); 28 | 29 | @RateLimit(interval = 2, count = 5) 30 | public void limitCount() { 31 | log.info("{}", Thread.currentThread().getName()); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /rate-limit-test/src/main/java/com/github/houbb/rate/limit/test/core/service/RepeatUserService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018. houbinbin Inc. 3 | * rate-tryAcquire All rights reserved. 4 | */ 5 | 6 | package com.github.houbb.rate.limit.test.core.service; 7 | 8 | import com.github.houbb.log.integration.core.Log; 9 | import com.github.houbb.log.integration.core.LogFactory; 10 | import com.github.houbb.rate.limit.core.annotation.RateLimit; 11 | import com.github.houbb.rate.limit.core.annotation.RateLimits; 12 | import org.springframework.stereotype.Service; 13 | 14 | /** 15 | *
服务实现
16 | * 17 | *Created: 2018/8/5 下午10:5318 | *
Project: rate-tryAcquire19 | * 20 | * @author houbinbin 21 | * @version 0.0.1 22 | * @since 0.0.1 23 | */ 24 | @Service 25 | public class RepeatUserService { 26 | 27 | private static final Log log = LogFactory.getLog(RepeatUserService.class); 28 | 29 | @RateLimits({@RateLimit(interval = 2, count = 5)}) 30 | public void limitCount() { 31 | log.info("{}", Thread.currentThread().getName()); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /rate-limit-test/src/main/java/com/github/houbb/rate/limit/test/core/service/RepeatClassUserService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018. houbinbin Inc. 3 | * rate-tryAcquire All rights reserved. 4 | */ 5 | 6 | package com.github.houbb.rate.limit.test.core.service; 7 | 8 | import com.github.houbb.log.integration.core.Log; 9 | import com.github.houbb.log.integration.core.LogFactory; 10 | import com.github.houbb.rate.limit.core.annotation.RateLimit; 11 | import com.github.houbb.rate.limit.core.annotation.RateLimits; 12 | import org.springframework.stereotype.Service; 13 | 14 | /** 15 | *
服务实现
16 | * 17 | *Created: 2018/8/5 下午10:5318 | *
Project: rate-tryAcquire19 | * 20 | * @author houbinbin 21 | * @version 0.0.1 22 | * @since 0.0.1 23 | */ 24 | @Service 25 | @RateLimits({@RateLimit(interval = 2, count = 5)}) 26 | public class RepeatClassUserService { 27 | 28 | private static final Log log = LogFactory.getLog(RepeatClassUserService.class); 29 | 30 | public void limitCount() { 31 | log.info("{}", Thread.currentThread().getName()); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /rate-limit-spring/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 |
运行时异常
12 | * 13 | *Created: 2018/8/5 下午10:2814 | *
Project: rate-tryAcquire15 | * 16 | * @author houbinbin 17 | * @version 0.0.1 18 | * @since 0.0.1 19 | */ 20 | @API(status = API.Status.INTERNAL) 21 | public class RateLimitRuntimeException extends RuntimeException { 22 | 23 | private static final long serialVersionUID = -7828188205076249256L; 24 | 25 | public RateLimitRuntimeException() { 26 | } 27 | 28 | public RateLimitRuntimeException(String message) { 29 | super(message); 30 | } 31 | 32 | public RateLimitRuntimeException(String message, Throwable cause) { 33 | super(message, cause); 34 | } 35 | 36 | public RateLimitRuntimeException(Throwable cause) { 37 | super(cause); 38 | } 39 | 40 | public RateLimitRuntimeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 41 | super(message, cause, enableSuppression, writableStackTrace); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /rate-limit-test/src/test/java/com/github/houbb/rate/limit/test/core/RateLimitCoreTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018. houbinbin Inc. 3 | * rate-tryAcquire All rights reserved. 4 | */ 5 | 6 | package com.github.houbb.rate.limit.test.core; 7 | 8 | 9 | import com.github.houbb.rate.limit.core.exception.RateLimitRuntimeException; 10 | import com.github.houbb.rate.limit.core.support.proxy.RateLimitProxy; 11 | import com.github.houbb.rate.limit.test.core.service.UserService; 12 | import org.junit.Test; 13 | 14 | import java.util.concurrent.TimeUnit; 15 | 16 | /** 17 | *
18 | * 19 | *
Created: 2018/8/1 上午9:5320 | *
Project: spring-framework-learn21 | * 22 | * @author houbinbin 23 | * @version 0.0.1 24 | * @since 0.0.1 25 | */ 26 | public class RateLimitCoreTest { 27 | 28 | @Test 29 | public void limitCountTest() throws InterruptedException { 30 | UserService userService = RateLimitProxy.getProxy(new UserService()); 31 | 32 | for(int i = 0; i < 4; i++) { 33 | TimeUnit.SECONDS.sleep(1); 34 | userService.limitCount(); 35 | } 36 | } 37 | 38 | @Test(expected = RateLimitRuntimeException.class) 39 | public void limitCountErrorTest() { 40 | UserService userService = RateLimitProxy.getProxy(new UserService()); 41 | for(int i = 0; i < 3; i++) { 42 | userService.limitCount(); 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /release_rm.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo "============================= RELEASE START..." 3 | 4 | ## 版本号信息(需要手动指定) 5 | oldVersion="1.0.0" 6 | newVersion="1.0.0" 7 | projectName="${artifactId}" 8 | 9 | # 删除分支 10 | oldBranchName="release_"${oldVersion} 11 | git branch -d ${oldBranchName} 12 | git push origin --delete ${oldBranchName} 13 | 14 | echo "1. Branch remove success..." 15 | 16 | # 拉取新的分支 17 | newBranchName="release_"${newVersion} 18 | git branch ${newBranchName} 19 | git checkout ${newBranchName} 20 | git push --set-upstream origin ${newBranchName} 21 | 22 | echo "2. NEW BRANCH DONE." 23 | 24 | # 修改新分支的版本号 25 | ## snapshot 版本号 26 | snapshot_new_version=${newVersion}"-SNAPSHOT" 27 | mvn versions:set -DgroupId=com.github.houbb -DartifactId=${projectName} -DoldVersion=${release_version} -DnewVersion=${snapshot_new_version} 28 | mvn -N versions:update-child-modules 29 | mvn versions:commit 30 | 31 | git add . 32 | git commit -m "modify branch ${release_version} TO ${snapshot_new_version}" 33 | git push 34 | git status 35 | echo "3. MODIFY ${release_version} TO ${snapshot_new_version} DONE." 36 | 37 | echo "============================= BRANCH RE-CREATE END..." 38 | 39 | echo "============================= BRANCH LIST =============================" 40 | git branch -a 41 | 42 | # 使用方式: 43 | # 注意:本脚本用于删除分支,谨慎使用! 44 | # 1. 赋值权限: chmod +x ./release_rm.sh 45 | # 2. 执行: ./release_rm.sh 46 | # Last Update Time: 2018-06-21 11:10:42 47 | # Author: houbb -------------------------------------------------------------------------------- /rate-limit-core/src/main/java/com/github/houbb/rate/limit/core/annotation/RateLimit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018. houbinbin Inc. 3 | * rate-tryAcquire All rights reserved. 4 | */ 5 | 6 | package com.github.houbb.rate.limit.core.annotation; 7 | 8 | 9 | import org.apiguardian.api.API; 10 | 11 | import java.lang.annotation.*; 12 | import java.util.concurrent.TimeUnit; 13 | 14 | /** 15 | * 限制调用 16 | * Created by bbhou on 2017/9/20. 17 | * @author binbin.hou 18 | * @since 0.0.3 19 | */ 20 | @Documented 21 | @Retention(RetentionPolicy.RUNTIME) 22 | @Target({ElementType.METHOD, ElementType.TYPE}) 23 | @Inherited 24 | @API(status = API.Status.MAINTAINED) 25 | public @interface RateLimit { 26 | 27 | /** 28 | * 每一次方法请求消耗的令牌数 29 | * @return 令牌数 30 | * @since 1.0.0 31 | */ 32 | int value() default 1; 33 | 34 | /** 35 | * 时间单位, 默认为秒 36 | * @see TimeUnit 时间单位 37 | * @return 时间单位 38 | * @since 0.0.1 39 | */ 40 | TimeUnit timeUnit() default TimeUnit.SECONDS; 41 | 42 | /** 43 | * 时间间隔 44 | * (1) 需要填入正整数。 45 | * @return 时间间隔 46 | * @since 0.0.1 47 | */ 48 | long interval() default 60; 49 | 50 | /** 51 | * 调用次数。 52 | * (1) 需要填入正整数。 53 | * @return 调用次数 54 | * @since 0.0.1 55 | */ 56 | long count() default 1000; 57 | 58 | /** 59 | * 是否启用 60 | * @return 结果 61 | * @since 1.1.0 62 | */ 63 | boolean enable() default true; 64 | 65 | } 66 | -------------------------------------------------------------------------------- /rate-limit-core/src/main/java/com/github/houbb/rate/limit/core/core/RateLimits.java: -------------------------------------------------------------------------------- 1 | package com.github.houbb.rate.limit.core.core; 2 | 3 | import com.github.houbb.rate.limit.api.core.IRateLimit; 4 | 5 | /** 6 | * @author binbin.hou 7 | * @since 1.0.0 8 | */ 9 | public final class RateLimits { 10 | 11 | private RateLimits(){} 12 | 13 | /** 14 | * 固定窗口 15 | * @return 策略 16 | */ 17 | public static IRateLimit fixedWindow() { 18 | return new RateLimitFixedWindow(); 19 | } 20 | 21 | /** 22 | * 滑动窗口 23 | * @return 策略 24 | */ 25 | public static IRateLimit slideWindow() { 26 | return new RateLimitSlideWindow(); 27 | } 28 | 29 | /** 30 | * 滑动窗口 31 | * @param windowNum 窗口数量 32 | * @return 策略 33 | */ 34 | public static IRateLimit slideWindow(int windowNum) { 35 | return new RateLimitSlideWindow(windowNum); 36 | } 37 | 38 | /** 39 | * 滑动窗口队列实现 40 | * @return 策略 41 | */ 42 | public static IRateLimit slideWindowQueue() { 43 | return new RateLimitSlideWindowQueue(); 44 | } 45 | 46 | /** 47 | * 漏桶算法 48 | * @return 策略 49 | */ 50 | public static IRateLimit leakyBucket() { 51 | return new RateLimitLeakyBucket(); 52 | } 53 | 54 | /** 55 | * 令牌桶算法 56 | * @return 策略 57 | */ 58 | public static IRateLimit tokenBucket() { 59 | return new RateLimitTokenBucket(); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /rate-limit-core/src/main/java/com/github/houbb/rate/limit/core/support/token/RateLimitTokenService.java: -------------------------------------------------------------------------------- 1 | package com.github.houbb.rate.limit.core.support.token; 2 | 3 | import com.github.houbb.heaven.util.lang.StringUtil; 4 | import com.github.houbb.heaven.util.util.ArrayUtil; 5 | import com.github.houbb.log.integration.core.Log; 6 | import com.github.houbb.log.integration.core.LogFactory; 7 | import com.github.houbb.rate.limit.api.support.IRateLimitTokenService; 8 | import com.github.houbb.web.core.util.HttpServletRequestUtil; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | 12 | /** 13 | * 默认基于 ip 获取对应的地址 14 | * 15 | * @author binbin.hou 16 | * @since 1.0.0 17 | */ 18 | public class RateLimitTokenService implements IRateLimitTokenService { 19 | 20 | /** 21 | * 日志信息 22 | * @since 0.0.1 23 | */ 24 | private static final Log LOG = LogFactory.getLog(RateLimitTokenService.class); 25 | 26 | @Override 27 | public String getTokenId(Object[] params) { 28 | if(ArrayUtil.isEmpty(params)) { 29 | LOG.warn("Param is empty, return empty"); 30 | return StringUtil.EMPTY; 31 | } 32 | 33 | for(Object param : params) { 34 | if(param instanceof HttpServletRequest) { 35 | HttpServletRequest request = (HttpServletRequest) param; 36 | return HttpServletRequestUtil.getIp(request); 37 | } 38 | } 39 | LOG.warn("Param is not found in request, return empty"); 40 | return StringUtil.EMPTY; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /rate-limit-core/src/main/java/com/github/houbb/rate/limit/core/support/proxy/cglib/CglibProxy.java: -------------------------------------------------------------------------------- 1 | package com.github.houbb.rate.limit.core.support.proxy.cglib; 2 | 3 | import com.github.houbb.rate.limit.core.bs.RateLimitBs; 4 | import com.github.houbb.rate.limit.core.support.proxy.AbstractProxy; 5 | import net.sf.cglib.proxy.Enhancer; 6 | import net.sf.cglib.proxy.MethodInterceptor; 7 | import net.sf.cglib.proxy.MethodProxy; 8 | 9 | import java.lang.reflect.Method; 10 | 11 | /** 12 | * CGLIB 代理类 13 | * @author binbin.hou 14 | * date 2019/3/7 15 | * @since 0.0.2 16 | */ 17 | public class CglibProxy extends AbstractProxy implements MethodInterceptor { 18 | 19 | /** 20 | * 被代理的对象 21 | */ 22 | private final Object target; 23 | 24 | public CglibProxy(Object target) { 25 | this.target = target; 26 | } 27 | 28 | public CglibProxy(Object target, RateLimitBs bs) { 29 | super(bs); 30 | this.target = target; 31 | } 32 | 33 | @Override 34 | public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 35 | //1. 添加判断 36 | super.rateLimitBs.tryAcquire(method, objects); 37 | 38 | //2. 返回结果 39 | return method.invoke(target, objects); 40 | } 41 | 42 | @Override 43 | public Object proxy() { 44 | Enhancer enhancer = new Enhancer(); 45 | //目标对象类 46 | enhancer.setSuperclass(target.getClass()); 47 | enhancer.setCallback(this); 48 | //通过字节码技术创建目标对象类的子类实例作为代理 49 | return enhancer.create(); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /rate-limit-test/src/test/java/com/github/houbb/rate/limit/test/bs/RateLimitBsTest.java: -------------------------------------------------------------------------------- 1 | package com.github.houbb.rate.limit.test.bs; 2 | 3 | import com.github.houbb.common.cache.core.service.CommonCacheServiceMap; 4 | import com.github.houbb.rate.limit.core.annotation.RateLimit; 5 | import com.github.houbb.rate.limit.core.bs.RateLimitBs; 6 | import com.github.houbb.rate.limit.core.constant.RateLimitConst; 7 | import com.github.houbb.rate.limit.core.core.RateLimits; 8 | import com.github.houbb.rate.limit.core.support.config.RateLimitConfigService; 9 | import com.github.houbb.rate.limit.core.support.method.RateLimitMethodService; 10 | import com.github.houbb.rate.limit.core.support.reject.RateLimitRejectListenerException; 11 | import com.github.houbb.rate.limit.core.support.token.RateLimitTokenService; 12 | import com.github.houbb.timer.core.util.Timers; 13 | import org.junit.Test; 14 | 15 | /** 16 | * @author binbin.hou 17 | * @since 1.0.0 18 | */ 19 | public class RateLimitBsTest { 20 | 21 | @Test 22 | public void defaultTest() { 23 | RateLimitBs.newInstance() 24 | .timer(Timers.system()) 25 | .methodService(new RateLimitMethodService()) 26 | .tokenService(new RateLimitTokenService()) 27 | .rejectListener(new RateLimitRejectListenerException()) 28 | .configService(new RateLimitConfigService()) 29 | .cacheService(new CommonCacheServiceMap()) 30 | .rateLimit(RateLimits.tokenBucket()) 31 | .cacheKeyNamespace(RateLimitConst.DEFAULT_CACHE_KEY_NAMESPACE); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /rate-limit-api/src/main/java/com/github/houbb/rate/limit/api/core/IRateLimitContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018. houbinbin Inc. 3 | * rate-tryAcquire All rights reserved. 4 | */ 5 | 6 | package com.github.houbb.rate.limit.api.core; 7 | 8 | import com.github.houbb.common.cache.api.service.ICommonCacheService; 9 | import com.github.houbb.rate.limit.api.support.*; 10 | import com.github.houbb.timer.api.ITimer; 11 | 12 | import java.lang.reflect.Method; 13 | 14 | /** 15 | * 16 | * 限流核心上下文接口 17 | * @author bbhou 18 | * @since 1.0.0 19 | */ 20 | public interface IRateLimitContext { 21 | 22 | /** 23 | * 时间戳 24 | * @return 时间戳 25 | */ 26 | ITimer timer(); 27 | 28 | /** 29 | * 配置服务类 30 | * @return 服务类 31 | * @since 1.0.0 32 | */ 33 | IRateLimitConfigService configService(); 34 | 35 | /** 36 | * 方法服务类 37 | * @return 服务类 38 | * @since 1.0.0 39 | */ 40 | IRateLimitMethodService methodService(); 41 | 42 | /** 43 | * 标识服务 44 | * @return 服务 45 | * @since 1.0.0 46 | */ 47 | IRateLimitTokenService tokenService(); 48 | 49 | /** 50 | * 缓存服务 51 | * @return 统计服务 52 | */ 53 | ICommonCacheService cacheService(); 54 | 55 | /** 56 | * 拒绝时的监听策略 57 | * @return 策略 58 | * @since 1.0.0 59 | */ 60 | IRateLimitRejectListener rejectListener(); 61 | 62 | /** 63 | * 访问的方法 64 | * @return 方法 65 | */ 66 | Method method(); 67 | 68 | /** 69 | * 访问的方法参数 70 | * @return 方法参数 71 | */ 72 | Object[] args(); 73 | 74 | /** 75 | * 对应的缓存 key 命名空间 76 | * @return 结果 77 | * @since 1.1.0 78 | */ 79 | String cacheKeyNamespace(); 80 | 81 | } 82 | -------------------------------------------------------------------------------- /rate-limit-spring/src/main/java/com/github/houbb/rate/limit/spring/annotation/EnableRateLimit.java: -------------------------------------------------------------------------------- 1 | package com.github.houbb.rate.limit.spring.annotation; 2 | 3 | import com.github.houbb.rate.limit.core.constant.RateLimitConst; 4 | import com.github.houbb.rate.limit.spring.config.RateLimitConfig; 5 | import org.springframework.context.annotation.EnableAspectJAutoProxy; 6 | import org.springframework.context.annotation.Import; 7 | 8 | import java.lang.annotation.*; 9 | 10 | /** 11 | * 启用自动限制注解 12 | * @author binbin.hou 13 | * @since 0.0.3 14 | */ 15 | @Target(ElementType.TYPE) 16 | @Retention(RetentionPolicy.RUNTIME) 17 | @Documented 18 | @Import(RateLimitConfig.class) 19 | @EnableAspectJAutoProxy 20 | public @interface EnableRateLimit { 21 | 22 | /** 23 | * 限流策略 24 | * @return 限流策略 25 | */ 26 | String value() default "rateLimit"; 27 | 28 | /** 29 | * 时间策略 30 | * @return 时间策略 31 | */ 32 | String timer() default "rateLimitTimer"; 33 | 34 | /** 35 | * 缓存策略 36 | * @return 缓存策略 37 | */ 38 | String cacheService() default "rateLimitCacheService"; 39 | 40 | /** 41 | * 配置策略 42 | * @return 配置策略 43 | */ 44 | String configService() default "rateLimitConfigService"; 45 | 46 | /** 47 | * 标识服务类 48 | * @return 标识 49 | */ 50 | String tokenService() default "rateLimitTokenService"; 51 | 52 | /** 53 | * 方法服务类 54 | * @return 服务类 55 | */ 56 | String methodService() default "rateLimitMethodService"; 57 | 58 | /** 59 | * 拒绝策略 60 | * @return 策略 61 | */ 62 | String rejectListener() default "rateLimitRejectListener"; 63 | 64 | /** 65 | * 缓存的命名空间 66 | * @since 1.1.0 67 | * @return 结果 68 | */ 69 | String cacheKeyNamespace() default RateLimitConst.DEFAULT_CACHE_KEY_NAMESPACE; 70 | 71 | } 72 | -------------------------------------------------------------------------------- /rate-limit-test/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 |
16 | * 每一秒发放多少。 17 | * 18 | * @since 0.0.6 19 | */ 20 | private long rate; 21 | 22 | /** 23 | * 容量 24 | *
25 | * 后期暴露为可以配置 26 | * 27 | * @since 0.0.6 28 | */ 29 | private long capacity; 30 | 31 | /** 32 | * 水量 33 | * 34 | * @since 0.0.6 35 | */ 36 | private volatile long water; 37 | 38 | /** 39 | * 上一次的更新时间 40 | * 41 | * @since 0.0.6 42 | */ 43 | private volatile long lastUpdateTime; 44 | 45 | public long getRate() { 46 | return rate; 47 | } 48 | 49 | public void setRate(long rate) { 50 | this.rate = rate; 51 | } 52 | 53 | public long getCapacity() { 54 | return capacity; 55 | } 56 | 57 | public void setCapacity(long capacity) { 58 | this.capacity = capacity; 59 | } 60 | 61 | public long getWater() { 62 | return water; 63 | } 64 | 65 | public void setWater(long water) { 66 | this.water = water; 67 | } 68 | 69 | public long getLastUpdateTime() { 70 | return lastUpdateTime; 71 | } 72 | 73 | public void setLastUpdateTime(long lastUpdateTime) { 74 | this.lastUpdateTime = lastUpdateTime; 75 | } 76 | 77 | @Override 78 | public String toString() { 79 | return "RateLimitLeakyBucketDto{" + 80 | "rate=" + rate + 81 | ", capacity=" + capacity + 82 | ", water=" + water + 83 | ", lastUpdateTime=" + lastUpdateTime + 84 | '}'; 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /rate-limit-core/src/main/java/com/github/houbb/rate/limit/core/dto/RateLimitTokenBucketDto.java: -------------------------------------------------------------------------------- 1 | package com.github.houbb.rate.limit.core.dto; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * @author binbin.hou 7 | * @since 1.0.0 8 | */ 9 | public class RateLimitTokenBucketDto implements Serializable { 10 | 11 | /** 12 | * 令牌的发放速率 13 | *
14 | * 每一秒发放多少。 15 | * 16 | * @since 0.0.6 17 | */ 18 | private long rate; 19 | 20 | /** 21 | * 容量 22 | *
23 | * 后期暴露为可以配置
24 | *
25 | * @since 0.0.6
26 | */
27 | private long capacity;
28 |
29 | /**
30 | * 令牌数量
31 | *
32 | * @since 0.0.6
33 | */
34 | private volatile long tokenNum;
35 |
36 | /**
37 | * 上一次的更新时间
38 | *
39 | * @since 0.0.6
40 | */
41 | private volatile long lastUpdateTime;
42 |
43 | public long getRate() {
44 | return rate;
45 | }
46 |
47 | public void setRate(long rate) {
48 | this.rate = rate;
49 | }
50 |
51 | public long getCapacity() {
52 | return capacity;
53 | }
54 |
55 | public void setCapacity(long capacity) {
56 | this.capacity = capacity;
57 | }
58 |
59 | public long getTokenNum() {
60 | return tokenNum;
61 | }
62 |
63 | public void setTokenNum(long tokenNum) {
64 | this.tokenNum = tokenNum;
65 | }
66 |
67 | public long getLastUpdateTime() {
68 | return lastUpdateTime;
69 | }
70 |
71 | public void setLastUpdateTime(long lastUpdateTime) {
72 | this.lastUpdateTime = lastUpdateTime;
73 | }
74 |
75 | @Override
76 | public String toString() {
77 | return "RateLimitBucketDto{" +
78 | "rate=" + rate +
79 | ", capacity=" + capacity +
80 | ", tokenNum=" + tokenNum +
81 | ", lastUpdateTime=" + lastUpdateTime +
82 | '}';
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/doc/user/02-spring.md:
--------------------------------------------------------------------------------
1 | # spring 整合
2 |
3 | ## maven 导入
4 |
5 | ```xml
6 |
代理信息
18 | * 19 | *Created: 2019/3/8 10:38 AM20 | *
Project: async21 | * 22 | * @author houbinbin 23 | * @since 0.0.1 24 | */ 25 | public final class RateLimitProxy { 26 | 27 | private RateLimitProxy(){} 28 | 29 | /** 30 | * 获取对象代理 31 | * @param
动态代理
18 | * 19 | * 1. 对于 executor 的抽象,使用 {@link CompletionService} 20 | * 2. 确保唯一初始化 executor,在任务执行的最后关闭 executor。 21 | * 3. 异步执行结果的获取,异常信息的获取。 22 | *Created: 2019/3/5 10:23 PM23 | *
Project: async24 | * 25 | * @author houbinbin 26 | * @since 0.0.1 27 | */ 28 | public class DynamicProxy extends AbstractProxy implements InvocationHandler { 29 | 30 | /** 31 | * 被代理的对象 32 | */ 33 | private final Object target; 34 | 35 | public DynamicProxy(Object target) { 36 | this.target = target; 37 | } 38 | 39 | public DynamicProxy(Object target, RateLimitBs bs) { 40 | super(bs); 41 | this.target = target; 42 | } 43 | 44 | /** 45 | * 这种方式虽然实现了异步执行,但是存在一个缺陷: 46 | * 强制用户返回值为 Future 的子类。 47 | * 48 | * 如何实现不影响原来的值,要怎么实现呢? 49 | * @param proxy 原始对象 50 | * @param method 方法 51 | * @param args 入参 52 | * @return 结果 53 | * @throws Throwable 异常 54 | */ 55 | @Override 56 | @SuppressWarnings("all") 57 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 58 | //1. 添加判断 59 | super.rateLimitBs.tryAcquire(method, args); 60 | 61 | //2. 返回以前的结果 62 | return method.invoke(target, args); 63 | } 64 | 65 | @Override 66 | public Object proxy() { 67 | // 我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的 68 | InvocationHandler handler = new DynamicProxy(target); 69 | 70 | return Proxy.newProxyInstance(handler.getClass().getClassLoader(), 71 | target.getClass().getInterfaces(), handler); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /rate-limit-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 |
切面实现
23 | * 24 | *Created: 2018/8/5 下午9:3725 | *
Project: rate-tryAcquire26 | * 27 | * @author houbinbin 28 | * @version 0.0.1 29 | * @since 0.0.1 30 | */ 31 | @Aspect 32 | @Component 33 | @API(status = API.Status.MAINTAINED) 34 | public class RateLimitAspect { 35 | 36 | @Autowired 37 | private RateLimitBs rateLimitBs; 38 | 39 | /** 40 | * 指定注解的方法 41 | */ 42 | @Pointcut("@annotation(com.github.houbb.rate.limit.core.annotation.RateLimit) || @annotation(com.github.houbb.rate.limit.core.annotation.RateLimits)") 43 | public void methodMyPointcut() { 44 | } 45 | 46 | /** 47 | * 指定注解的类 48 | */ 49 | @Pointcut("@within(com.github.houbb.rate.limit.core.annotation.RateLimit) || @within(com.github.houbb.rate.limit.core.annotation.RateLimits)") 50 | public void classMyPointcut() { 51 | } 52 | 53 | /** 54 | * https://www.cnblogs.com/bjlhx/p/12081300.html 声明方式 55 | * @param point 切面 56 | * @return 结果 57 | * @throws Throwable 异常 58 | */ 59 | @Around("methodMyPointcut() || classMyPointcut()") 60 | public Object around(ProceedingJoinPoint point) throws Throwable { 61 | Method method = SpringAopUtil.getCurrentMethod(point); 62 | // 执行代理操作 63 | Object[] args = point.getArgs(); 64 | 65 | // 核心处理方法 66 | rateLimitBs.tryAcquire(method, args); 67 | 68 | return point.proceed(); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /rate-limit-core/src/main/java/com/github/houbb/rate/limit/core/core/RateLimitFixedWindow.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018. houbinbin Inc. 3 | * rate-tryAcquire All rights reserved. 4 | */ 5 | 6 | package com.github.houbb.rate.limit.core.core; 7 | 8 | import com.github.houbb.common.cache.api.service.ICommonCacheService; 9 | import com.github.houbb.heaven.util.lang.StringUtil; 10 | import com.github.houbb.log.integration.core.Log; 11 | import com.github.houbb.log.integration.core.LogFactory; 12 | import com.github.houbb.rate.limit.api.core.IRateLimitContext; 13 | import com.github.houbb.rate.limit.api.dto.RateLimitConfigDto; 14 | import org.apiguardian.api.API; 15 | 16 | /** 17 | * 固定时间窗口 18 | * 19 | * @author houbinbin 20 | * Created by bbhou on 2017/9/20. 21 | * @since 0.0.5 22 | */ 23 | @API(status = API.Status.EXPERIMENTAL) 24 | public class RateLimitFixedWindow extends AbstractRateLimit { 25 | 26 | /** 27 | * 日志 28 | * @since 0.0.5 29 | */ 30 | private static final Log LOG = LogFactory.getLog(RateLimitFixedWindow.class); 31 | 32 | /** 33 | * 固定窗口的实现方式比较简单,直接设置过期时间即可。 34 | * 35 | * @param cacheKey 缓存标识 36 | * @param configDto 配置 37 | * @param rateLimitContext 上下文 38 | * @return 结果 39 | */ 40 | @Override 41 | protected boolean doAcquire(String cacheKey, RateLimitConfigDto configDto, IRateLimitContext rateLimitContext) { 42 | final ICommonCacheService cacheService = rateLimitContext.cacheService(); 43 | final int permits = configDto.getPermits(); 44 | 45 | String cacheValue = cacheService.get(cacheKey); 46 | if(StringUtil.isEmpty(cacheKey)) { 47 | final long expireMills = configDto.getTimeUnit().toMillis(configDto.getInterval()); 48 | LOG.info("cacheKey: {} 对应的历史配置为空,进行初始化"); 49 | // 模式初始化为0次 50 | cacheValue = "0"; 51 | cacheService.set(cacheKey, cacheValue, expireMills); 52 | } 53 | 54 | long cacheCount = Long.parseLong(cacheValue); 55 | 56 | long newCount = cacheCount + permits; 57 | final long configCount = configDto.getCount(); 58 | if(newCount > configCount) { 59 | LOG.warn("newCount {} 大于配置的 {}", newCount, configCount); 60 | return false; 61 | } else { 62 | long ttlMills = cacheService.ttl(cacheKey); 63 | if(ttlMills > 0) { 64 | // 直接 set 一个值,redis 会将其有效期设置为永远。 65 | cacheService.set(cacheKey, cacheValue, ttlMills); 66 | } 67 | 68 | return true; 69 | } 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /doc/项目原型.md: -------------------------------------------------------------------------------- 1 | # 原型创建 2 | 3 | - create 4 | 5 | ``` 6 | $ mvn archetype:create-from-project 7 | ``` 8 | 9 | - config 10 | 11 | ``` 12 | ~/target/generated-sources/archetype/src/main/resources/META-INF/maven/archetype-metadata.xml 13 | ``` 14 | 15 | [archetype-descriptor](http://maven.apache.org/archetype/archetype-models/archetype-descriptor/archetype-descriptor.html) 16 | 17 | # 文件内容 18 | 19 | `~/maven-archetype/target/generated-sources/archetype/src/main/resources/META-INF/maven/archetype-metadata.xml` 20 | 21 | 22 | ```xml 23 | 24 |
25 | * 1. 限制 queue 的大小与 count 一致 26 | * 2. 队首和队尾时间对比 27 | *
28 | * 这个和最正宗的滑动窗口有些区别。
29 | *
30 | * @author houbinbin
31 | * Created by bbhou on 2017/9/20.
32 | * @since 0.0.5
33 | */
34 | @API(status = API.Status.EXPERIMENTAL)
35 | public class RateLimitSlideWindowQueue extends AbstractRateLimit {
36 |
37 | private static final Log LOG = LogFactory.getLog(RateLimitSlideWindowQueue.class);
38 |
39 | @Override
40 | protected boolean doAcquire(String cacheKey, RateLimitConfigDto configDto, IRateLimitContext context) {
41 | // 队列?
42 | Queue project: rate-tryAcquire-RateLimitContext create on 2020/6/20 21:35 project: rate-tryAcquire-RateLimitBs create on 2020/6/20 21:38 Created: 2018/8/1 上午9:53
28 | * Project: spring-framework-learn
29 | *
30 | * @author houbinbin
31 | * @version 0.0.1
32 | * @since 0.0.1
33 | */
34 | @ContextConfiguration(classes = SpringConfig.class)
35 | @RunWith(SpringJUnit4ClassRunner.class)
36 | @Ignore
37 | public class SpringConfigTest {
38 |
39 | @Autowired
40 | private UserService userService;
41 |
42 | @Autowired
43 | private ClassUserService classUserService;
44 |
45 | @Autowired
46 | private RepeatClassUserService repeatClassUserService;
47 |
48 | @Autowired
49 | private RepeatUserService repeatUserService;
50 |
51 |
52 | @Test(expected = RateLimitRuntimeException.class)
53 | public void repeatTest() {
54 | for(int i = 0; i < 3; i++) {
55 | repeatUserService.limitCount();
56 | }
57 | }
58 |
59 | @Test
60 | public void repeatPassTest() throws InterruptedException {
61 | for(int i = 0; i < 3; i++) {
62 | TimeUnit.SECONDS.sleep(1);
63 | repeatUserService.limitCount();
64 | }
65 | }
66 |
67 | @Test(expected = RateLimitRuntimeException.class)
68 | public void repeatClassTest() {
69 | for(int i = 0; i < 3; i++) {
70 | repeatClassUserService.limitCount();
71 | }
72 | }
73 |
74 | @Test
75 | public void repeatClassPassTest() throws InterruptedException {
76 | for(int i = 0; i < 3; i++) {
77 | TimeUnit.SECONDS.sleep(1);
78 | repeatClassUserService.limitCount();
79 | }
80 | }
81 |
82 | @Test(expected = RateLimitRuntimeException.class)
83 | public void limitCountErrorTest() {
84 | for(int i = 0; i < 3; i++) {
85 | userService.limitCount();
86 | }
87 | }
88 |
89 | @Test
90 | public void limitCountPassTest() throws InterruptedException {
91 | for(int i = 0; i < 3; i++) {
92 | TimeUnit.SECONDS.sleep(1);
93 | userService.limitCount();
94 | }
95 | }
96 |
97 | /**
98 | * @since 1.1.0
99 | */
100 | @Test(expected = RateLimitRuntimeException.class)
101 | public void limitCountErrorTest2() {
102 | for(int i = 0; i < 3; i++) {
103 | classUserService.limitCount();
104 | }
105 | }
106 |
107 | @Test
108 | public void limitCountClassPassTest() throws InterruptedException {
109 | for(int i = 0; i < 3; i++) {
110 | TimeUnit.SECONDS.sleep(1);
111 | classUserService.limitCount();
112 | }
113 | }
114 |
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/rate-limit-core/src/main/java/com/github/houbb/rate/limit/core/support/config/RateLimitConfigService.java:
--------------------------------------------------------------------------------
1 | package com.github.houbb.rate.limit.core.support.config;
2 |
3 | import com.github.houbb.heaven.util.util.ArrayUtil;
4 | import com.github.houbb.heaven.util.util.CollectionUtil;
5 | import com.github.houbb.rate.limit.api.dto.RateLimitConfigDto;
6 | import com.github.houbb.rate.limit.api.support.IRateLimitConfigService;
7 | import com.github.houbb.rate.limit.core.annotation.RateLimit;
8 | import com.github.houbb.rate.limit.core.annotation.RateLimits;
9 |
10 | import java.lang.reflect.Method;
11 | import java.util.ArrayList;
12 | import java.util.Collections;
13 | import java.util.List;
14 |
15 | /**
16 | * @author binbin.hou
17 | * @since 1.0.0
18 | */
19 | public class RateLimitConfigService implements IRateLimitConfigService {
20 |
21 | @Override
22 | public List