微服务整合sentinel

背景

提供服务给第三方,但是需要给的权限码进行限制,并且可动态配置,包括限流的接口,限流次数,限流日期,限流ip,限流时间

实现方式——sentinel

  1. 控制台(Dashboard):可以通过控制台进行限流,并通过配置实现(如果不通过配置,服务重启以后配置就没了),但是我当时测试了一下没成功,可能哪里没弄对,可参照官方文档(https://sentinelguard.io/zh-cn/docs/dynamic-rule-configuration.html)
  2. 核心库:使用提供的api进行限流控制(本文的处理方式中,提供服务的服务实例只有一个,在多个实例场景下应该会有问题)
    官方文档:https://sentinelguard.io/zh-cn/docs/quick-start.html

使用规则——热点规则

选择热点规则是因为,需要实现几秒调用一次,流量规则不好使
官网说明:
热点参数规则(ParamFlowRule)类似于流量控制规则(FlowRule):
在这里插入图片描述在这里插入图片描述

实现逻辑

1.将动态配置的限流数据存储到库中,并将规则放置到redis中,给一个热点规则修改的标识

redisService.setCacheObject("ParamFlowRuleFlag",true);
redisService.setCacheObject("ParamFlowRule",jsonString);

2.调用前进行限流处理

@Before("@annotation(requestLimit)")
public void doBefore(JoinPoint point, RequestLimiter requestLimit) throws Throwable {
	//如果规则为空或者标识为已修改则对规则进行更新
	if(CollUtil.isEmpty(ParamFlowRuleManager.getRules()) || (boolean)redisService.getCacheObject("ParamFlowRuleFlag")){
		updateParamFlowRule();
	}
    //获取请求
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
    //根据授权码进行限流
    if(request.getParameterMap().get("authorization_code")!=null){
    	String authCode = request.getParameterMap().get("authorization_code")[0];
    	//获取授权码信息
    	DataService dataService = XXXX; 
    	//未找到对应授权码
	    if(dataService == null){
	    	throw new RequestLimiterException(DataServiceStatus.UNAUTHORIZED);
	    }
	    //是否符合限制信息,ip时间等
	    ipAndTimeAndOpenLimit(dataService, request, point, requestLimit);
	    try {
	    	//一个授权码对应多个接口,所以限流resource命名为接口地址+授权码
	        entry = SphU.entry(request.getRequestURI() + authCode , EntryType.IN, 1, authCode );
	    }
	    // 如果被保护的资源被限流或者降级了,就会抛BlockException
	    catch (BlockException e) {
	        throw new RequestLimiterException(DataServiceStatus.FORBIDDEN);
	    } catch (IllegalArgumentException e2) {
	        Tracer.trace(e2);
	    } finally {
	        if (Objects.nonNull(entry)) {
	            // 退出entry
	            entry.exit(1,token);
	        }
	        ContextUtil.exit();
	    }
    }
}
    private void updateParamFlowRule() {
        String rules = redisService.getCacheObject("ParamFlowRule");
        if(StrUtil.isNotBlank(rules)){
            JSONArray rulesArray = JSON.parseArray(rules);
            List<ParamFlowRule> paramFlowRuleList = new ArrayList<>();
            for (int i = 0; i < rulesArray.size(); i++) {
                JSONObject jsonObject = (JSONObject) rulesArray.get(i);
                ParamFlowRule paramFlowRule = rulesArray.getObject(i, ParamFlowRule.class);
                //不单独写出来出问题了,具体什么问题有点忘记了
                paramFlowRule.setLimitApp("default");
                paramFlowRule.setParamIdx(jsonObject.getInteger("praramIdx"));
                paramFlowRuleList.add(paramFlowRule);
            }
            ParamFlowRuleManager.loadRules(paramFlowRuleList);
        }
        redisService.setCacheObject("ParamFlowRuleFlag",false);
    }
    public static class ParamFlowRule {
        @ApiModelProperty(value = "资源名称")
        private String resource;

        @ApiModelProperty(value = "单机阈值")
        private double count;

        @ApiModelProperty(value = "参数索引")
        private Integer praramIdx;

        @ApiModelProperty(value = "是否集群")
        private boolean clusterMode;

        @ApiModelProperty(value = "统计窗口")
        private double durationInSec;

        @ApiModelProperty(value = "参数外项")
        private List<ParamFlowItem> paramFlowItemList;
    }
    public static class ParamFlowItem {
        @ApiModelProperty(value = "参数值")
        private String object;

        @ApiModelProperty(value = "限流阈值")
        private double count;

        @ApiModelProperty(value = "参数类型")
        private String classType;
    }

注意

这个只是针对单个实例的服务,如果想在本文基础上稍加修改,可以考虑使用reids存储全局限流次数,但是不优雅

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值