当前位置: 首页 > news >正文

java多租户_(九十二)java版spring cloud 多租户社交电子商务-gateway(实现限流)...

电子商务平台源码请加企鹅求求:三伍三六贰四柒二伍九。限流一般有两个实现方式,令牌桶和漏桶

令牌桶是初始化令牌(容器)的个数,通过拿走里边的令牌就能通过, 没有令牌不能报错,可以设置向容器中增加令牌的速度和最大个数

漏桶是向里边放入请求,当请求数量达到最大值后,丢弃,漏桶中的数据以一定速度流出,没有则不流出

令牌桶实现方式如下:

pom

com.github.vladimir-bukhtoyarov

bucket4j-core

4.0.0

创建下边类并且继承下边类package com.gla.datacenter.filter;

import io.github.bucket4j.Bandwidth;

import io.github.bucket4j.Bucket;

import io.github.bucket4j.Bucket4j;

import io.github.bucket4j.Refill;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.cloud.gateway.filter.GatewayFilter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;

import org.springframework.core.Ordered;

import org.springframework.http.HttpStatus;

import org.springframework.web.server.ServerWebExchange;

import reactor.core.publisher.Mono;

import java.time.Duration;

import java.util.Map;

import java.util.concurrent.ConcurrentHashMap;

/**

* @Description: 自定义过滤器进行限流

* @Author: zzh

* @Modified By:

* @Date: 2018/12/3 18:07

*/

public class GatewayRateLimitFilterByIP implements GatewayFilter, Ordered {

private final Logger log = LoggerFactory.getLogger(GatewayRateLimitFilterByIP.class);

/**

* 单机网关限流用一个ConcurrentHashMap来存储 bucket,

* 如果是分布式集群限流的话,可以采用 Redis等分布式解决方案

*/

private static final Map LOCAL_CACHE = new ConcurrentHashMap<>();

/**

* 桶的最大容量,即能装载 Token 的最大数量

*/

int capacity;

/**

* 每次 Token 补充量

*/

int refillTokens;

/**

*补充 Token 的时间间隔

*/

Duration refillDuration;

public GatewayRateLimitFilterByIP() {

}

/**

*

* @param capacity 即能装载 Token 的最大数量.

* @param refillTokens

* @param refillDuration

*/

public GatewayRateLimitFilterByIP(int capacity, int refillTokens, Duration refillDuration) {

this.capacity = capacity;

this.refillTokens = refillTokens;

this.refillDuration = refillDuration;

}

private Bucket createNewBucket() {

Refill refill = Refill.of(refillTokens, refillDuration);

Bandwidth limit = Bandwidth.classic(capacity, refill);

return Bucket4j.builder().addLimit(limit).build();

}

@Override

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();

//若ip不存在则创建一个Bucket(令牌桶)

Bucket bucket = LOCAL_CACHE.computeIfAbsent(ip, k -> createNewBucket());

log.info("IP:{} ,令牌通可用的Token数量:{} " ,ip,bucket.getAvailableTokens());

if (bucket.tryConsume(1)) {

return chain.filter(exchange);

} else {

//当可用的令牌书为0是,进行限流返回429状态码

log.error("IP:{} ,限制访问:{} " ,ip,bucket.getAvailableTokens());

exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);

return exchange.getResponse().setComplete();

}

}

@Override

public int getOrder() {

return -1000;

}

public static Map getLocalCache() {

return LOCAL_CACHE;

}

public int getCapacity() {

return capacity;

}

public void setCapacity(int capacity) {

this.capacity = capacity;

}

public int getRefillTokens() {

return refillTokens;

}

public void setRefillTokens(int refillTokens) {

this.refillTokens = refillTokens;

}

public Duration getRefillDuration() {

return refillDuration;

}

public void setRefillDuration(Duration refillDuration) {

this.refillDuration = refillDuration;

}

}

配置路由@Bean

public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {

//生成比当前时间早一个小时的UTC时间

ZonedDateTime minusTime = LocalDateTime.now().minusHours(1).atZone(ZoneId.systemDefault());

return builder.routes()

.route(r ->r.path("/demo/**")

//过滤器

.filters(f -> f.filter(new APIGatewayFilter())

.filter(new GatewayRateLimitFilterByIP(10,1, Duration.ofSeconds(1))))

.uri("http://192.168.26.113:8001/demo").order(0).id("demo_route"))

.route(r ->r.path("/test")

.uri("http://192.168.26.113/system/nav/login").id("jd_route")

)

build();

}

相关文章:

  • foxpro mysql_Foxpro数据库命令汇总
  • java generatedvalue_java – 在JPA @GeneratedValue列中手动指定主键的值
  • java io byte_JavaIO之字节流学习笔记
  • 八大排序方法java_八大排序java
  • java一个类怎么调用另一个类的变量_如何在一个类里调用到另一个类的变量的值...
  • java return后执行_java 问题 如果前一个return执行了 那么后面的一系列System.out.println 还会执行吗...
  • java持久层_java访问持久层技术的进化
  • java set encoding file_系统变量file.encoding对Java的运行影响有多大?(转)good
  • java运行一段时间变慢_tomcat 运行程序很慢 运行一段时间就报错: java.lang.OutOfMemoryError: PermGen space...
  • java的开发人员数量_Java开发人员最容易出现的几类错误
  • 字符串加减转数字java_剑指Offer解题报告(Java版)——字符串转换为数字 49
  • Java txt 下拉刷新_「小程序JAVA实战」小程序页面的上拉下拉刷新(50)
  • Java语言西安交大高起专_2018年西安交大网络学院高起专/本英语入学考试复习题...
  • php 生成不了zip文件怎么打开吗,PHP生成压缩包,不带根目录 | 学步园
  • php变量持有对象的引用,我对PHP变量引用、对象引用的理解
  • [译]CSS 居中(Center)方法大合集
  • 《Java8实战》-第四章读书笔记(引入流Stream)
  • 【347天】每日项目总结系列085(2018.01.18)
  • 08.Android之View事件问题
  • React-Native - 收藏集 - 掘金
  • Spring-boot 启动时碰到的错误
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • Windows Containers 大冒险: 容器网络
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 前端面试之CSS3新特性
  • 驱动程序原理
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 学习ES6 变量的解构赋值
  • 带你开发类似Pokemon Go的AR游戏
  • ​ssh免密码登录设置及问题总结
  • !!Dom4j 学习笔记
  • #、%和$符号在OGNL表达式中经常出现
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • $ git push -u origin master 推送到远程库出错
  • $GOPATH/go.mod exists but should not goland
  • (¥1011)-(一千零一拾一元整)输出
  • (C语言)fread与fwrite详解
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (SpringBoot)第七章:SpringBoot日志文件
  • (附源码)springboot美食分享系统 毕业设计 612231
  • (机器学习-深度学习快速入门)第三章机器学习-第二节:机器学习模型之线性回归
  • (亲测)设​置​m​y​e​c​l​i​p​s​e​打​开​默​认​工​作​空​间...
  • (三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (算法)前K大的和
  • (一)80c52学习之旅-起始篇
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .NET 线程 Thread 进程 Process、线程池 pool、Invoke、begininvoke、异步回调
  • .NET 中 GetHashCode 的哈希值有多大概率会相同(哈希碰撞)
  • .net安装_还在用第三方安装.NET?Win10自带.NET3.5安装
  • .NET中使用Protobuffer 实现序列化和反序列化
  • .sh 的运行
  • .skip() 和 .only() 的使用