范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

接口的屏蔽和限流很难么?Redis全搞定

  需求
  线上出现的问题是,一些非核心的查询数据业务,在请求超时或者错误的时候,用户会越查询,导致数据库cup飙升,拖垮核心的业务。
  领导让我做三件事,一是把这些接口做一个限流,这些限流参数是可配的,第二是这些接口可以设置开关,当发现问题时,可以手动关闭这些接口,不至于数据库压力过大影响核心业务的服务。第三是做接口的熔断,熔断设置可以配置。
  经过确定,前两个实现用redis来实现,第三个因为熔断讨论觉得比较复杂,决定采用我提出的用Hystrix,目前项目不能热加载生效配置中心的最新的配置,所以后期推荐使用Archaius,这些网上查到的,具体为啥不选其他的,原因就是其他的比较复杂,上手感觉这个最快。
  这篇文章说实现,其他问题不涉及,请多多指教。  思路
  接口的屏蔽:通过AOP实现,每次访问接口的时候,通过接口的Key值,在Redis取到接口设置开关值,如果打开继续,否在拒绝。接口限流也是基于AOP,根据接口的Key值,取到这个接口的限流值,表示多长时间,限流几次,每次访问都会请求加一,通过比较,如果超过限制再返回,否在继续。  代码
  AccessLimiter接口,主要有两类方法,是否开启限流,取Redis中的限流值。  package com.hcfc.auto.util.limit; import java.util.concurrent.TimeUnit; /**  * @创建人 peng.wang  * @描述 访问限制器  */ public interface AccessLimiter {     /**      * 检查指定的key是否收到访问限制      * @param key   限制接口的标识      * @param times 访问次数      * @param per   一段时间      * @param unit  时间单位      * @return      */     public boolean isLimited(String key, long times, long per, TimeUnit unit);       /**      * 移除访问限制      * @param key      */     public void refreshLimited(String key);       /**      * 接口是否打开      * @return      */     public boolean isStatus(String redisKey);       /**      * 接口的限流大小      * @param redisKeyTimes      * @return      */     public long getTimes(String redisKeyTimes);       /**      * 接口限流时间段      * @param redisKeyPer      * @return      */     public long getPer(String redisKeyPer);       /**      * 接口的限流时间单位      * @param redisKeyUnit      * @return      */     public TimeUnit getUnit(String redisKeyUnit);       /**      * 是否删除接口限流      * @param redisKeyIsRefresh      * @return      */     public boolean getIsRefresh(String redisKeyIsRefresh); }
  RedisAccessLimiter是AccessLimiter接口的实现类  package com.hcfc.auto.util.limit;   import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component;   import java.util.concurrent.TimeUnit;   /**  * @创建人 peng.wang  * @描述 基于Redis的实现  */ @Component public class RedisAccessLimiter implements AccessLimiter {       private static final Logger LOGGER = LoggerFactory.getLogger(RedisAccessLimiter.class);       @Autowired     private RedisTemplate redisTemplate;       @Override     public boolean isLimited(String key, long times, long per, TimeUnit unit) {         Long curTimes = redisTemplate.boundValueOps(key).increment(1);         LOGGER.info("curTimes {}",curTimes);         if(curTimes > times) {             LOGGER.debug("超频访问:[{}]",key);             return true;         } else {             if(curTimes == 1) {                 LOGGER.info(" set expire ");                 redisTemplate.boundValueOps(key).expire(per, unit);                 return false;             } else {                 return false;             }         }     }       @Override     public void refreshLimited(String key) {         redisTemplate.delete(key);     }       @Override     public boolean isStatus(String redisKey) {         try {             return (boolean)redisTemplate.opsForValue().get(redisKey+"IsOn");         }catch (Exception e){             LOGGER.info("redisKey is not find or type mismatch, key: ", redisKey);             return false;         }     }       @Override     public long getTimes(String redisKeyTimes) {         try {             return (long)redisTemplate.opsForValue().get(redisKeyTimes+"Times");         }catch (Exception e){             LOGGER.info("redisKey is not find or type mismatch, key: ", redisKeyTimes);             return 0;         }     }       @Override     public long getPer(String redisKeyPer) {         try {             return (long)redisTemplate.opsForValue().get(redisKeyPer+"Per");         }catch (Exception e){             LOGGER.info("redisKey is not find or type mismatch, key: ", redisKeyPer);             return 0;         }     }       @Override     public TimeUnit getUnit(String redisKeyUnit) {         try {             return (TimeUnit) redisTemplate.opsForValue().get(redisKeyUnit+"Unit");         }catch (Exception e){             LOGGER.info("redisKey is not find or type mismatch, key: ", redisKeyUnit);             return TimeUnit.SECONDS;         }     }       @Override     public boolean getIsRefresh(String redisKeyIsRefresh) {         try {             return (boolean)redisTemplate.opsForValue().get(redisKeyIsRefresh+"IsRefresh");         }catch (Exception e){             LOGGER.info("redisKey is not find or type mismatch, key: ", redisKeyIsRefresh);             return false;         }     } }
  Limit标签接口,实现注解方式  package com.hcfc.auto.util.limit; import java.lang.annotation.*; /**  * @创建人 peng.wang  * @描述  */ @Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Limit {}
  LimitAspect 切面的实现,实现接口屏蔽和限流的逻辑  package com.hcfc.auto.util.limit; import com.hcfc.auto.vo.response.ResponseDto; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RequestMapping; import java.lang.reflect.Method; import java.util.concurrent.TimeUnit;   /**  * @创建人 peng.wang  * @创建时间 2019/10/11  * @描述  */ @Slf4j @Aspect @Component public class LimitAspect {     private static final Logger logger = LoggerFactory.getLogger(LimitAspect.class);       @Autowired     private AccessLimiter limiter;       @Autowired     GenerateRedisKey generateRedisKey;       @Pointcut("@annotation(com.hcfc.auto.util.limit.Limit)")     public void limitPointcut() {}       @Around("limitPointcut()")     public Object doArround(ProceedingJoinPoint joinPoint) throws Throwable {         String redisKey = generateRedisKey.getMethodUrlConvertRedisKey(joinPoint);         long per = limiter.getPer(redisKey);         long times = limiter.getTimes(redisKey);         TimeUnit unit = limiter.getUnit(redisKey);         boolean isRefresh =limiter.getIsRefresh(redisKey);         boolean methodLimitStatus = limiter.isStatus(redisKey);         String bindingKey = genBindingKey(joinPoint);         if (methodLimitStatus) {             logger.info("method is closed, key: ", bindingKey);             return ResponseDto.fail("40007", "method is closed, key:"+bindingKey);             //throw new OverLimitException("method is closed, key: "+bindingKey);         }         if(bindingKey !=null){             boolean isLimited = limiter.isLimited(bindingKey, times, per, unit);             if(isLimited){                 logger.info("limit takes effect: {}", bindingKey);                 return ResponseDto.fail("40006", "access over limit, key: "+bindingKey);                 //throw new OverLimitException("access over limit, key: "+bindingKey);             }         }         Object result = null;         result = joinPoint.proceed();         if(bindingKey!=null && isRefresh) {             limiter.refreshLimited(bindingKey);             logger.info("limit refreshed: {}", bindingKey);         }         return result;     }       private String genBindingKey(ProceedingJoinPoint joinPoint){         try{             Method m = ((MethodSignature) joinPoint.getSignature()).getMethod();             return joinPoint.getTarget().getClass().getName() + "." + m.getName();         }catch (Throwable e){             return null;         }     } }
  还有一个不重要的RedisKey实现类GenerateRedisKey和一个错误封装类,目前没有使用到,使用项目中其他的错误封装类了。
  GenerateRedisKey  package com.hcfc.auto.util.limit; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RequestMapping; import java.lang.reflect.Method;   /**  * @创建人 peng.wang  * @描述  */ @Component public class GenerateRedisKey {     public String getMethodUrlConvertRedisKey(ProceedingJoinPoint joinPoint){         StringBuilder redisKey =new StringBuilder("");         Method m = ((MethodSignature)joinPoint.getSignature()).getMethod();         RequestMapping methodAnnotation = m.getAnnotation(RequestMapping.class);         if (methodAnnotation != null) {             String[] methodValue = methodAnnotation.value();             String dscUrl = diagonalLineToCamel(methodValue[0]);             return redisKey.append("RSK:").append("interfaceIsOpen:").append(dscUrl).toString();         }         return redisKey.toString();     }     private String diagonalLineToCamel(String param){         char UNDERLINE="/";         if (param==null||"".equals(param.trim())){             return "";         }         int len=param.length();         StringBuilder sb=new StringBuilder(len);         for (int i = 1; i < len; i++) {             char c=param.charAt(i);             if (c==UNDERLINE){                 if (++i
为何手机市场缩水严重?国内云科技ToDesk市场空间不敢想象1月29日,StrategyAnalytics的最新研究显示,2021年全年中国智能手机出货量为3。293亿部,同比下滑2。相对几年前移动智能设备的爆发式增长,目前手机市场已经进入堵不住了!力通通信破冰5G射频芯片,打压华为的后果显现点击关注,每天精彩不断!导读堵不住了!力通通信破冰5G射频芯片,打压华为的后果显现!对于现代科技领域的发展来说,半导体集成电路芯片无疑是十分重要的而华为公司的任正非早在2004年就IDC数据起争议,vivo第一没问题,荣耀排第几才是关键近一段时间全球各大调研公司的数据出现一个井喷期,其中大家最期待的是IDC的数据。因为一般情况之下行业都认为IDC的数据是最权威的,那么今天我们就来解读下IDC发布的2021年国内全FF自曝真实订单数据1。4万辆预订中仅300辆为付费预订澎湃新闻记者范佳来法拉第未来(FaradayFuture,以下简称FF)公布了FF91的付费预订数据300台。2月9日,FF相关负责人告诉澎湃新闻记者,FF的预订包含收费预订单和免孝道科技完成数千万元的首轮融资36氪获悉,安全玻璃盒孝道科技近日宣布完成数千万元的首轮融资。本轮融资由国内安全上市公司安恒信息主投。本轮融资后,公司将把资金将用于DevSecOps软件供应链安全及云原生应用安全全球芯片设计巨头或独立上市,券商称产业链设备有望超万亿台此前ARM芯片出货量高达250亿颗。今日重要性据经济观察网报道,当地时间周一,软银以660亿美元将英国芯片企业ARM出售给英伟达的交易以失败告终,另外软银开始寻求推动ARM独立上市喜报!极光(JG。US)荣获2021中国软件和信息服务业年度SaaS行业领军企业近日,2021第五届中国软件和信息服务业年度风云榜评选结果正式发布。中国领先的开发者服务提供商,极光(AuroraMobile,纳斯达克股票代码JG)凭借2021年在SaaS行业取好物推荐11期戴森都怕的吸尘器HiFi手机解码耳放减压啪啪牌包罗万象,各种好物科技指南帮你搜一搜,这期好物推荐为大家推荐三款不同类型的产品石头H7无线手持吸尘器,有些细节戴森都赶不上给手机音乐加上个小尾巴,音质提升更明显,山灵UA5小尾巴H25003000元段手机型推荐,有拍照够用性能有质感,看有适合的吗1。小米10s基本信息1。CPU。搭载高通骁龙870处理器(对比骁龙888,骁龙8)功耗发热要好点,2相机。一亿像素增加细节,3音质。哈曼卡顿调教对称式杨声器听着更爽,4充电。303000元内8256手机推荐?3000元内8256手机推荐?作为女生用,小米civi5G的价格为2469元钱,是2021年9月份上市的一款手机,就掌握的信息分析,这款新机应该是主打女性消费者市场,正所谓颜值在线你手机里有没有一张拍的特别有家乡韵味的照片?新兴农业讯猛发展,农村土地50被能人承包,统一管理机械化,无人机正在给小麦打药,三个人一天打上百亩,省心,省力,省倒伏,最省的是钱。土地有了生机,农民有了安居,后继有人,祖国昌盛!
Python入门题041比较两个列表的异同题目给出2个列表,1,2和2,3。输出他们的相同元素,和不同元素。结果分别为2和1,3pythonlist集合操作异或操作视频教程Python入门题041比较两个列表的异同代码1l我是真的不明白并且非常讨厌,现在的有些手机为什么用玻璃背壳,难道是自信的认为这样很帅?我曾经拿着iphone6,在高铁上电话打不出去,网也上不了。看着身边拿着华为的几位同事上网刷剧打电话都不耽误。我陷入了深深的思考中,装X却被同事取笑,说我买高档手机是拿来当装饰品的java提供的线程池java提供的线程池Java中默认实现好的线程池又有哪些呢?今天就给大家分享一下Java中默认实现了的线程池,废话不多说,我们就一起直接看一下吧。SingleThreadExecu为什么现在打滴滴越来越慢,好长时间打不到?为什么现在打滴滴越来越慢,好长时间打不到呢?我就是兼职跑滴滴的,下图为证,是我这几个月的流水我以滴滴司机的立场来谈谈原因,主要有以下几点司机没利润。由于平台派单规则,3公里以内都得为什么说光刻机难以制作?光刻机是芯片制造中必不可少的精密设备。其难度甚至超过航空发动机。首先是在技术上的难度光刻机可以说每个部件都是科技含量很高,步步困难重重。瓶颈主要集中在透镜掩膜版光源能量控制器等。下过几年计算机专业将烂大街呢,为什么?儿子今年大一计算机专业?计算机专业人才不会饱和,只是分工越来越细,要求越来越高,工资也会随着所从事的具体工作具体岗位而定。拿尖端的来说,华为够牛的吧,它还在不断地说需要芯片人才,需要创新人才。拿日常的来说三星GalaxyS22明年春节前后发布梦幻配置,苹果表示压力很大由于上一代三星GalaxyS21功耗发热问题饱受用户的吐槽,表示骁龙888发热非常严重,不少三星用户表示想等GalaxyS22,根据最新的消息称,三星GalaxyS22预计将在明年LCD永不为奴的背后究竟是什么前段时间,Redmi产品总监王腾在微博上与网友互动时的一句话引起了我的注意想要LCD旗舰可以考虑RedmiK30S至尊版,现在还有货。咋的,都2021年了还在推荐去年的旗舰呢?其实曝Windows11致使游戏性能暴跌,iPhone12让路新机跌至爱疯价Windows11正式发布,你更新了吗?如果您使用的是AMD锐龙处理器并且喜欢玩游戏,那么您应该等待。AMD和微软官方今天宣布了两个AMD处理器在Windows11系统上的兼容性问什么手机实用?过不了过久就是一年一度的双十一,手机厂商么每年都会发布自家双十一当天的从成绩,证明自己,国产手机现在基本都还停留在用出货量证明自己的层面,还没有哪一家开始用利润证明自己。往往在双十助听器只佩戴一个,跟人沟通时有障碍吗?如果你的听力有一只耳朵正常,那就可以戴一个,如果两个耳朵都有听力损失,那就必须要两个耳朵同时佩戴。双耳配戴可以提高语言的清晰度,听声音是立体声,假如你只带一个就好像用一只眼睛看世界