# confine **Repository Path**: itCjb/confine ## Basic Information - **Project Name**: confine - **Description**: 轻量限流控制组件-confine - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 15 - **Forks**: 1 - **Created**: 2021-03-18 - **Last Updated**: 2021-03-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 轻量限流控制组件-confine ## confine-client使用教程 confine-client组件纯api手动进行限流操作,使用前请引入此依赖 ```java icu.funkye confine-client 1.0.0 ``` 使用方式: 注:使用confine-spring-boot-starter时可直接通过注解来等价与以下使用方法 ```java @RequestMapping("/test") @ResponseBody public String test(@ModelAttribute Test test) throws InterruptedException { try { //会通过此资源名找到对应的资源构造对象,自动进行判断当前是否需要限流 ConfineFilter.entry(资源名称,可以为类名+函数+入参来命名); // business return "ok"; }catch (ConfineException e) { //当抛出此异常的时候,就是触发限流,可自行编写failback逻辑 } } public void init(){ //默认根据tps限流,如果有填写限流rt,如rt为1000,那么就是1秒,1分钟内此资源被请求的平均rt高于此阈值则进行限流,若低于根据tps进行判断是否限流 RateLimiterFactory.put(资源名称,可以为类名+函数+入参来命名, 对此资源限制的tps, 限流rt); } ``` 入口限流使用示例: 注:此功能强依赖spring组件,当然你也可以通过使用api方式自己写入口限流策略,使用confine-spring-boot-starter时自动装配入口限流 ```java private static volatile ScheduledThreadPoolExecutor EXECUTOR; @Bean public ConfineFailHandle confineFailHandle() { //此熔断处理器可实现ConfineFailHandle接口自定义处理熔断时的逻辑 return new DefaultConfineFailHandle(); } @Bean public ConfineInterceptor confineInterceptor(ConfineFailHandle confineFailHandle) { ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("computeTps-pool-%d").build(); EXECUTOR = new ScheduledThreadPoolExecutor(1, threadFactory); ConfineInterceptor confineInterceptor = new ConfineInterceptor(confineFailHandle, 全局最大tps限制, 全局最大rt限制); // 每分钟通过cpuload变更当前最大tps,计算公式 默认最大tps*目前空闲率 EXECUTOR.scheduleAtFixedRate(() -> { int maxTps =最大tps; com.sun.management.OperatingSystemMXBean bean = (com.sun.management.OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean(); Double load = bean.getSystemCpuLoad(); ResourceWrapper resourceWrapper = RateLimiterFactory.put(DEFAULT_METHOD, maxTps); RateLimiter rateLimiter = resourceWrapper.getRateLimiter(); BigDecimal standard = new BigDecimal(100); BigDecimal loadRate = new BigDecimal(load.intValue() / 5); BigDecimal tps = new BigDecimal(maxTps); int currentTps = standard.subtract(loadRate).divide(standard).multiply(tps).intValue(); rateLimiter.setRate(currentTps); confineInterceptor.setGlobalMaxTps(currentTps); }, 0, 60, TimeUnit.SECONDS); return confineInterceptor; } ``` ``` //继承WebMvcConfigurationSupport,使入口限流生效 @Configuration public class HttpAutoConfiguration extends WebMvcConfigurationSupport { @Autowired ConfineInterceptor confineInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(confineInterceptor).addPathPatterns("/**"); } } ``` ## confine-spring-boot-starter使用教程 此组件拥有confine-client所有功能,并自动化装配上述所有功能 首先引入依赖: ```java icu.funkye confine-spring-boot-starter 1.0.0 ``` 首先在你的yaml或者properties中加入以下配置 ```properties confine.enable=true #是否开启自动装配,默认true,如果关闭使用方法跟confine-client无区别 confine.global-max-tps=1000 #全局最大tps,可自定义默认1000 confine.global-max-rt-threshold=1000 #全局最大rt,单位毫秒,默认1秒 confine.type=bucket #默认bucket实现,内置guava需要引入guava依赖,也可通过spi扩展使用其他限流实现 ``` 之后在需要限流的函数加入注解即可 ```java @RequestMapping("/test") @ResponseBody @ConfineLimiter(method=可不填,默认类名@函数名@参数@...拼接而成 ,tps = 最大tps, failBack = 触发限流后的处理器,可参考spring-cloud的failback配置, rt = 最大rt,1分钟内平均达到此rt后就限流) public String test(@ModelAttribute Test test) throws InterruptedException { return "ok"; } ``` 如果你的应用已经继承了WebMvcConfigurationSupport或WebMvcConfigurationSupport 那么需要仿照HttpAutoConfiguration类的做法,将ConfineInterceptor注册到你的拦截链路中,才能实现对入口处的全局限流 ## 动态更新限流阈值 通过shutter之类的配置中心,可自行订阅某个配置项,调用confine提供的接口来更新阈值 ```java //得到配置更新后,直接调用此接口即可 RateLimiterFactory.update(需要更新的资源名,最大tps,最大rt) ``` ## SPI扩展实现 可参考BucketLimiter类的实现,简略示例如下: ``` @LoadLevel(name = "填你的实现名即可,confine.type的值等于此值既会加载此实现") public class XXXXXLimiter extends AbstractLimiter { @Override public Limiter create(String resource, int tps, long seconds) { return this; } @Override public boolean tryAcquire(int permits, long timeout, TimeUnit unit) { } } ```